首页 > 其他分享 >Day7代码随想录(1刷) 哈希表

Day7代码随想录(1刷) 哈希表

时间:2024-03-12 21:32:03浏览次数:28  
标签:ransomNote right nums int Day7 sum 随想录 哈希 nums1

目录

454. 四数相加 II

 383. 赎金信

15. 三数之和

 18. 四数之和


 

454. 四数相加 II

给你四个整数数组 nums1nums2nums3 和 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] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0

示例 2:

输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
输出:1

  提示:

  • n == nums1.length
  • n == nums2.length
  • n == nums3.length
  • n == nums4.length
  • 1 <= n <= 200
  • -228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228

状态:看了答案思路完成,一开始定nums1的值,然后遍历剩下三个数组的方式超时

思路: 把nums1和nums2的和有多少种情况用map存起来,然后在nums3和nums4中遍历并查看map里有无与其相加为0的数字若有则把val加到sum中。map.getOrDefault(key,val)这个方法可以指定默认值然后存取。

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        int sum=0;
        HashMap<Integer,Integer> map = new HashMap<>();
            for(int j=0;j<nums1.length;j++){
                for(int k=0;k<nums2.length;k++){
                    if(map.containsKey(nums1[j]+nums2[k])){
                        map.put(Integer.valueOf(nums1[j]+nums2[k]),Integer.valueOf(map.get(nums1[j]+nums2[k])+1));
                    }else{
                        map.put(Integer.valueOf(nums1[j]+nums2[k]),Integer.valueOf(1));
                    }
                }
            }
        for(int i=0;i<nums3.length;i++){
            for(int j=0;j<nums4.length;j++){
                if(map.containsKey(0-nums3[i]-nums4[j])){
                    sum+=map.get(0-nums3[i]-nums4[j]);
                }
            }
        }
        return sum;
    }
}

 383. 赎金信

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false 。

magazine 中的每个字符只能在 ransomNote 中使用一次。

示例 1:

输入:ransomNote = "a", magazine = "b"
输出:false

示例 2:

输入:ransomNote = "aa", magazine = "ab"
输出:false

示例 3:

输入:ransomNote = "aa", magazine = "aab"
输出:true

提示:

  • 1 <= ransomNote.length, magazine.length <= 105
  • ransomNote 和 magazine 由小写英文字母组成

状态:完成

思路:因为只有小写字母,所以直接构建长度为26的int数组arr用于存放magzine中的字符出现次数,字符-'a'则可以得到数组的下标。存放完magzine中出现次数后,遍历ransomNote,如果arr里该值大于0则arr中该下标-1,如果等于0则返回false。

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if(ransomNote.length()>magazine.length()) return false;
        int[] arr = new int[26];
        char[] ransomNotes=ransomNote.toCharArray();
        char[] magazines=magazine.toCharArray();
        for(int i=0;i<magazines.length;i++){
            arr[magazines[i]-'a']++;
        }
        for(int i=0;i<ransomNotes.length;i++){
            if(arr[ransomNotes[i]-'a']>0){
                arr[ransomNotes[i]-'a']--;
            }else{ 
                return false;
            }
        }
        return true;
        
    }
}

15. 三数之和

 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

状态:完成

思路:使用双指针的方式去解题更好,不用建立哈希表节约空间与时间。我先对数组采用升序排序,因为是要找到三个数和为0的,我们先指定一个数i,将他的值固定,以不变找变,left的初始值是i+1,right初始值是最后一个,如图一所示。

                                                        图1

-4是小于0,若i所对应的值大于0则不可能相加为0了,因为采用升序排。如果三个数相加如图一小于0,则left++,将结果变大。若大于0,则right--将结果变小,若等于0则将i,left,right写入数组,java可以用Arrays.asList(int,int,int,...)来快速创建数组,然后left++,right--,因为这两个值肯定不能选择了。这时注意结果数组不能有重复,如果left++/right--之后对应的值等于原先的值则一直+/-到不同样为止。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> arr = new ArrayList<>();
        if(nums[0]>0) return arr;
        for(int i=0;i<nums.length;i++){
            while(i>0&&i<nums.length-1&&nums[i]==nums[i-1]) i++; 
            if(nums[i]>0) break;
            int left=i+1;
            int right=nums.length-1;
            if(right==i) break;
            while(left<right){
                int sum=nums[left]+nums[right]+nums[i];
                if(sum==0){
                    arr.add(Arrays.asList(nums[left],nums[right],nums[i]));
                    left++;
                    right--;
                    while(left<nums.length-1&&nums[left]==nums[left-1]) left++; 
                    while(right>i&&nums[right]==nums[right+1]) right--; 
                }else if(sum>0){
                    right--;
                }else if(sum<0){
                    left++;
                }
            }
        }
        return arr;
    }
}

 18. 四数之和

状态:缝缝补补写出来的,有两个点没注意。一是剪枝的时候把nums[a]>0的值给删了,但是这个target可以是正可以是负,导致错误。二是sum的结果溢出,要用long类型。

思路:一看到就知道是三数之和多嵌套了一层,但是实际写起来没有这么简单,问题主要就在剪枝和去重以及结果溢出。我的代码太乱了,还是要想清楚再做题,下面给出正确的思路及代码。

