Skip to content

Commit 0a0b236

Browse files
Update searching.md
1 parent 13b4bf1 commit 0a0b236

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

‎searching.md‎

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,58 @@ Let us consider the problem of calculating the number of paths in an n x n grid
172172

173173
Meet in the middle is a technique where the search space is divided into two parts of about equal size. A separate search is performed for both of the parts, and finally the results of the searches are combined.
174174

175-
For example, suppose that the list is \[2,4,5,9\] and x = 15. First, we divide the list into A = \[2,4\] and B = \[5,9\]. After this, we create lists SA = \[0,2,4,6\] and SB = \[0,5,9,14\]. \(SA is total subset sum possible in A\) Next we can find original problem solution by using hashmap SA\[i\] + SA\[j\] = targ.
175+
### [Partition Array Into Two Arrays to Minimize Sum Difference](https://leetcode.com/problems/partition-array-into-two-arrays-to-minimize-sum-difference/description/)
176+
177+
```cpp
178+
/** Here naive solution was to get all possible subsets through bitmanipulation 2^(2n) for the cases where popcount is n get the sum.
179+
However total time complexity of 2^2n is 2^30 will give TLE.
180+
181+
Solution use meet in middle approach, divide the array in two part [0, n/2 - 1] [n/2, n-1]
182+
Now, find all subset which will be 2*2^n i.e. 2^16 which is within limit. Grouping those subsets in terms of how many elements taken.
183+
Now do a loop on how much to take from left and get its possible sums and do a lower bound on right possibilities.
184+
185+
*/
186+
classSolution{
187+
public:
188+
int minimumDifference(vector<int>& nums){
189+
int totalSum = accumulate(nums.begin(), nums.end(), 0), n = nums.size();
190+
191+
function<vector<vector<int>>(int, int)> findAllSubsets = [&](int l, int r) -> vector<vector<int>>{
192+
int len = r - l + 1;
193+
vector<vector<int>> res(len + 1);
194+
for (int i = 0; i < (1 << len); ++i){
195+
int sum = 0;
196+
for (int j = 0; j < len; ++j){
197+
if (i&(1<<j)) sum += nums[l + j];
198+
}
199+
res[__builtin_popcount(i)].push_back(sum);
200+
}
201+
return res;
202+
};
203+
204+
auto left = findAllSubsets(0, n/2 - 1);
205+
auto right = findAllSubsets(n/2, n - 1);
206+
207+
int res = INT_MAX;
208+
for (int takeLeft = 0; takeLeft <= n/2; ++takeLeft){
209+
int takeRight = n/2 - takeLeft;
210+
auto rightPossibleSums = right[takeRight];
211+
sort(rightPossibleSums.begin(), rightPossibleSums.end());
212+
213+
for (auto leftPossibileSum: left[takeLeft]){
214+
int needSumFromRight = totalSum/2 - leftPossibileSum;
215+
auto it = lower_bound(rightPossibleSums.begin(), rightPossibleSums.end(), needSumFromRight);
216+
if (it != rightPossibleSums.end()){
217+
int first = leftPossibileSum + *it;
218+
int second = totalSum - first;
219+
res = min(res, abs(first - second));
220+
}
221+
}
222+
}
223+
return res;
224+
}
225+
};
226+
```
176227

177228
This makes the complexity O\(2^\(n/2\)\) which is also O\(root 2^n\)
178229

0 commit comments

Comments
(0)