leetcode-zgd-day7-454.四数相加II/383.赎金信/15.三数之和/18.四数之和

900 阅读2分钟

454.四数相加II

题目链接:Loading Question... - 力扣(LeetCode)

该题目的关键点并不需要记录四个满足条件数的下标,也就是说只记录满足条件的次数即可。通过HashMap即可降低暴力求法的时间复杂度,使用Map去记录前两个数组中可能出现的数以及出现该组合的次数。再通过两层循环的方式计算后两个数组可能出现的和并去Map中查看是否有符合条件的相反数。该方法的时间复杂度降低到了O(n^2)

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

383.赎金信

题目链接:383. 赎金信 - 力扣(LeetCode)

先统计报纸中的词频,再去循环赎金信一个一个删,如果到某个词的时候发现词频已经为0了,就可以确定,报纸不足以改编出赎金信,代码实现如下:

 class Solution {
     public boolean canConstruct(String ransomNote, String magazine) {
         char[] mag = magazine.toCharArray();
         char[] ran = ransomNote.toCharArray();
         HashMap<Character,Integer> record = new HashMap<>();
         for(char c : mag){
             if(!record.containsKey(c)){
                 record.put(c,1);
             }
             else{
                 record.put(c,record.get(c) + 1);
             }
         }
         for(char c : ran){
             if(!record.containsKey(c) || record.get(c) == 0) return false;
             else{
                 record.put(c,record.get(c) - 1);
             }
         }
         return true;
     }
 }

15.三数之和

题目链接:15. 三数之和 - 力扣(LeetCode)

因为今天是Map和Set的专题,所以这里不采用双指针的方式去写,采用HashSet的方式去写,其实两种方法的本质是一样的。代码如下:

 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;
             }
             Set<Integer> record = new HashSet<>();
             for(int j = i + 1; j < nums.length; j++){
                 if(j > i + 2 && // 第三个数的去重
                     nums[j] == nums[j - 1] &&
                     nums[j] == nums[j - 2]){
                     continue;
                 }
                 int sum = 0 - (nums[i] + nums[j]); 
                 // 这里的nums[j]其实代表的是第三个数,没找到伴的第二个数存在了set当中。
                 if(record.contains(sum)){
                     result.add(Arrays.asList(nums[i],nums[j],sum));
                     record.remove(sum); // 删除第二个数
                 }else{
                     record.add(nums[j]); 
                 }
             }
         }
         return result;
     }
 }

18.四数之和

题目链接:18. 四数之和 - 力扣(LeetCode)

这个题和上面的三数之和,思路是一样的,只不过最外层又多了一层循环。这种写法多少有点稀里糊涂对了的感觉= =理的不是很清晰。先记录一下吧

 class Solution {
     public List<List<Integer>> fourSum(int[] nums, int target) {
         List<List<Integer>> result = new ArrayList<>();
         Arrays.sort(nums);
 ​
         for(int i = 0; i < nums.length; i++){ // 外面的两层普通循环只需要进行相邻元素去重即可。
             if(nums[i] > 0 && nums[i] > target){
                 return result;
             }
             if(i > 0 && nums[i] == nums[i - 1]){
                 continue;
             }
             for(int j = i + 1; j < nums.length; j++){
                 if(j > i + 1 && nums[j] == nums[j - 1]){
                     continue;
                 }
                 Set<Long> record = new HashSet<>();
                 for(int k = j + 1; k < nums.length; k++){ // 最内层的循环需要特殊处理考虑一下,
                     if(k > j + 3 && nums[k] == nums[k - 1] && nums[k] == nums[k-2] && nums[k] == nums[k-3]){
                         continue;
                     }
                     long sum = (long)target - ((long)nums[i] + nums[j] + nums[k]); // 这里nums[i]前面的long类型转换是为了避免三个数相加溢出
                     // 这里的nums[j]其实代表的是第三个数,没找到伴的第二个数存在了set当中。
                     if(record.contains(sum)){
                         result.add(Arrays.asList(nums[i],nums[j],nums[k],(int)sum));
                         record.remove(sum); // 删除第二个数
                     }else{
                         record.add((long)nums[k]);
                     }
                 }
             }
         }
         return result;
     }
 }