14、★★ 四个数组分组-454.四数相加Ⅱ

题目描述

给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

来源:力扣(LeetCode)

思路:完全没有思路:

四个数组,如果遍历就是 N的四次方的复杂度!可以进行折半,复杂度就折半变成了 n的²

答案思路

1)将其中两个分别相加,得出全部可能的值!重要的思想,当然也可以将其中3组相加,n的三次方的时间复杂度!

2)然后再用哈希判断,需要记录合适的结果的 出现次数!

3)getOrDefault()方法,是map中的方法!如果有就得到value值,没有就设置默认值!

代码

1)分组 + 哈希:看了答案思路自己写的

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        //套循环肯定不行
        //只用记录元组个数

        //最重要的是,将四个数组拆分成两两一组,变成了上一题的 两数之和!
        int n = nums1.length;
        int num = 0;
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i < n;i++){
            for(int j = 0;j < n;j++){
                int sum = nums1[i] + nums2[j];
                if(map.containsKey(sum)) map.put(sum,map.get(sum) + 1);
                else map.put(sum,1);
            }
        }

        for(int i = 0;i < n;i++){
            for(int j = 0;j < n;j++){
                int sum = nums3[i] + nums4[j];
                if(map.containsKey(0 - sum)){
                    num = num + map.get(0 - sum);
                }
            }
        }
        return num;
    }
}

2)优化了一个 方法

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        //套循环肯定不行
        //只用记录元组个数

        //最重要的是,将四个数组拆分成两两一组,变成了上一题的 两数之和!
        int n = nums1.length;
        int num = 0;
        Map<Integer,Integer> map = new HashMap<>();
        for(int i = 0;i < n;i++){
            for(int j = 0;j < n;j++){
                int sum = nums1[i] + nums2[j];
                map.put(sum,map.getOrDefault(sum,0) + 1);
            }
        }

        for(int i = 0;i < n;i++){
            for(int j = 0;j < n;j++){
                int sum = nums3[i] + nums4[j];
                if(map.containsKey(0 - sum)){
                    num += map.get(0 - sum);
                }
            }
        }
        return num;
    }
}

3)使用Map效果很差!因为空间大,计算耗时!

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        //记录杂志字符串出现的次数
        Map<Character,Integer> map = new HashMap<>();
        for (int i = 0; i < magazine.length(); i++) {
            char c = magazine.charAt(i);
            map.put(c,map.getOrDefault(c,0) + 1);
        }
        for (int i = 0; i < ransomNote.length(); i++) {
            char c = ransomNote.charAt(i);
            if(!map.containsKey(c)) return false;
            map.put(c,map.get(c) - 1);
            if(map.get(c) < 0) return false;
        }
        return true;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 首先需要计算数组的偏移量(offset),即 A[i,j,k] 相对于 A[1,-2,0] 的地址偏移量。由于每个元素占用 32 位(即 4 个字节),因此偏移量可以如下计算: offset = [(4-1)*15 + (2-(-2))*7 + (3-0)]*4 = 216 其中,(4-1)*15 表示第 4 行之前一共有 3 行,每行有 15 个元素,所以在第四行之前的地址偏移量为 45*4=180;(2-(-2))*7 表示在第 4 行之前,第 2 行到第 -2 行(即第 3 行到第 7 行)总共有 5 行,每行有 7 个元素,所以在第 4 行之前,第 2 列到第 4 列之间的地址偏移量为 5*7*4=140;(3-0) 表示在第 4 行的前提下,第 3 列到第 0 列之间有 3 列,每列有 1 个元素,所以在第 4 行的前提下,第 3,2,1 列到第 4,3,2 列之间的地址偏移量为 3*1*4=12。 因此,元素 A[4,2,3] 的首地址为: 78 + 216 = 294 ### 回答2: 首先,我们需要确定数组元素A[4, 2, 3] 所在的行、列、和高度。 根据给定数组范围A[1..8 ,-2..6 ,0..6],我们可以得知行的范围是1到8,列的范围是-2到6,高度的范围是0到6。 然后,我们需要计算A[4, 2, 3] 所在的行的偏移量、列的偏移量、和高度的偏移量。 数组元素的首地址是78,每个元素占32位,即4字节。因此,每一行的偏移量是(6-(-2)+1)*(7-1+1)*(6-0+1)*4=588字节。 在第四行的偏移量是(4-1)*588=1764字节。 在第二列的偏移量是(2-(-2))*(6-(-2)+1)*4=80字节。 在第三个高度的偏移量是(3-0)*4=12字节。 最后,我们将偏移量相加,得到元素A[4, 2, 3] 的首地址为78 + 1764 + 80 + 12 = 1934。 所以,元素A[4, 2, 3] 的首地址是1934。 ### 回答3: 要求元素A[4,2,3]的首地址,需要先计算该元素在数组中的偏移量。 首先,数组的行数为8,列数为9(从-2到6,共有9个元素),所以每一行的元素个数为9。 然后,我们需要按照行为主序存储,即先存储第一行的所有元素,再存储第二行的所有元素,然后是第三行,以此类推。 根据给定的题目信息,每个元素占32位,即4个字节。 我们需要计算元素A[4,2,3]相对于第一个元素A[1,-2,0]的偏移量。 首先,先计算第四行之前的元素个数。 第一行有9个元素,第二行有9个元素,第三行有9个元素,第四行有2个元素,所以前四行的元素个数为(9+9+9+2)=29个。 然后,计算第四行中元素2之前的元素个数。 第四行中的元素2的前面有3个元素(-2,0,1),所以第四行中元素2之前的元素个数为3个。 因此,元素A[4,2,3]相对于第一个元素A[1,-2,0]的偏移量为(29+3)=32个元素。 由于每个元素占32位,偏移量为32个元素,所以元素A[4,2,3]的首地址为78 + (32 x 32) = 1106。 所以,元素A[4,2,3]的首地址是1106。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值