- August Week 1
- 24.07.29 - 1395. Count Number of Teams
- 24.07.30 - 1653. Minimum Deletions to Make String Balanced
- 24.07.31 - 1105. Filling Bookcase Shelves
- 24.08.01 - 2678. Number of Senior Citizens
- 24.08.02 - 2134. Minimum Swaps to Group All 1's Together II
- 24.08.03 - 1460. Make Two Arrays Equal by Reversing Subarrays
- 24.08.04 - 1508. Range Sum of Sorted Subarray Sums
// 2783ms, 11.52MB
class Solution {
public:
int numTeams(vector<int>& rating) {
const int SIZE = static_cast<int>(rating.size());
int answer{};
for (int i{}; i < SIZE - 2; ++i) {
for (int j = i + 1; j < SIZE - 1; ++j) {
for (int k = j + 1; k < SIZE; ++k) {
if ((rating[i] < rating[j] && rating[j] < rating[k]) ||
(rating[i] > rating[j] && rating[j] > rating[k])) {
++answer;
}
}
}
}
return answer;
}
};Since I couldn't access the page directly, I'll provide an outline on how to solve the "Count Number of Teams" problem typically found on LeetCode.
You are given an array of integers representing the rating of soldiers. You need to count the number of teams of 3 soldiers where either:
- The ratings are in increasing order (i < j < k).
- The ratings are in decreasing order (i > j > k).
We can solve this problem using a nested loop approach to count valid teams. Here's a step-by-step solution in C++:
- Initialization: We need an array
ratingand its lengthn. - Nested Loops: Use three nested loops to check each combination of three soldiers.
- Condition Checking: Check for increasing or decreasing order.
- Counting Teams: Increment a counter whenever a valid team is found.
class Solution {
public:
int numTeams(vector<int>& rating) {
int n = rating.size();
int count = 0;
// Iterate over all possible triplets (i, j, k)
for (int i = 0; i < n - 2; ++i) {
for (int j = i + 1; j < n - 1; ++j) {
for (int k = j + 1; k < n; ++k) {
if ((rating[i] < rating[j] && rating[j] < rating[k]) ||
(rating[i] > rating[j] && rating[j] > rating[k])) {
++count;
}
}
}
}
return count;
}
};- Triple Loop: The loops run through all combinations of indices (i, j, k) with i < j < k.
- Condition Check: The condition checks if the ratings are in either strictly increasing or decreasing order.
- Count Increment: The counter
countis incremented whenever a valid team is found.
To solve the "Count Number of Teams" problem using a more efficient approach with dynamic programming, we can use the following strategy:
- Count of Smaller and Larger Elements: For each soldier, count the number of soldiers with a lower rating before it and the number of soldiers with a higher rating after it. Similarly, count the number of soldiers with a higher rating before it and the number of soldiers with a lower rating after it.
- Count Valid Teams: Using these counts, we can determine the number of valid increasing and decreasing teams.
class Solution {
public:
int numTeams(vector<int>& rating) {
int n = rating.size();
int result = 0;
for (int j = 0; j < n; ++j) {
int less_left = 0, greater_left = 0;
int less_right = 0, greater_right = 0;
// Count elements smaller/greater than rating[j] to the left of j
for (int i = 0; i < j; ++i) {
if (rating[i] < rating[j]) {
++less_left;
} else if (rating[i] > rating[j]) {
++greater_left;
}
}
// Count elements smaller/greater than rating[j] to the right of j
for (int k = j + 1; k < n; ++k) {
if (rating[k] < rating[j]) {
++less_right;
} else if (rating[k] > rating[j]) {
++greater_right;
}
}
// Calculate the number of valid teams with j as the middle soldier
result += less_left * greater_right + greater_left * less_right;
}
return result;
}
};- Initialization: Initialize counters for elements smaller and greater than the current element both to the left and right.
- Loop Through Array: For each element in the array, count elements smaller and greater to its left and right.
- Count Valid Teams: The number of valid teams with the current element as the middle soldier is the sum of products of valid left and right combinations.
This approach reduces the time complexity to O(n^2), which is more efficient than the O(n^3) solution but still manageable for moderately sized arrays. For very large arrays, further optimizations may be necessary.
To solve the "Count Number of Teams" problem using prefix/suffix arrays, we can optimize the counting of elements that are smaller or larger than the current element. Here's how:
- Prefix Arrays: Use prefix arrays to count the number of elements smaller or larger than the current element up to that index.
- Suffix Arrays: Use suffix arrays to count the number of elements smaller or larger than the current element from that index to the end.
- Counting Valid Teams: Use these counts to determine the number of valid teams.
Here's a C++ solution using prefix and suffix arrays:
class Solution {
public:
int numTeams(vector<int>& rating) {
int n = rating.size();
vector<int> lessLeft(n, 0), greaterLeft(n, 0);
vector<int> lessRight(n, 0), greaterRight(n, 0);
// Fill the prefix arrays
for (int i = 1; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (rating[j] < rating[i]) {
++lessLeft[i];
} else if (rating[j] > rating[i]) {
++greaterLeft[i];
}
}
}
// Fill the suffix arrays
for (int i = n - 2; i >= 0; --i) {
for (int j = n - 1; j > i; --j) {
if (rating[j] < rating[i]) {
++lessRight[i];
} else if (rating[j] > rating[i]) {
++greaterRight[i];
}
}
}
int count = 0;
// Count the number of valid teams
for (int i = 0; i < n; ++i) {
count += lessLeft[i] * greaterRight[i] + greaterLeft[i] * lessRight[i];
}
return count;
}
};- Prefix Arrays:
lessLeft[i]andgreaterLeft[i]store the count of elements smaller and greater thanrating[i]to the left ofi. - Suffix Arrays:
lessRight[i]andgreaterRight[i]store the count of elements smaller and greater thanrating[i]to the right ofi. - Counting Teams: For each index
i, the number of valid teams is calculated using the counts from prefix and suffix arrays:lessLeft[i] * greaterRight[i]gives the count of teams whererating[i]is the middle element in an increasing sequence.greaterLeft[i] * lessRight[i]gives the count of teams whererating[i]is the middle element in a decreasing sequence.
This approach is more efficient than the brute-force solution, reducing the overall complexity to O(n^2). For further improvements, more advanced data structures like Fenwick Trees or Segment Trees could be used to reduce the complexity to O(n log n).
// 82ms, 23.68MB
class Solution {
public:
int minimumDeletions(string s) {
int totA{};
for(auto c : s) {
if(c == 'a') ++totA;
}
int answer = totA;
int cntA{}, cntB{};
for(auto c : s) {
if(c == 'a') ++cntA;
else if(c == 'b') ++cntB;
answer = min(answer, cntB + totA - cntA);
}
return answer;
}
};To solve the problem of finding the minimum number of deletions required to make a string balanced, we need to ensure that all 'a's in the string appear before all 'b's. This problem can be approached using dynamic programming or a more optimized two-pass strategy with prefix sums.
Here’s the detailed approach:
-
Prefix Calculation:
- Calculate the number of 'b's to the left of each position (prefix_b).
- Calculate the number of 'a's to the right of each position (suffix_a).
-
Compute Minimum Deletions:
- For each position, compute the total deletions needed to make the string balanced if the split occurs at that position.
- Track the minimum deletions across all possible split positions.
Here’s the implementation:
// 87ms, 53.17MB
class Solution {
public:
int minimumDeletions(string s) {
int n = s.size();
std::vector<int> prefix_b(n + 1, 0); // number of 'b's to the left of i (exclusive)
std::vector<int> suffix_a(n + 1, 0); // number of 'a's to the right of i (exclusive)
// Fill prefix_b array
for (int i = 1; i <= n; ++i) {
prefix_b[i] = prefix_b[i - 1] + (s[i - 1] == 'b' ? 1 : 0);
}
// Fill suffix_a array
for (int i = n - 1; i >= 0; --i) {
suffix_a[i] = suffix_a[i + 1] + (s[i] == 'a' ? 1 : 0);
}
// Compute minimum deletions
int min_deletions = n; // Initialize with maximum possible deletions (all characters)
for (int i = 0; i <= n; ++i) {
min_deletions = std::min(min_deletions, prefix_b[i] + suffix_a[i]);
}
return min_deletions;
}
};-
Prefix Array Calculation:
prefix_b[i]counts the number of 'b's in the substrings[0...i-1].- Iterate through the string and populate
prefix_b.
-
Suffix Array Calculation:
suffix_a[i]counts the number of 'a's in the substrings[i...n-1].- Iterate through the string in reverse and populate
suffix_a.
-
Finding the Minimum Deletions:
- For each possible split point
i, compute the sum ofprefix_b[i](deletions needed for 'b's beforei) andsuffix_a[i](deletions needed for 'a's afteri). - Track the minimum of these sums.
- For each possible split point
- Time Complexity: O(n), where n is the length of the string. This is because we iterate through the string a constant number of times.
- Space Complexity: O(n) for the prefix and suffix arrays.
This approach ensures that the solution is efficient and optimal for the given problem constraints.
해결 못 했습니다.. ㅠㅠ (아이디어가 안 떠 오름.)
To solve the problem of "Filling Bookcase Shelves" from LeetCode, you need to approach it using dynamic programming (DP). The problem can be summarized as arranging a set of books on shelves such that the total height of the shelves is minimized. Each book has a width and a height, and each shelf has a maximum width limit.
Here's a step-by-step solution:
-
Understand the Problem:
- You have an array of books, where each book is represented by its width and height.
- You need to arrange these books on shelves with a given maximum width.
- The goal is to minimize the total height of the shelves.
-
Define the DP State:
- Let
dp[i]represent the minimum height needed to place the firstibooks.
- Let
-
DP Transition:
- For each book
i, you decide whether to place it on a new shelf or add it to the current shelf if it fits within the width constraint. - You update the
dparray by considering the height of the current shelf and the books that fit on it.
- For each book
-
Base Case:
dp[0] = 0, which means no height is needed for zero books.
Here is the complete code for solving the problem using dynamic programming:
// 3ms, 11.11MB
class Solution {
public:
int minHeightShelves(vector<vector<int>>& books, int shelf_width) {
int n = books.size();
vector<int> dp(n + 1, INT_MAX);
dp[0] = 0;
for (int i = 1; i <= n; ++i) {
int width = 0, height = 0;
for (int j = i; j > 0; --j) {
width += books[j-1][0];
if (width > shelf_width) break;
height = max(height, books[j-1][1]);
dp[i] = min(dp[i], dp[j-1] + height);
}
}
return dp[n];
}
};- Initialization:
dpvector is initialized toINT_MAXexceptdp[0]which is0because no height is needed for zero books.
- Outer Loop:
- Iterate over each book
ifrom1ton.
- Iterate over each book
- Inner Loop:
- Check the books from the current book
ibackwards to see how many can fit on the current shelf without exceeding theshelf_width. - Update the
widthandheightof the current shelf. - Update
dp[i]to the minimum value between its current value and the height of the shelf plus the height from the previous books (dp[j-1] + height).
- Check the books from the current book
- Return the Result:
- The final result will be in
dp[n], which represents the minimum height to arrange allnbooks.
- The final result will be in
- Ensure you understand the dynamic programming state transition.
- Carefully handle the conditions within the inner loop to avoid exceeding the shelf width.
- The solution leverages the fact that placing a book on a new shelf vs. the current shelf is mutually exclusive and must be evaluated at each step.
Note
예제에서 첫 책을 쌓고, 두 번째 세 번째 책을 쌓을 때 점화식을 생각 못 했다.
두 번째 책까지만 쌓으면 최소 높이는 3이고 min 값을 거기서 갱신해버리면 이후 답이 제대로 나오지 않는다. 이럴 때는 거꾸로 볼 수 있다는 아이디어가 있다는 것을 깨달았다. (무조건 정방향으로 볼 필요는 없다.)
// 10ms, 17.6MB
class Solution {
public:
int countSeniors(vector<string>& details) {
// 10 characters => phone number
// gender(M, F)
// 2 characters => age
// 2 characters => seat
// # of passengers who are strictly more than 60 years old.
int answer{};
for(string& detail : details) {
if(stoi(detail.substr(11, 2)) > 60) ++answer;
}
return answer;
}
};Certainly! The problem on LeetCode you are referring to is about counting the number of senior citizens in a given list of personal details. Here's a step-by-step solution in C++ to solve this problem.
The problem description states:
You are given a 0-indexed array of strings details. Each element of details is a string, where:
- The first 2 characters represent the country code.
- The next 8 characters represent the phone number.
- The next 2 characters represent the age.
- The last 1 character represents the gender.
Return the number of strings in details that represent senior citizens.
Here's how we can approach solving this problem in C++:
- Parse each string to extract the age.
- Convert the extracted age to an integer.
- Check if the age is greater than or equal to 60.
- Count how many such strings exist in the array.
Here's the C++ code to implement this logic:
class Solution {
public:
int countSeniors(std::vector<std::string>& details) {
int count = 0;
for (const std::string& detail : details) {
// The age is located at indices 10 and 11 in the string
int age = std::stoi(detail.substr(10, 2));
if (age >= 60) {
count++;
}
}
return count;
}
};- Loop through each string in the
detailsvector: We use a range-based for loop to iterate through each string. - Extract the age:
detail.substr(10, 2)extracts the substring starting at index 10 with a length of 2, which corresponds to the age in the given format. - Convert the substring to an integer:
std::stoiconverts the extracted substring to an integer. - Check if the age is 60 or more: If the age is greater than or equal to 60, increment the count.
- Return the count: After checking all strings, return the final count of senior citizens.
This code correctly solves the problem as described. You can test it with various inputs to ensure it works for all edge cases as well.
I think age starts with index 11, isn't it?
You're right! The age starts at index 11. Here is the corrected code with the proper index for extracting the age:
class Solution {
public:
int countSeniors(std::vector<std::string>& details) {
int count = 0;
for (const std::string& detail : details) {
// The age is located at indices 11 and 12 in the string
int age = std::stoi(detail.substr(11, 2));
if (age >= 60) {
count++;
}
}
return count;
}
};- Loop through each string in the
detailsvector: We use a range-based for loop to iterate through each string. - Extract the age:
detail.substr(11, 2)extracts the substring starting at index 11 with a length of 2, which corresponds to the age in the given format. - Convert the substring to an integer:
std::stoiconverts the extracted substring to an integer. - Check if the age is 60 or more: If the age is greater than or equal to 60, increment the count.
- Return the count: After checking all strings, return the final count of senior citizens.
This corrected code ensures that we are extracting the age from the correct indices in the string.
strictly more than 60 years old.it doesn't contains 60..!
Thank you for the clarification. If the requirement is to count only those who are strictly more than 60 years old (i.e., age > 60), we need to adjust the condition in our check. Here is the corrected code:
// 13ms, 17.56MB
class Solution {
public:
int countSeniors(const std::vector<std::string>& details) {
int count = 0;
for (const std::string& detail : details) {
// The age is located at indices 11 and 12 in the string
int age = std::stoi(detail.substr(11, 2));
if (age > 60) {
count++;
}
}
return count;
}
};- Extract the age: The age is extracted using
detail.substr(11, 2)which gets the substring starting at index 11 with a length of 2 characters. - Convert the substring to an integer: The extracted age substring is converted to an integer using
std::stoi. - Check if the age is strictly more than 60: The condition
if (age > 60)is used to count only those ages that are strictly greater than 60. - Return the count: After iterating through all strings, the final count of senior citizens is returned.
This code correctly solves the problem with the updated condition that only counts those who are strictly older than 60.
약간의 오류
$\rightarrow$ 수정..중간에 11번째가 아니라 13번째 아니야? 라고 물었는데 속지 않음.
아이디어가 떠오르지 않아 힌트 참고 했음..
- Notice that the number of 1’s to be grouped together is fixed. It is the number of 1's the whole array has.
- Call this number total. We should then check for every subarray of size total (possibly wrapped around), how many swaps are required to have the subarray be all 1’s.
- The number of swaps required is the number of 0’s in the subarray.
- To eliminate the circular property of the array, we can append the original array to itself. Then, we check each subarray of length total.
- How do we avoid recounting the number of 0’s in the subarray each time? The Sliding Window technique can help.
// 71ms, 83.06MB
class Solution {
public:
int minSwaps(std::vector<int>& nums) {
const int SIZE = static_cast<int>(nums.size());
// 총 1의 개수 카운팅
int oneTot{};
for(int& num : nums) {
if(num == 1) ++oneTot;
}
int oneCntInWindow{}, maxOneCntInWindow{};
// 초기 window 구성
for (int i = 0; i < oneTot; ++i) {
if (nums[i] == 1) {
oneCntInWindow++;
}
}
maxOneCntInWindow = oneCntInWindow;
for (int i = oneTot; i < SIZE + oneTot; ++i) {
if (nums[i % SIZE] == 1) {
oneCntInWindow++;
}
if (nums[(i - oneTot) % SIZE] == 1) {
oneCntInWindow--;
}
maxOneCntInWindow = std::max(maxOneCntInWindow, oneCntInWindow);
}
return oneTot - maxOneCntInWindow;
}
};Certainly! Let's solve the problem of finding the minimum number of swaps to group all 1s together in a circular array, as described in the LeetCode problem Minimum Swaps to Group All 1s Together II.
Given a circular binary array, you need to find the minimum number of swaps required to group all the 1s together. The array can be rotated, making the circular nature a crucial aspect of the problem.
- Count the total number of 1s (
totalOnes) in the array: This helps determine the window size that we need to use to group the 1s together. - Create a double-length version of the array: This accounts for the circular nature by allowing the window to wrap around seamlessly.
- Use a sliding window technique: Count the number of 1s in the current window of size
totalOnes. The goal is to maximize the number of 1s in any such window. - Calculate the minimum swaps: The minimum number of swaps needed to bring all 1s together in the best window is determined by the difference between
totalOnesand the maximum number of 1s found in any window.
Here's the detailed implementation:
// 76ms, 93.54MB
class Solution {
public:
int minSwaps(std::vector<int>& nums) {
int n = nums.size();
// Count total number of 1s in the array
int totalOnes = std::count(nums.begin(), nums.end(), 1);
// Create a double-length array to handle circular nature
std::vector<int> doubleNums(nums.begin(), nums.end());
doubleNums.insert(doubleNums.end(), nums.begin(), nums.end());
// Use sliding window to find maximum number of 1s in any window of size `totalOnes`
int maxOnesInWindow = 0;
int currentOnesInWindow = 0;
for (int i = 0; i < totalOnes; ++i) {
if (doubleNums[i] == 1) {
currentOnesInWindow++;
}
}
maxOnesInWindow = currentOnesInWindow;
for (int i = totalOnes; i < doubleNums.size(); ++i) {
if (doubleNums[i] == 1) {
currentOnesInWindow++;
}
if (doubleNums[i - totalOnes] == 1) {
currentOnesInWindow--;
}
maxOnesInWindow = std::max(maxOnesInWindow, currentOnesInWindow);
}
// The minimum number of swaps needed
return totalOnes - maxOnesInWindow;
}
};- Counting 1s: We first count the total number of 1s in the array (
totalOnes). This will be the size of the window we need to consider for grouping the 1s together. - Handling Circular Nature: By duplicating the array (
doubleNums), we can handle the circular nature. This way, sliding windows can naturally wrap around the end of the array. - Sliding Window Technique:
- Initialize a window of size
totalOnesand count the number of 1s in this window. - Slide the window one position at a time, updating the count of 1s by adding the new element and removing the old element that is no longer in the window.
- Track the maximum number of 1s found in any window of size
totalOnes.
- Initialize a window of size
- Calculating Minimum Swaps: The minimum number of swaps required is
totalOnes - maxOnesInWindow.
This solution ensures an efficient and effective way to determine the minimum swaps needed, with a time complexity of
// 6ms, 17.8MB
class Solution {
public:
bool canBeEqual(vector<int>& target, vector<int>& arr) {
// 1 <= target[i], arr[i] <= 1000
vector dat(1001, 0);
for(int& t : target) dat[t]++;
for(int& a : arr) {
if(dat[a] > 0) {
dat[a]--;
}
else {
return false;
}
}
return true;
}
};Sure! Let's go through the problem "Make Two Arrays Equal by Reversing Subarrays" on LeetCode.
You are given two integer arrays of equal length target and arr. In one step, you can select any non-empty subarray of arr and reverse it. You need to determine if it's possible to make arr equal to target by performing any number of such reversals.
To determine if we can make arr equal to target by reversing subarrays, let's consider the following:
- Permutation Check: Any subarray reversal does not change the elements of the array but only their order. Therefore, for
arrto be transformed intotarget, both arrays must contain the same elements with the same frequencies. In other words,arrmust be a permutation oftarget.
If arr is a permutation of target, then it's always possible to sort arr to match target using a series of reversals. This is because any sequence of reversals can rearrange the elements to match any permutation.
We can solve this problem efficiently by using sorting or a hashmap to check if arr is a permutation of target.
Here is a Python implementation using sorting:
// 4ms, 17.58MB
class Solution {
public:
bool canBeEqual(vector<int>& target, vector<int>& arr) {
sort(target.begin(), target.end());
sort(arr.begin(), arr.end());
return target == arr;
}
};이게 되네?..
Alternatively, here is the implementation using hash maps to count the frequency of each element:
// 10ms, 19.52MB
class Solution {
public:
bool canBeEqual(vector<int>& target, vector<int>& arr) {
unordered_map<int, int> countMap;
for (int num : target) {
countMap[num]++;
}
for (int num : arr) {
if (countMap.find(num) == countMap.end() || countMap[num] == 0) {
return false;
}
countMap[num]--;
}
return true;
}
};- Sorting Method: We sort both
targetandarrarrays. If they are identical after sorting, thenarrcan be transformed intotarget. - Hashmap Method: We use a hashmap to count the frequencies of elements in
target. We then decrement the count for each element inarr. If any element inarreither doesn't exist in the hashmap or its count goes below zero, thenarrcannot be transformed intotarget.
Both approaches have a time complexity of
If you have any further questions or need additional clarifications, feel free to ask!
// 92ms, 27.2MB
class Solution {
public:
const int MOD = 1'000'000'007;
int rangeSum(vector<int>& nums, int n, int left, int right) {
vector<int> sums;
// 합을 다 안 구하고 하는 방법이 있나?
// the sum of all non-empty continuous subarrays
for(int i{};i<n;++i) {
int sum{};
for(int j{i};j<n;++j) {
sum += nums[j];
sums.push_back(sum);
}
}
sort(begin(sums), end(sums));
// Since the answer can be a huge number return it modulo 109 + 7. (이런 게 있더라..)
int answer{};
// 합쳐주는 함수가 생각이 안 난다
for(int i{left-1};i<right;++i) {
answer += sums[i];
answer %= MOD;
}
return answer;
}
};The problem "Range Sum of Sorted Subarray Sums" can be broken down into several steps. Here is a detailed explanation of how to approach it:
Given an integer array nums and two integers n and left and right, your task is to find the sum of the subarray sums that lie between the left-th and right-th smallest sums of all possible subarrays. The answer should be returned modulo (10^9 + 7).
-
Generate All Subarray Sums:
- First, generate all possible subarrays of the given array.
- Compute the sum of each subarray.
-
Sort the Sums:
- Sort the array of subarray sums.
-
Calculate the Required Sum:
- Find the sum of elements between the indices
left-1andright-1in the sorted array of subarray sums. - Return this sum modulo (10^9 + 7).
- Find the sum of elements between the indices
Let's implement this step-by-step in C++:
// 90ms, 27.2MB
class Solution {
public:
int rangeSum(std::vector<int>& nums, int n, int left, int right) {
constexpr int MOD = 1e9 + 7;
std::vector<int> subarraySums;
// Generate all subarray sums
for (int i = 0; i < n; ++i) {
int sum = 0;
for (int j = i; j < n; ++j) {
sum += nums[j];
subarraySums.push_back(sum);
}
}
// Sort the subarray sums
std::sort(subarraySums.begin(), subarraySums.end());
// Calculate the sum from left-1 to right-1
long long result = 0;
for (int i = left - 1; i < right; ++i) {
result = (result + subarraySums[i]) % MOD;
}
return static_cast<int>(result);
}
};-
Generate All Subarray Sums:
- We use two nested loops to generate the sum of all subarrays.
- For each starting point
i, we calculate the sum of subarrays ending at each pointj(i <= j < n). - These sums are stored in the
subarraySumsvector.
-
Sort the Sums:
- We use the
sortfunction to sort the vectorsubarraySums.
- We use the
-
Calculate the Sum for the Given Range:
- We iterate over the
subarraySumsvector from indexleft-1toright-1and compute the sum modulo (10^9 + 7).
- We iterate over the
-
Time Complexity: Generating all subarray sums takes
$O(n^2)$ . Sorting the sums takes$O((n^2) \log (n^2))$ . Thus, the overall time complexity is$O(n^2 \log n)$ . -
Space Complexity: We store all subarray sums, which requires
$O(n^2)$ space.
This approach ensures that we efficiently compute the required range sum of sorted subarray sums.
python으로 된 완전 최적화한 코드가 있던데... C++로 바꿔달라고 요청
Certainly! Here's the given Python code converted to C++:
// 0ms, 10MB
class Solution {
public:
int rangeSum(std::vector<int>& nums, int n, int left, int right) {
constexpr int MOD = 1e9 + 7;
auto count_and_sum = [&](const std::vector<int>& nums, int target) {
int count = 0;
long long current_sum = 0, total_sum = 0, window_sum = 0;
int i = 0;
for (int j = 0; j < n; ++j) {
current_sum += nums[j];
window_sum += static_cast<long long>(nums[j]) * (j - i + 1);
while (current_sum > target) {
window_sum -= current_sum;
current_sum -= nums[i];
++i;
}
count += j - i + 1;
total_sum += window_sum;
}
return std::make_pair(count, total_sum);
};
auto sum_of_first_k = [&](const std::vector<int>& nums, int k) {
int min_sum = *std::min_element(nums.begin(), nums.end());
int max_sum = std::accumulate(nums.begin(), nums.end(), 0);
int left = min_sum, right = max_sum;
while (left <= right) {
int mid = left + (right - left) / 2;
if (count_and_sum(nums, mid).first >= k) {
right = mid - 1;
} else {
left = mid + 1;
}
}
auto [count, total_sum] = count_and_sum(nums, left);
// There can be more subarrays with the same sum of left.
return total_sum - static_cast<long long>(left) * (count - k);
};
long long result = (sum_of_first_k(nums, right) - sum_of_first_k(nums, left - 1)) % MOD;
// Ensure non-negative result
return (result + MOD) % MOD;
}
};-
Helper Function
count_and_sum:- This function calculates the number of subarrays whose sum is less than or equal to a given target and the total sum of such subarrays.
- It uses a sliding window technique to maintain the sum of subarrays.
-
Helper Function
sum_of_first_k:- This function uses binary search to find the smallest subarray sum that has at least
ksubarrays. - It calls
count_and_sumto determine the number of subarrays and their sum for a given target sum. - Adjusts the result to handle potential duplicates and ensure we get the sum of exactly the first
ksmallest subarray sums.
- This function uses binary search to find the smallest subarray sum that has at least
-
Main Function
rangeSum:- This function calls
sum_of_first_kto get the sum of subarrays for the specified range (lefttoright). - Ensures the result is non-negative by taking it modulo (10^9 + 7).
- This function calls
- The use of lambda functions in C++ (
[&]captures variables by reference) allows for defining helper functions within the main function scope, similar to Python's nested functions. - The
autokeyword is used for type inference, simplifying the code when the exact type is complex or verbose. std::make_pairand structured bindings (auto [count, total_sum]) are used for returning and unpacking multiple values from the helper functions.
내 스타일대로 변경~
class Solution {
public:
int rangeSum(std::vector<int>& nums, int n, int left, int right) {
using ll = long long;
constexpr int MOD = 1e9 + 7;
// cnt -> The number of subarrays whose sum is less than or equal to a given target.
// totalSum -> The total sum of these subarrays.
auto countAndSum = [&](const std::vector<int>& nums, int target) {
int cnt{}, i{};
ll currSum{}, totalSum{}, windowSum{};
// currSum: The sum of the current sliding window.
// windowSum: The sum of all subarrays ending at j that start from i to j.
for (int j{}; j < n; ++j) {
currSum += nums[j];
windowSum += static_cast<ll>(nums[j]) * (j - i + 1);
while (currSum > target) {
// eliminate first element
windowSum -= currSum;
currSum -= nums[i];
++i;
}
cnt += j - i + 1;
totalSum += windowSum;
}
return std::make_pair(cnt, totalSum);
};
auto sumOfFirstK = [&](const std::vector<int>& nums, int k) {
int min_sum = *std::min_element(begin(nums), end(nums));
int max_sum = std::accumulate(begin(nums), end(nums), 0);
int left = min_sum, right = max_sum;
while (left <= right) {
int mid = left + (right - left) / 2;
if (countAndSum(nums, mid).first >= k) { // more than k
right = mid - 1;
}
else {
left = mid + 1;
}
}
auto[cnt, totalSum] = countAndSum(nums, left);
// There can be more subarrays with the same sum of left.
return totalSum - static_cast<ll>(left) * (cnt - k);
};
ll result = (sumOfFirstK(nums, right) - sumOfFirstK(nums, left - 1)) % MOD;
// Ensure non-negative result
return (result + MOD) % MOD;
}
};