Day7补代码随想录 454.四数相加II 383赎金信 15.三数之和 18.四数之和

news/2024/12/26 10:28:22/

链接

https://programmercarl.com/0454.%E5%9B%9B%E6%95%B0%E7%9B%B8%E5%8A%A0II.html

454.四数相加II

题目

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

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

输入:

  • A = [ 1, 2]
  • B = [-2,-1]
  • C = [-1, 2]
  • D = [ 0, 2]

输出: 2

思路

  • 初步思路
    • 数据结构,数据量不大,但是数组有4个,选择数组。
    • 终止条件,固定数组1,遍历2,遍历3,遍历4,四层for循环,直到四个数相加等于0时,返回元素位置,键和值,选择map比较好
  • 代码随想录思路
    • 4个数组

      • 前两个数组遍历一遍,计算a+b的值(key)和次数(value)
      • 后两个数组进行【查询】操作,查询是否有-(c+d)=(a+b)的情况,如果有,count+value(注意为什么加而不是乘)
    • class Solution {public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {int res=0;//存储和为0的元组Map<Integer,Integer> map=new HashMap<Integer,Integer>();//遍历前两个数组for(int i:nums1){for(int j:nums2){int sum=i+j;map.put(sum,map.getOrDefault(sum,0)+1);  }}  //统计剩余的两个元素的和,在map中找是否存在相加为0的情况,同时记录次数for(int i:nums3){for(int j:nums4){res+=map.getOrDefault(0-i-j,0);}}return res;}
      }
      

收获

  • 增强型for循环,for(int i:nums1){}
  • map.put(sum, map.getOrDefault(sum, 0) + 1);
    • map.getOrDefault(sum, 0) 从map中返回sum键对应的值(出现次数),当i,j循环的sum出现一次,就+1,只是计算了一个新的值
    • map.put() 更新map值
  • res是存储符合条件的元组

383赎金信

题目

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

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

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

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

思路

  • 我的思路

    • 能不能包含,如果在magazine中能查找到ransomNote,就说明包含。
      • 怎么样叫做包含?
    • 选择结构
  • 思路

    • 原则:不暴露赎金信字迹,字母不可重复使用;假设两个字符串均只含有小写字母。
    • record数组存储两个数组的字母出现的字数,一个++,一个–,当最后的record的某个字母<0时,说明false【关键】
    • class Solution {public boolean canConstruct(String ransomNote, String magazine) {int [] record=new int[26];//初始化要正确//第一步判断要加上if (ransomNote.length() > magazine.length()) {return false;}//++for(int i=0;i<magazine.length();i++){record[magazine.charAt(i)-'a']++;}//--for(int j=0;j<ransomNote.length();j++){record[ransomNote.charAt(j)-'a']--;if (record[ransomNote.charAt(j)-'a']<0){return false;}}return true;}
      }
      
  • class Solution {public boolean canConstruct(String ransomNote, String magazine) {// shortcutif (ransomNote.length() > magazine.length()) {return false;}// 定义一个哈希映射数组int[] record = new int[26];// 遍历for(char c : magazine.toCharArray()){record[c - 'a'] += 1;}for(char c : ransomNote.toCharArray()){record[c - 'a'] -= 1;}// 如果数组中存在负数,说明ransomNote字符串中存在magazine中没有的字符for(int i : record){if(i < 0){return false;}}return true;}
    }

    总结

  • 增强型for循环

    • for(char c:magazine.toCharArray())[record[c-‘a’]++;
  • 字符的用法magazine.charAt(i) 单个字符 magazine.charAt(i)多个字符

  • 初步判断要加上,如果ransomNote.length() > magazine.length,就不用进行下去了

15.三数之和

题目

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != 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] 。
注意,输出的顺序和三元组的顺序并不重要。
* `3 <= nums.length <= 3000`
* `-105 <= nums[i] <= 105`

思路

  • 我的思路
    • 难点在于不能重复,不能暴力循环。
    • 选择数据结构,map,key value,遍历一遍,value为值出现的次数。
  • 代码思路
    • 数据结构 数组
    • 排序+双指针+去重(这道题挺难的)
  • 盲写一遍代码
  • 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(nums[i]>0){return result;}//特殊情况if(i>0&&nums[i]==nums[i-1]){continue;}//为什么不管他//定义范围int left=i+1;int right=nums.length-1;while(right>left){int sum=nums[i]+nums[left]+nums[right];if(sum>0){right--;}else if(sum<0){left++;}else{result.add(Arrays.asList(nums[i],nums[left],nums[right]));//去重b,cwhile (right > left && nums[right] == nums[right - 1]) right--;while (right > left && nums[left] == nums[left + 1]) left++;right--; left++;}}}return result;}
    }

出现问题

  • 动态的二维列表怎么定义的,<>菱形语法,List <List<Integer>> result=new ArrayList<>()
  • 注意写前提特殊情况
    • 当第一个数>0直接返回结果
  • 排序
    • Arrays.sort(nums);
  • 去重【两个地方的去重】
    • 去重a
      • 注意是nums[i]==nums[i+1]还是i-1,和left不一样,是i-1
      • 需要确保当前值如果和过去的值相等,就不用重复了,如果是i+1,那么还是重复了i+1后计算后,多重复了一次
    • 去重b,c
      • 之所以用while,是因为要一次性跳过所有重复值为止
      • // 去重 b 和 c
        while (right > left && nums[right] == nums[right - 1]) right–;
        while (right > left && nums[left] == nums[left + 1]) left++;
      • 之所以是这样,是因为要先保存当前的值,保存完之后,在和下一个值进行比较
      • 指针是从前往后的
  • while和if的区别
特性whileif
功能用于重复执行某些语句,直到条件不满足。用于判断条件是否成立,成立则执行一次语句块。
循环性是循环结构,会反复检查条件并执行语句块。是分支结构,条件成立时执行一次语句块,不会重复。
条件的检查每次循环前都会检查条件。条件检查一次,只决定是否执行语句块。

18.四数之和

题目

题意:给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。【第2个题是等于0,这个是等于target】

注意:

答案中不可以包含重复的四元组。

示例: 给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]

思路我的思yi题眼:不重复,target

    • 排序,循环a,去重a
      • b到c一个区间,c到d一个区间
      • c向左,d从末尾向前到一半。
      • target>0时
        • cwang
    • 再套一层循环,
  • Karl
    • 2层for循环,k,i,left,right
    • 剪支 注意:不能像三数之和那样判断,nums[i]>target,如果有负数的话,两数相加更小,比如-3,-3,0,0<-5
    • 2个剪支
    • 3个去重
  • class Solution {public List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> results=new ArrayList<>();Arrays.sort(nums);for(int k=0;k<nums.length;k++){//1剪枝 target包含0if(nums[k]>target&&target>=0){break;}  //1去重 if(k>0&&nums[k]==nums[k-1]){continue;}for(int i=k+1;i<nums.length;i++){if(nums[k]+nums[i]>target&&nums[k] + nums[i] >= 0){//二级剪枝,要把两个加一起,必须保证两数之和>0,如果-2-3>-6,不能让停止。break;}if(i>k+1&&nums[i]==nums[i-1]){//二级去重,注意i>k+1开始continue;}int left=i+1;int right=nums.length-1;while(right>left){//终止条件不要忘了加int sum=nums[i]+nums[k]+nums[left]+nums[right];if(sum>target){right--;}if(sum<target){left++;}if (sum==target){results.add(Arrays.asList(nums[k],nums[i],nums[left],nums[right]));//去重,需要加上条件right > left,不然会报错while(right > left&&nums[left]==nums[left+1]){left++;}//加前面的条件是防止跳过的时候交错了一遍去重while(right > left&&nums[right]==nums[right-1]){right--;}left++;right--;}}  }}return results;}
    }
    

易错点

  • ArrayList和Arrays的使用区别:

    • ArrayList,建立列表
    • Arrays,使用一些方法,.sort()排序,.asList是将数放在列表中
  • 2次剪枝的条件

    • 外:>target且target>=0,避开负数的target
    • 内:两数之和的剪枝,同时两数之和要>=0,不然会出错,例如:-2-3>-6
  • 3次去重

    • 第3次去重,是放在sum==target里的,不要放在外面。注意要right>left,如果省略的话,会交错一遍
    • while(right > left&&nums[left]==nums[left+1]){left++;}//加前面的条件是防止跳过的时候交错了一遍去重
    • while(right > left&&nums[right]==nums[right-1]){right–;}
    • left++;right–;

http://www.ppmy.cn/news/1558245.html

相关文章

Google AdMob广告变现常见违规行为排查

AdMob类似国内的穿山甲、优量汇等广告平台&#xff0c;可帮助APP开发者快速实现广告变现。对海外应用广告变现而言&#xff0c;AdMob是商业化的必接入平台。为了让防止AdMob账号被限流的问题&#xff0c;开发者要从根源入手解决。#AdMob# &#xff08;一&#xff09;广告点击率…

VSCode 插件开发实战(六):配置自定义状态栏

前言 VSCode 作为一款功能强大的代码编辑器&#xff0c;以其高度的可扩展性和丰富的插件生态系统而备受开发者青睐。在现代软件开发中&#xff0c;定制化和高效是提高生产力的关键。本文将详细介绍如何通过自定义插件在 VSCode 的状态栏中添加专属的功能项&#xff0c;帮助开发…

数据分析的分类和EDIT思维框架

为了服务于企业不同层次的决策&#xff0c;商业数据分析过程需要提供相应的数据科学产出物。 一般而言&#xff0c;数据分析需要经历从需求层、数据层、分析层到输出层四个阶段。 第一个阶段是需求层——确定目标&#xff0c;具体目标需要依据具体的层次进行分析&#xff1a…

地理数据库Telepg面试内容整理-分布式与高可用

在 Telepg 地理数据库 的应用场景中,尤其是在处理大规模地理数据时,分布式架构 和 高可用性(HA)设计 是确保系统可扩展性、容错性和高性能的关键。以下是分布式架构和高可用性设计的详细指南,涵盖了数据库分布式存储、数据分片、负载均衡、容错机制等方面的最佳实践。 分布…

Vue3 +Element-Plus el-select下拉菜单样式(局部生效)

下拉框代码 <el-selectclass"buttons-switch-group select-hub":teleported"false"style"width: 120px"v-model"queryParam.type"placeholder"请选择"size"mini"change"loadData"><el-option…

【每日学点鸿蒙知识】大图性能问题、WebView加载网页问题、H5页面数据更新问题、安全控件位置影响数据保存、企业内部应用发布

1、Image大图使用了.blur会有性能问题&#xff0c;有没有平替方案&#xff1f; 参考demo&#xff1a; async aboutToAppear(): Promise<void> {let OutData: http.HttpResponsehttp.createHttp().request("http:myURL.jpg",(error: BusinessError, data: htt…

echarts地图可视化展示

地图可视化展示 获取地图json数据下载json数据代码示例 获取地图json数据 全国各地市json文件下载地址&#xff1a; http://datav.aliyun.com/portal/school/atlas/area_selector#&lat33.521903996156105&lng104.29849999999999&zoom4 https://hxkj.vip/demo/ech…

MySQL三层B+树能存多少条数据

参数 在InnoDB中&#xff0c;数据页的默认大小为16KB&#xff0c;可以通过修改innodb_page_size参数调整&#xff0c;真实数据存贮在聚簇索引中&#xff0c;而聚簇索引有以下的结构&#xff1a; 叶子节点页 叶子节点上存放的是完整的数据行&#xff0c;假设数据行的大小为1K…