算法刷题-哈希表-四数相加

这篇具有很好参考价值的文章主要介绍了算法刷题-哈希表-四数相加。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

需要哈希的地方都能找到map的身影

第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

思路

本题是使用哈希法的经典题目,而0015.三数之和,0018.四数之和并不合适使用哈希法,因为三数之和和四数之和这两道题目使用哈希法在不超时的情况下做到对结果去重是很困难的,很有多细节需要处理。

而这道题目是四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑有重复的四个元素相加等于0的情况,所以相对于题目18. 四数之和,题目15.三数之和,还是简单了不少!

如果本题想难度升级:就是给出一个数组(而不是四个数组),在这里找出四个元素相加等于0,答案中不可以包含重复的四元组,大家可以思考一下,后续的文章我也会讲到的。

本题解题步骤:

  1. 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
  2. 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
  3. 定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
  4. 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
  5. 最后返回统计值 count 就可以了

C++代码:

class Solution {
public:
    int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
        unordered_map<int, int> umap; //key:a+b的数值,value:a+b数值出现的次数
        // 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中
        for (int a : A) {
            for (int b : B) {
                umap[a + b]++;
            }
        }
        int count = 0; // 统计a+b+c+d = 0 出现的次数
        // 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。
        for (int c : C) {
            for (int d : D) {
                if (umap.find(0 - (c + d)) != umap.end()) {
                    count += umap[0 - (c + d)];
                }
            }
        }
        return count;
    }
};

其他语言版本

Java:

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        Map<Integer, Integer> map = new HashMap<>();
        int temp;
        int res = 0;
        //统计两个数组中的元素之和,同时统计出现的次数,放入map
        for (int i : nums1) {
            for (int j : nums2) {
                temp = i + j;
                if (map.containsKey(temp)) {
                    map.put(temp, map.get(temp) + 1);
                } else {
                    map.put(temp, 1);
                }
            }
        }
        //统计剩余的两个元素的和,在map中找是否存在相加为0的情况,同时记录次数
        for (int i : nums3) {
            for (int j : nums4) {
                temp = i + j;
                if (map.containsKey(0 - temp)) {
                    res += map.get(0 - temp);
                }
            }
        }
        return res;
    }
}

Python:

class Solution(object):
    def fourSumCount(self, nums1, nums2, nums3, nums4):
        # use a dict to store the elements in nums1 and nums2 and their sum
        hashmap = dict()
        for n1 in nums1:
            for n2 in nums2:
                if n1 + n2 in hashmap:
                    hashmap[n1+n2] += 1
                else:
                    hashmap[n1+n2] = 1
        
        # if the -(a+b) exists in nums3 and nums4, we shall add the count
        count = 0
        for n3 in nums3:
            for n4 in nums4:
                key = - n3 - n4
                if key in hashmap:
                    count += hashmap[key]
        return count
 

class Solution:
    def fourSumCount(self, nums1: list, nums2: list, nums3: list, nums4: list) -> int:
        from collections import defaultdict # You may use normal dict instead.
        rec, cnt = defaultdict(lambda : 0), 0
        # To store the summary of all the possible combinations of nums1 & nums2, together with their frequencies.
        for i in nums1:
            for j in nums2:
                rec[i+j] += 1
        # To add up the frequencies if the corresponding value occurs in the dictionary
        for i in nums3:
            for j in nums4:
                cnt += rec.get(-(i+j), 0) # No matched key, return 0.
        return cnt

Go:

func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
    m := make(map[int]int)   //key:a+b的数值,value:a+b数值出现的次数
    count := 0
     // 遍历nums1和nums2数组,统计两个数组元素之和,和出现的次数,放到map中
    for _, v1 := range nums1 {  
        for _, v2 := range nums2 {
            m[v1+v2]++
        }
    }
    // 遍历nums3和nums4数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来
    for _, v3 := range nums3 {
        for _, v4 := range nums4 {
            count += m[-v3-v4]
        }
    }
    return count
}

javaScript:

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @param {number[]} nums3
 * @param {number[]} nums4
 * @return {number}
 */
var fourSumCount = function(nums1, nums2, nums3, nums4) {
    const twoSumMap = new Map();
    let count = 0;
    // 统计nums1和nums2数组元素之和,和出现的次数,放到map中
    for(const n1 of nums1) {
        for(const n2 of nums2) {
            const sum = n1 + n2;
            twoSumMap.set(sum, (twoSumMap.get(sum) || 0) + 1)
        }
    }
    // 找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来
    for(const n3 of nums3) {
        for(const n4 of nums4) {
            const sum = n3 + n4;
            count += (twoSumMap.get(0 - sum) || 0)
        }
    }

    return count;
};

