给你一个 下标从 0 开始 的整数数组 nums ,返回满足下述条件的 不同 四元组 (a, b, c, d) 的 数目 :

    nums[a] + nums[b] + nums[c] == nums[d] ,且
    a < b < c < d

    示例 1:

    输入:nums = [1,2,3,6]
    输出:1
    解释:满足要求的唯一一个四元组是 (0, 1, 2, 3) 因为 1 + 2 + 3 == 6 。
    示例 2:

    输入:nums = [3,3,6,4,5]
    输出:0
    解释:[3,3,6,4,5] 中不存在满足要求的四元组。
    示例 3:

    输入:nums = [1,1,1,3,5]
    输出:4
    解释:满足要求的 4 个四元组如下:
    - (0, 1, 2, 3): 1 + 1 + 1 == 3
    - (0, 1, 3, 4): 1 + 1 + 3 == 5
    - (0, 2, 3, 4): 1 + 1 + 3 == 5
    - (1, 2, 3, 4): 1 + 1 + 3 == 5

    提示:

    4 <= nums.length <= 50
    1 <= nums[i] <= 100


    1. class Solution {
    2. /**
    3. nums[a] + nums[b] = nums[d] - nums[c]
    4. 我们枚举b,然后b+1当坐c,只需再枚举d,然后将d-c存入哈希表
    5. 再枚举a,将哈希表中a + 个数加入答案即可
    6. 细节:d-c可能为负数 我们用数组时需要加上偏移量
    7. */
    8. public int countQuadruplets(int[] nums) {
    9. int n = nums.length;
    10. int res = 0;
    11. int[] cnt = new int[5110];
    12. for (int b = n - 3; b >= 1; --b) {
    13. for (int d = b + 2; d < n; ++d) cnt[nums[d] - nums[b+1] + 100]++;
    14. for (int a = 0; a < b; ++a) res += cnt[nums[a] + nums[b] + 100];
    15. }
    16. return res;
    17. }
    18. }

    二维背包

    1. class Solution {
    2. /**
    3. 状态表示:f[i,j,k] 表示只考虑前i个数,凑成数值为j,个数恰好是k的集合
    4. 属性:count
    5. 状态转移:选当前物品f[i-1,j,k],不选f[i-1,j-t,k-1]
    6. f[i,j,k] += f[i-1,j,k],当j > t时 + f[i-1,j-t,k-1]
    7. 当然我们可以优化掉i这个维度
    8. */
    9. public int countQuadruplets(int[] nums) {
    10. int n = nums.length;
    11. int[][] f = new int[110][4];
    12. int res = 0;
    13. f[0][0] = 1;
    14. for (int i = 1; i <= n; ++i) {
    15. int t = nums[i-1];
    16. res += f[t][3];
    17. for (int j = 109; j >= t; --j)
    18. for (int k = 3; k - 1 >= 0; --k) {
    19. f[j][k] += f[j-t][k-1];
    20. }
    21. }
    22. return res;
    23. }
    24. }