5675. The sum of the subsequences closest to the target value (binary, bit operation)

Difficult

Give you an array of integers  nums and a target value  goal .

You need from  nums elected a subsequence, the subsequence element closest to the sum  goal . In other words, if the subsequence elements are summed  sum , you need to  minimize the absolute difference abs(sum - goal)  .

Return  abs(sum - goal) the smallest possible  value  .

Note that the subsequence of an array is an array formed by removing some elements (maybe all or none) in the original array.

Example 1:

Input: nums = [5,-7,3,5], goal = 6
 Output: 0
 Explanation: The entire array is selected as the selected subsequence, and the sum of the elements is 6.
The subsequence sum is equal to the target value, so the absolute difference is 0.

Example 2:

Input: nums = [7,-9,15,-2], goal = -5
 Output: 1
 Explanation: Select the subsequence [7,-9,-2], and the sum of the elements is -4.
The absolute difference is abs(-4-(-5)) = abs(1) = 1, which is the smallest possible value.

Example 3:

Input: nums = [1,2,3], goal = -7
 Output: 7

prompt:

  • 1 <= nums.length <= 40
  • -107 <= nums[i] <= 107
  • -109 <= goal <= 109

Keywords : bit operation, exponential traversal, dichotomy

It should be noted that the amount of data is limited to n<=40. Generally, for complexity such as O(n), O(n^2), O(n^3), 40 is too small, so it should be It is exponential complexity O(2^n), and 2^40 is too big. Experienced contestants will know that it will time out, but 2^20 will not. Therefore, this problem should first divide the data into a subset of traversal .

For the traversal of 2^n, bitwise operations can be used to quickly implement it. 1 << n is the size of the traversal, and the range corresponding to i is [0, 2^n -1], where the number of n can be passed ( i >> j) & 1 Determine whether each bit is 1, to represent whether this subset contains j.

Subsequently, the sum of a subsequence of the original array must be one of the following three:

  1. an element in left;
  2. an element in right;
  3. The sum of an element in left and an element in right.

In order to obtain the smallest abs (Sum-goal), for each subset of left, find the two closest subsets of right through dichotomy to minimize the absolute value of the difference with goal, traverse left, and update the smallest difference The absolute value of is the result.

class Solution {
public:
	int minAbsDifference(vector<int>& nums, int goal) {
		int N = nums.size(),n_left = N / 2, n_right = N - n_left;
		vector<int>left(1 << n_left, 0), rigjt(1 << n_right, 0);
		for (int i = 0; i < (1 << n_left); ++i) {
			for (int j = 0; j < n_left; ++j) {
				if ((i >> j) & 1) {
					left[i] += nums[j];
				}
			}
		}
		sort(left.begin(), left.end());
		int res = 1000000000;
		for (int i = 0; i < (1 << n_right); ++i) {
			for (int j = 0; j < n_right; ++j) {
				if ((i >> j) & 1) {
					rigjt[i] += nums[j + n_left];
				}
			}
			int index = lower_bound(left.begin(), left.end(), goal - rigjt[i]) - left.begin();
			if (index - 1 >= 0) {
				res = min(res, abs(rigjt[i] + left[index - 1] - goal));
			}
			if (index < left.size()) {
				res = min(res, abs(rigjt[i] + left[index] - goal));
			}
		}
		return res;
	}
};

 

Guess you like

Origin blog.csdn.net/Yanpr919/article/details/113746190