TypeScript:

function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4: number[]): number {
    let helperMap: Map<number, number> = new Map();
    let resNum: number = 0;
    let tempVal: number | undefined;
    for (let i of nums1) {
        for (let j of nums2) {
            tempVal = helperMap.get(i + j);
            helperMap.set(i + j, tempVal ? tempVal + 1 : 1);
        }
    }
    for (let k of nums3) {
        for (let l of nums4) {
            tempVal = helperMap.get(0 - (k + l));
            if (tempVal) {
                resNum += tempVal;
            }
        }
    }
    return resNum;
};

PHP:

class Solution {
    /**
     * @param Integer[] $nums1
     * @param Integer[] $nums2
     * @param Integer[] $nums3
     * @param Integer[] $nums4
     * @return Integer
     */
    function fourSumCount($nums1, $nums2, $nums3, $nums4) {
        $map = [];
        foreach ($nums1 as $n1) {
            foreach ($nums2 as $n2) {
                $temp = $n1 + $n2;
                $map[$temp] = isset($map[$temp]) ? $map[$temp]+1 : 1;
            }
        }
        $count = 0;
        foreach ($nums3 as $n3) {
            foreach ($nums4 as $n4) {
                $temp = 0 - $n3 - $n4;
                if (isset($map[$temp])) {
                    $count += $map[$temp];
                }
            }
        }
        return $count;
    }
}

Swift:

func fourSumCount(_ nums1: [Int], _ nums2: [Int], _ nums3: [Int], _ nums4: [Int]) -> Int {
    // ab和: ab和出现次数
    var countDic = [Int: Int]()
    for a in nums1 {
        for b in nums2 {
            let key = a + b
            countDic[key] = countDic[key, default: 0] + 1
        }
    }

    // 通过-(c + d)作为key,去累加ab和出现的次数
    var result = 0
    for c in nums3 {
        for d in nums4 {
            let key = -(c + d)
            result += countDic[key, default: 0]
        }
    }
    return result
}

Rust:

use std::collections::HashMap;
impl Solution {
    pub fn four_sum_count(nums1: Vec<i32>, nums2: Vec<i32>, nums3: Vec<i32>, nums4: Vec<i32>) -> i32 {
        let mut umap:HashMap<i32, i32> = HashMap::new();
        for num1 in &nums1 {
            for num2 in &nums2 {
                *umap.entry(num1 + num2).or_insert(0) += 1;
            }
        }
        
        let mut count = 0;
        
        for num3 in &nums3 {
            for num4 in &nums4 {
                let target:i32 = - (num3 + num4);
                count += umap.get(&target).unwrap_or(&0);          
            }
        }
        
        count
     }
}

Scala:

object Solution {
  // 导包
  import scala.collection.mutable
  def fourSumCount(nums1: Array[Int], nums2: Array[Int], nums3: Array[Int], nums4: Array[Int]): Int = {
    // 定义一个HashMap,key存储值,value存储该值出现的次数
    val map = new mutable.HashMap[Int, Int]()
    // 遍历前两个数组,把他们所有可能的情况都记录到map
    for (i <- nums1.indices) {
      for (j <- nums2.indices) {
        val tmp = nums1(i) + nums2(j)
        // 如果包含该值,则对他的key加1,不包含则添加进去
        if (map.contains(tmp)) {
          map.put(tmp, map.get(tmp).get + 1)
        } else {
          map.put(tmp, 1)
        }
      }
    }
    var res = 0 // 结果变量
    // 遍历后两个数组
    for (i <- nums3.indices) {
      for (j <- nums4.indices) {
        val tmp = -(nums3(i) + nums4(j))
        // 如果map中存在该值,结果就+=value
        if (map.contains(tmp)) {
          res += map.get(tmp).get
        }
      }
    }
    // 返回最终结果,可以省略关键字return
    res
  }
}

C#:文章来源地址https://www.toymoban.com/news/detail-480504.html

