代码编织梦想

代码随想录 Day7

今日任务

454.四数相加Ⅱ
383.赎金信
15.三数之和
18.四数之和

454. 四数相加Ⅱ

考点:哈希表
链接:https://leetcode.cn/problems/4sum-ii/

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

在这里插入图片描述

383. 赎金信

考点:哈希表
链接:https://leetcode.cn/problems/ransom-note/

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] record = new int[26];
        for(int i = 0; i < magazine.length(); i++){
            record[magazine.charAt(i) - 'a']++;
        }
        for(int i = 0; i < ransomNote.length(); i++){
            record[ransomNote.charAt(i) - 'a']--;
            if(record[ransomNote.charAt(i) - 'a'] < 0){
                return false;
            }
        }
        return true;
    }
}

在这里插入图片描述

15. 三数之和

考点:双指针(哈希表麻烦)
链接:https://leetcode.cn/problems/3sum/
解题思路:卡哥视频
注意事项:此题还是有很多细节点的

  1. 为什么这道题可以先对数组排序再求解?
    因为这道题需要我们返回的并不是数组元素的下标,而是数组中的元素,所以可以对数组进行排序,这样哪怕数组元素不在原来的位置也不会影响最终结果;
  2. 为何这道题对 i 去重时要写成nums[i] == nums[i - 1]而不是nums[i] == nums[i + 1]
    这和我们对 left 的处理有关,因为我们 left 的初始位置是在 i 右侧一个,如果直接判断 nums[i] 和 nums[i + 1] ,相当于我们会忽略掉nums[i] == nums[left]但其实结果符合nums[i] + nums[left] + nums[right] == 0的情况,所以去重时我们要使用nums[i] == nums[i - 1]这种判断方式;同理,后续对 left 和 right 的处理也是一样,left 向右移动,那么想要去重就要和 nums[left + 1] 比较,right 向左移动,想要去重就要和 nums[right - 1] 比较;
  3. 我们需要先将结果加到 result 中,再对 left 和 right 去重,否则会导致result 中一个结果都没有。
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        for(int i = 0; i < nums.length; i++){
            if(i > 0 && nums[i] == nums[i - 1]){
                continue;
            }
            int left = i + 1;
            int right = nums.length - 1;
            while(left < right){
                while(left < right && nums[i] + nums[left] + nums[right] > 0){
                    right--;
                }
                while(left < right && nums[i] + nums[left] + nums[right] < 0){
                    left++;
                }
                if(left < right && nums[i] + nums[left] + nums[right] == 0){
                    List<Integer> temp = new ArrayList<>();
                    temp.add(nums[i]);
                    temp.add(nums[left]);
                    temp.add(nums[right]);
                    result.add(temp);
                    // while的时候务必注意下标范围
                    while(left < right && nums[left] == nums[left + 1]){
                        left++;
                    }
                    while(left < right && nums[right] == nums[right - 1]){
                        right--;
                    }
                    left++;
                    right--;
                }
            }
        }
        return result;
    }
}

在这里插入图片描述

18. 四数之和

考点:
链接:https://leetcode.cn/problems/4sum/
思考问题:本题和454.四数相加Ⅱ的区别在哪里,为什么四数相加Ⅱ会简单很多?
四数相加Ⅱ是求四个数组之间的元素相加和为0的情况有多少种,哪怕元素值相等,但只要不是同一个数组中同位置的元素,就是不同的结果;但是此题要求元组不能重复;也就是说四数相加Ⅱ中(-1, -1, 1, 1)和(-1, 1, 1, -1)可能是两种结果,但在四数之和中,(-1, -1, 1, 1)和(-1, 1, 1, -1)只能算作一种结果,由去重产生的一系列需要考虑的情况导致了难度的上升。

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        //错误的剪枝操作,nums[0]为负数且nums[0]>target是有可能的
        // if(nums.length < 4 || nums[0] > target){
        //     return result;
        // }
        for(int i = 0; i < nums.length - 3; i++){
            //这里的剪枝操作必须是 nums[i]>0 时才可以
            //因为在 nums[i]<0 时是有可能通过继续和负数相加得到target的
            if(nums[i] > 0 && nums[i] > target){
                return result;
            }
            //这里的if不要写成while,否则continue会死循环
            if(i > 0 && nums[i] == nums[i - 1]){
                continue;
            }
            for(int j = i + 1; j < nums.length - 2; j ++){
                if(j > i + 1 && nums[j] == nums[j - 1]){
                    continue;
                }
                int left = j + 1;
                int right = nums.length - 1;
                while(left < right){
                    while(left < right && nums[i] + nums[j] + nums[left] + nums[right] > target){
                        right--;
                    }
                    while(left < right && nums[i] + nums[j] + nums[left] + nums[right] < target){
                        left++;
                    }
                    if(left < right && nums[i] + nums[j] + nums[left] + nums[right] == target){
                        result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                        while(left < right && nums[left] == nums[left + 1]){
                            left++;
                        }
                        while(left < right && nums[right] == nums[right - 1]){
                            right--;
                        }
                        left++;
                        right--;
                    }
                }
            }
        }
        return result;
    }
}

