leetcode刷题:哈希表05 (四数相加 II)

54 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

第454题.四数相加II

力扣题目链接

给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。

为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -2^28 到 2^28 - 1 之间,最终结果不会超过 2^31 - 1 。

例如:

输入: A = [ 1, 2] B = [-2,-1] C = [-1, 2] D = [ 0, 2] 输出: 2 解释: 两个元组如下:

  1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
  2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0

这题拿过来,是不是就想着和我一样四层循环


    /**
     * @param nums1
     * @param nums2
     * @param nums3
     * @param nums4
     * @return
     * @Version 1.0
     */
    public int fourSumCount1(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int count = 0;
        for (int i = 0; i < nums1.length; i++) {
            for (int j = 0; j < nums1.length; j++) {
                for (int k = 0; k < nums1.length; k++) {
                    for (int l = 0; l < nums1.length; l++) {
                        if (nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0) {
                            count++;
                        }
                    }
                }
            }
        }
        return count;
    }

在这里插入图片描述

没有用的,不要把力扣当傻子,老老实实做题。 回想一下昨天做两数之和的时候,用的hashMap,直接把O(N^2^)转化为O(N) 这题也一样,前后两个数组分别相加 把O(N^4^)转化为O(N^2^)

    /**
     * @param nums1
     * @param nums2
     * @param nums3
     * @param nums4
     * @return
     * @Version 2.0
     *
     * 1,1   0.2 -1.1
     * -1 1 2 4
     */
    public static int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        /**
         * 可以类似两数之和。把O(N^4)转化为O(N^2),用两数之和思想
         */
        //总数
        int count = 0;
        //数组长度
        int n = nums1.length;
        //结果集,键为需要的结果,值为键出现的次数,因为set中键唯一
        HashMap<Integer, Integer> result = new HashMap<>();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                //set中键不重复
                if (result.containsKey(-(nums1[i] + nums2[j]))) {
                    //如果键重复出现,要记录键出现的次数
                    int value = result.get(-(nums1[i] + nums2[j])) + 1;
                    result.put(-(nums1[i] + nums2[j]), value);
                } else {
                    result.put(-(nums1[i] + nums2[j]), 1);
                }
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (result.containsKey(nums3[i] + nums4[j])) {
                    //比如1 2 之和出现4次-1,3 4 之和 每出现1次1,则就加4次
                    count += result.get(nums3[i] + nums4[j]);
                }
            }
        }
        return count;
    }

在这里插入图片描述

嚯嚯嚯!!! 看了一下题解,和我思路一模一样,只是改用了增强for,速度就上去好多


    /**
     * @param nums1
     * @param nums2
     * @param nums3
     * @param nums4
     * @return
     * @Version 3.0
     * 增强for改写一下
     *
     */
    public static int fourSumCount3(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        /**
         * 可以类似两数之和。把O(N^4)转化为O(N^2),用两数之和思想
         */
        //总数
        int count = 0;
        //数组长度
        int n = nums1.length;
        //结果集,键为需要的结果,值为键出现的次数,因为set中键唯一
        HashMap<Integer, Integer> result = new HashMap<>();
        for (int i:nums1) {
            for (int j :nums2) {
                //set中键不重复
                if (result.containsKey(-(i + j))) {
                    //如果键重复出现,要记录键出现的次数
                    int value = result.get(-(i + j)) + 1;
                    result.put(-(i + j), value);
                } else {
                    result.put(-(i + j), 1);
                }
            }
        }
        for (int i:nums3) {
            for (int j :nums4) {
                if (result.containsKey(i + j)) {
                    //比如1 2 之和出现4次-1,3 4 之和 每出现1次1,则就加4次
                    count += result.get(i + j);
                }
            }
        }
        return count;
    }

在这里插入图片描述