public int FourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
       Dictionary<int, int> dic = new Dictionary<int, int>();
        foreach(var i in nums1){
            foreach(var j in nums2){
                int sum = i + j;
                if(dic.ContainsKey(sum)){
                    dic[sum]++;
                }else{
                    dic.Add(sum, 1);
                }
                
            }
        }
        int res = 0;
         foreach(var a in nums3){
            foreach(var b in nums4){
                int sum = a+b;
                if(dic.TryGetValue(-sum, out var result)){
                    res += result;
                }
            }
        }
        return res;
    }

到了这里,关于算法刷题-哈希表-四数相加的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【代码随想录 | Leetcode | 第九天】哈希表 | 快乐数 | 四数相加 II | 赎金信

    欢迎来到小K的Leetcode|代码随想录|专题化专栏,今天将为大家带来哈希法~快乐数 | 四数相加 II | 赎金信的分享 ✨ ✨题目链接点这里 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后

    2024年02月13日
    浏览(39)
  • 代码随想录-哈希表02 第454题.四数相加II&383. 赎金信&第15题. 三数之和&第18题. 四数之和

    第454题.四数相加II 第454题.四数相加II 条件:四个数组中分别取一个,相加和为0,求满足条件的元组个数 思路使用1个map,mapA保存 s1 s2中相加和及其出现次数 遍历s3 s4,去判断是否满足 0 - (s3[i] + s4[j]) 在mapA中,并统计出现次数 383. 赎金信 383. 赎金信 题目要求,s1 是否能由s

    2024年02月12日
    浏览(31)
  • leetcode刷题(字符串相加、包含每个查询的最小区间、模拟行走机器人、环形子数组的最大和、满足不等式的最大值、四数之和、树中距离之和)

    目录 1、字符串相加 2、包含每个查询的最小区间 3、模拟行走机器人 4、环形子数组的最大和 5、满足不等式的最大值 6、四数之和 7、 树中距离之和

    2024年02月10日
    浏览(35)
  • 454. 四数相加 II

    给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 = i, j, k, l n nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0   示例 1: 输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2] 输出:2 解释: 两个元组如下: 1. (0, 0, 0, 1) - nums1[0]

    2024年02月16日
    浏览(30)
  • 【力扣】454. 四数相加 II

    【力扣】454. 四数相加 II 给你四个整数数组 nums1 、 nums2 、 nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 = i, j, k, l n nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0 示例 1: 输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2] 输出:2 解释: 两个元组如下

    2024年02月16日
    浏览(33)
  • day07 四数相加Ⅱ 赎金信 三数之和 四数之和

    题目链接:454 四数相加Ⅱ 题意 4个整数数组nums1, nums2, nums3, nums4的长度均为n,有多少个元组(i,j,k,l)使得 nums[i]+nums[j]+nums[k]+nums[l]==0    (本题不包含去重的逻辑,i,j,k,l  可以相等,一组元素与一组元素之间的各个元素也可以相等) 暴力解法 会报如下超时错

    2024年01月24日
    浏览(39)
  • day7 四数相加 赎金信 三数之和 四数之和

    - 四数相加      - 不用去重,所以简单遍历就是     - 四个数,如果四重循环,就是O n^4,反正求和相加有几组数而已,俩俩一组先加起来,前俩个用map记下来,key是加和,value是出现组次数,再遍历第三、四个数组,找加和为0的,int ret = 0,去加上记录次数就好了 - 赎金信

    2024年02月14日
    浏览(84)
  • LeetCode 454.四数相加 II

    454.四数相加 II 一、题目 给你四个整数数组 nums1 、 nums2 、 nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 = i, j, k, l n nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0 示例 1: 示例 2: 提示: n == nums1.length n == nums2.length n == nums3.length n == nums4.length 1 = n = 200

    2024年02月12日
    浏览(31)
  • LeetCode_Day6 | 四数相加||、赎金信、三数之和、四数之和!

    详情leetcode链接 解题步骤: 首先定义 map,key放a和b两数之和,value 放a和b两数之和出现的次数。 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。 定义int变量count,用来统计 a+b+c+d = 0 出现的次数。 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话

    2024年02月09日
    浏览(34)
  • 【代码随想录06】454. 四数相加 II 383. 赎金信 15. 三数之和 18. 四数之和

    题目描述 给你四个整数数组 nums1 、 nums2 、 nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 = i, j, k, l n nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0 做题思路 本题可以使用哈希表, key 为 nums1[i] + nums2[j] 的和, value 为其出现的次数。然后再遍历 nums3 和

    2024年01月16日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包