在这里插入图片描述
因为在三数之和时我没有进行剪枝操作,所以这道题写剪枝的时候就出现了很多意料之外的bug
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_38255385/article/details/127386788

代码随想录算法训练营day6 | 242.有效的字母异位词,349. 两个数组的交集 ,202. 快乐数,1. 两数之和_jzh013的博客-爱代码爱编程

哈希表理论基础: 当需要快速判断一个元素是否出现在集合里的时候,则优先考虑哈希表。      出现哈希碰撞: 拉链法:将发生碰撞的两个或多个元素存储在链表中 tip:拉链法就是要选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间。线性探测法:依靠哈希表中的空位来解决碰撞问题,出现碰

代码随想录训练营day06|哈希表理论基础、_高一步的博客-爱代码爱编程

哈希表理论基础 1.一句箴言:想要快速判断一个元素是否出现在集合里,就使用哈希表。 2.哈希表定义:哈希表是根据关键码的值而直接进行访问的一种数据结构。                    (1)数组就是一张哈希表。关键码为数组下标索引,通过下标直接进行访问。                    (2) 无序。不需保持有序性,只是用来快速判断存

代码随想录算法训练营 day6 | 哈希表 |242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和_快叫我去刷leetcode的博客-爱代码爱编程

代码随想录算法训练营 Day6 | 哈希表 |242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和 其实参与这个打卡训练营之前自己就有开始刷题,但是就是知道自己自制力不够才参与了训练

代码随想路算法训练营第9天| kmp 字符串匹配算法 kmp是什么 前缀表 前缀表与next数组 使用next数组来匹配 28. 找出字符串中第一个匹配项的下标_lebowskii的博客-爱代码爱编程

KMP是什么: 在一个串中查找是否出现过另一个串,这是KMP的看家本领 KMP的经典思想就是:  当出现字符串不匹配时,可以用NEXT数组记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。 那么,用什么去记录之前已经匹配的文本内容呢? 前缀表: 前缀表里存的是最长相同前后缀的长度。前缀表可以告诉我们匹配失败之后跳到哪里重新匹

代码随想录算法训练营day10 | 459.重复的子字符串_jzh013的博客-爱代码爱编程

题目: 459.重复的子字符串 看题解前: 根据题意,有这样的一个子字符串存在,那么子字符串乘以重复的次数应该等于原字符串。 trick:遍历的时候 都不用遍历结束,只需要遍历到中间位置,因为子串结束位置大于中间位置的话,一定不能重复组成字符串。 有两种写法: class Solution: def repeatedSubstring

代码随想录算法训练营day14|二叉树理论基础,递归遍历,迭代遍历,统一迭代, 144.二叉树的前序遍历,145.二叉树的后序遍历,94.二叉树的中序遍历_cccccilu的博客-爱代码爱编程

二叉树理论基础 二叉树有两种主要的形式:满二叉树和完全二叉树。 满二叉树 满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。 如果定义这个二叉树的深度为 k ,也就是有 2^k-1 个节点。 完全二叉树 完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数

【代码随想录训练营】day6-哈希表_koffer-debug的博客-爱代码爱编程

代码随想录 Day6 今日任务 242.有效的字母异位词 349.两个数组的交集 202.快乐数 1.两数之和 语言:Java 242. 有效的字母异位词 考点:哈希表(数组) 链接:https://leetcode

代码随想录训练营 day6 242 有效的字母异位词_头顶的树荫有个洞的博客-爱代码爱编程