思路:链接icon-default.png?t=N7T8https://programmercarl.com/0018.%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C.html#%E6%80%9D%E8%B7%AF

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> list = new ArrayList<>();
        if (nums.length < 4)
            return list;
        Arrays.sort(nums);
        for (int a = 0; a < nums.length - 3; a++) {
            while (a > 0 && nums[a] == nums[a - 1]){
                a++;
                if (a >= nums.length - 3) return list;
            }
            long sum_t = (long)target - nums[a];// b+c+d所要求的总和
            int b = a + 1;
            int c = b + 1;
            int d = nums.length - 1;
            long sum = (long)nums[b] + nums[c] + nums[d];
            for (; b < d - 1; b++) {
                System.out.println(a + " " + b + " " + c + " " + d + " ");
                while(b!=a+1&&b<d&&nums[b]==nums[b-1]) b++;
                c = b + 1;
                while (b < c && c < d) {
                    sum = (long)nums[b] + nums[c] + nums[d];
                    if (sum == sum_t) {
                        list.add(Arrays.asList(nums[a], nums[b], nums[c], nums[d]));
                        c++;
                        d--;
                        while (c < d && nums[c] == nums[c - 1])
                            c++;
                        while (d > c && nums[d] == nums[d + 1])
                            d--;
                    } else if (sum > sum_t) {
                        d--;
                    } else if (sum < sum_t) {
                        c++;
                    }
                }
                d = nums.length - 1;
            }
        }
        return list;
    }
}

感想:今天的题目难度主要都集中于最后一题。没想到最后一题竟然这么多坑,其实就比第三题多一个循环,但是就是要想的点有很多。继续坚持下去。

标签:ransomNote,right,nums,int,Day7,sum,随想录,哈希,nums1
From: https://blog.csdn.net/SuperSwaggy/article/details/136646573

相关文章

  • 代码随想录刷题笔记
    代码随想录刷题数组二分查找思路:有序数组,数组中无重复元素移除元素思路:数组在内存地址中是连续的,不能单独删除某个数组中的某个元素,只能覆盖快慢指针法,用于数组、链表、字符串等的操作双向指针法,更优,移动更少的元素注意:补充快慢指针法的代码交换时候......
  • 代码随想录算法训练营第四十三天 | 474.一和零,● 494. 目标和 ,1049. 最后一块石头的
     1049.最后一块石头的重量II 已解答中等 相关标签相关企业 提示 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,......
  • 代随想录 第十八天 | ● 513.找树左下角的值 ● 112. 路径总和 113.路径总和ii ● 10
    leetcode:513.找树左下角的值-力扣(LeetCode)思路:是找最深左下角的值,不是找左节点最深的值!!遍历深度,判断最大深度,存储后再与下一个相同深度的比较,先左后右,也就是从左到右的顺序来判断的,所以能找到树下左下角的值classSolution{intmaxdepth=0;intresult=0;......
  • 代码随想录算法训练营第四十四天|完全背包 ● 518. 零钱兑换 II ● 377. 组合总和 Ⅳ
    完全背包题目链接:52.携带研究材料(第七期模拟笔试)(kamacoder.com)思路:完全·背包问题和01背包的区别在于同一个物品可以被重复放入,在代码里的区别就是内部遍历背包的for循环由倒序变成了正序。而且如果我们压缩了一维的话,如我的做法,两个for循环的顺序也是无所谓的。#include<i......
  • 代码随想录算法训练营第七天| 454. 四数相加 II 383. 赎金信
    454.四数相加IIhttps://leetcode.cn/problems/4sum-ii/description/、publicintfourSumCount(int[]nums1,int[]nums2,int[]nums3,int[]nums4){intres=0;HashMap<Integer,Integer>map=newHashMap<>();for(inti:nu......
  • 代码随想录算法训练营第六天| 242. 有效的字母异位词
    242.有效的字母异位词https://leetcode.cn/problems/valid-anagram/description/publicbooleanisAnagram(Strings,Stringt){char[]sChar=s.toCharArray();char[]tChar=t.toCharArray();Arrays.sort(sChar);Arrays.sort(tChar......
  • 代码随想录算法训练营第四十一天 | 416. 分割等和子集,● 01背包问题,你该了解这些! 滚
     46.携带研究材料(第六期模拟笔试)时间限制:5.000S空间限制:128MB题目描述小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据......
  • 代码随想录算法训练营第四十三天|● 1049. 最后一块石头的重量 II ● 494. 目标和
    最后一块石头的重量 II 题目链接:1049.最后一块石头的重量II-力扣(LeetCode)思路:尽可能将石头分成重量相近的两堆,结果一定最小,因此问题可以转换为分割子集。dp[i]的含义是背包容量为i的背包能装下的最大重量,由于题目中最大重量是15000,所以我们申请15001的vector。注意,结果不......
  • 算法面试通关40讲 - 哈希表/映射
    1.两数之和#include<iostream>#include<unordered_map>usingnamespacestd;classSolution{public:vector<int>twoSum(vector<int>&nums,inttarget){vector<int>indices;unordered_map<int,decltype(nums.siz......
  • 动态规划 代码随想录
    step:确定dp数组(dptable)以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组需要重做的题:343(整数拆分) 96(二叉搜索树的种类)简单题:509.斐波那契数   70.爬楼梯   746.使用最小花费爬楼梯注意用step一步步来,注意dp【0】是否有含义。 ......