Description

给定一个长度为n的数组a,以及一个整数target

数组可以通过+-符号组成表达式,求表达式结果为target的方案数。

Constraints

  • 1n20
  • 0ai1000
  • 0ai1000
  • 1000target1000

Solution

LeetCode官方给出了O(2n)的DFS方案和O(nai)的01背包方案。

这里展示O(n2n2)的折半枚举方案。

字面意思,拆成两半去暴力匹配,使得2n能降低成2n2

Code

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        if(nums.size() == 1) {
            if(nums[0] == target) return 1;
            return (-nums[0]) == target;
        }

        auto bitselect = [](auto &vec, auto f) {
            int S = 1 << vec.size();
            for(int i = 0, sum = 0; i < S; ++i, sum = 0) {
                for(int j = 0; j < vec.size(); ++j) {
                    if(i >> j & 1) sum += vec[j];
                    else sum -= vec[j];
                }
                f(sum);
            }
        };

        unordered_map<int, int> buckets;
        int ans = 0;

        auto midpoint = nums.begin() + nums.size() / 2;
        vector<int> left {nums.begin(), midpoint};
        vector<int> right {midpoint, nums.end()};

        bitselect(left, [&](int sum) {
            buckets[sum]++;
        });

        bitselect(right, [&](int sum) {
            ans += buckets[target - sum];
        });

        return ans;
    }
};

LeetCode-494 Target Sum