题目链接 242 有效的字母异位词 思路:设置一个数组用来做哈希表,该数组用来保存是否存在目标数。如果第一个数组存在,则以该数作为哈希值作为数组下标。 bool isAnagram(char * s, char * t

代码随想录训练营 day6 349 两个数组的交集_头顶的树荫有个洞的博客-爱代码爱编程

题目链接 349 两个数组的交集 思路:哈希表应用 /** * Note: The returned array must be malloced, assume caller calls free(). */ i

代码随想训练营(两个月)_代码训练营-爱代码爱编程

代码随想训练营 Day1 数组:二分搜索 + 移除元素Leetcode 704 二分查找Leetcode 27 移除元素 Day2 数组:有序数组平方 + 长度最小子数组 + 螺旋矩阵生成Leetcode

算法60天:day 6数组的进阶:哈希表_records=dict()-爱代码爱编程

代码随想录(截图自参考【1】) 本系列是代码随想录算法训练营的学习笔记之day6,主要记录一下刷题的过程,以及核心知识点和一些值的记录的问题。 代码随想录的资源都是免费的

代码随想录训练营day6-爱代码爱编程

目录 题目一:有效的字母异位词 题目二:两个数组的交集  题目三:快乐数 题目四: 两数之和  总结: 题目一:有效的字母异位词 力扣题目链接 题目描述: 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词

代码随想录训练营day 6||哈希表-爱代码爱编程

今日的任务: 哈希表理论基础242.有效的字母异位词202.快乐数1.两数之和 哈希表理论基础   主要有三种数据结构,Set, Array and Map.    Hash Table: maps Key to values.   一般哈希表都是用来快速判断一个元素是否出现在集合里。   Strength:时间复杂度只有O(1).(相比于枚举

5.哈希表(1) | 有效的字母异位词、两个数组的交集、快乐数、两数之和_将unordered_set转换成vector-爱代码爱编程

        这4道题的前3道主要让人了解了set和map的各项基本用法,题目本身的方法方面没有难度。第4题低于O(n²)的方法还是不容易想到的,这次难得自己想到,不过具体实现上相比题解还要很大优化空间。         第1题(242.有效的字母异位词)是典型的哈希表问题,但又不完全是。做题过程主要学习了解了unordere

代码随想录训练营day6:哈希表理论基础 、 242.有效的字母异位词 、349. 两个数组的交集 、202. 快乐数、1. 两数之和-爱代码爱编程

1.哈希表理论基础:代码随想录 (programmercarl.com)         1.注意一般哈希表都是用来快速判断一个元素是否出现在集合里。         2.一般来讲,若哈希值较少,用数组即可,若哈希值较大,则用set或者map。set数据结构和数组类似,但是里面的值不能重复。 2.有效字母异位词:代码随想录 (programm

(二刷)代码随想录算法训练营day7 | 454.四数相加ii,383. 赎金信,15. 三数之和,18. 四数之和-爱代码爱编程

454.四数相加II(medium) trick: reduce to two sum problem 这样复杂度从暴力解法的O(n^4)降为O(n^2) 注意:题目要求解的是“有多少个元祖”,也就是求满足条件的个数。如果需要返回indices,那么就是另一种写法了 class Solution(object): def fo

代码随想录算法训练营 day7 | 哈希表 | 454.四数相加ii 、383. 赎金信 、15. 三数之和、 18. 四数之和-爱代码爱编程

代码随想录算法训练营 Day7 | 哈希表 | 454.四数相加II 、383. 赎金信 、15. 三数之和、 18. 四数之和 补博客打卡。。。 454. 四数相加 II 两数之和哈希表的解法思路稍微改变

训练营day07 哈希表 | 454.四数相加ii、383. 赎金信、15. 三数之和、18. 四数之和 、哈希表总结-爱代码爱编程

454.四数相加II 思路 1-定义map,key存放a+b的值,value存放a+b出现的次数 2-遍历c, d,在map中寻找0-(c+d),找到后便在count中加上map的value值 3-返回count 代码 class Solution { public: int fourSumCount(vector<int>

代码随想录算法训练营第14天 | 二叉树理论基础 递归遍历 迭代遍历-爱代码爱编程

系列文章目录 代码随想录——二叉树篇 文章目录 系列文章目录二叉树的基础知识二叉树的种类满二叉树完全二叉树二叉搜索树平衡二叉搜索树 二叉树的存储方式二叉树的遍历方式二叉树结点的写法 递归遍