代码随想录算法训练营Day07| 454. 四数相加Ⅱ 383.赎金信 15.三数之和 18.四数之和

454.四数相加Ⅱ

先看了视频,理解之后做出来的

 1 var fourSumCount = function(nums1, nums2, nums3, nums4) {
 2     let map = new Map();
 3     for (let a = 0; a < nums1.length; a++) {
 4         for (let b = 0; b < nums2.length; b++) {
 5 
 6             let value = map.has(nums1[a] + nums2[b]) ? map.get(nums1[a] + nums2[b]) + 1 : 1;
 7             map.set(nums1[a] + nums2[b], value); //是否已有这个键,有则value+1,无则传入value为1;
 8         }
 9     }
10     let count = 0; //用于储存,有多少个符合条件的元组  数量
11     for (let c = 0; c < nums3.length; c++) {
12         for (let d = 0; d < nums4.length; d++) {
13             for (const [Key, value] of map.entries()) { //遍历并读取map中的键值对
14                 if (Key === -(nums3[c] + nums4[d])) {
15                     count += value;
16                 }
17             }
18         }
19     }
20     return count;
21 };
View Code

注意:

1.map.entries() – returns an iterable for entries [key, value], it’s used by default in for..of.

2. 三元条件运算符中,不可以使用自增运算符(++),例如

 1 map.has(nums1[a] + nums2[b]) ? map.get(nums1[a] + nums2[b]) + + : 1; 2 // 是错误的 

不管是 前置(++map.get(nums1[a] + nums2[b])),还是后置(map.get(nums1[a] + nums2[b])++),因为三目条件运算符中没有其它运算,所以返回的依旧只是map.get(nums1[a] + nums2[b])的值,并无改变。

关于操作符前置和后置,不是什么情况下都可以用的,具体解释可以参考该篇文章:https://juejin.cn/post/7042101620380794917

383.赎金信

这题比较简单,思考步骤,以及代码如下:

 1 /**
 2  * @param {string} ransomNote
 3  * @param {string} magazine
 4  * @return {boolean}
 5  */
 6 var canConstruct = function(ransomNote, magazine) {
 7     let mapA = new Map();
 8     // 在mapA中存储ransomNote的所有字符,字符为key,出现次数为value;
 9     for (let letter of ransomNote) {
10         if (mapA.has(letter)) {
11             mapA.set(letter, mapA.get(letter) + 1);
12         } else {
13             mapA.set(letter, 1)
14         }
15     }
16     // 遍历magazine,如果mapA中存在该字符,则对应的value-1
17     for (let letter of magazine) {
18         if (mapA.has(letter)) {
19             mapA.set(letter, mapA.get(letter) - 1);
20         }
21     }
22     // 遍历mapA,如果mapA中存在该字符的value > 0,则说明有字符不能由magazine中的字符构成,直接返回false
23     for (const [key, value] of mapA.entries()) {
24         if (value > 0) {
25             return false;
26         }
27     }
28     // 否则,返回true
29     return true;
30 };
View Code

15.三数之和

先看视频,再自己做出来

方法:双指针法

 1 /**
 2  * @param {number[]} nums
 3  * @return {number[][]}
 4  */
 5 var threeSum = function(nums) {
 6     // 首先,进行排序
 7     //nums.sort();
 8     nums.sort((a, b) => a - b)
 9     let arr = new Array();
10     for (let i = 0; i < nums.length; i++) {
11         if (nums[i] > 0) return arr; //如果最小的数>0,则不可能有=0的三数之和,直接返回false
12         if (i > 0 && nums[i] === nums[i - 1]) { continue; }
13         let left = i + 1;
14         let right = nums.length - 1;
15         while (right > left) {
16             if (nums[left] + nums[right] + nums[i] > 0) right--;
17             else if (nums[left] + nums[right] + nums[i] < 0) left++;
18             else {
19                 arr.push([nums[i], nums[left], nums[right]]);
20                 // 开始去重
21                 while (left < right && nums[left] === nums[left + 1]) {
22                     left += 1;
23                 }
24                 while (left < right && nums[right] === nums[right - 1]) {
25                     right -= 1;
26                 }
27                 // 双指针收缩
28                 right--;
29                 left++;
30             }
31         }
32     }
33     return arr;
34 };
View Code

18. 四数之和

先看了视频

注意以下几点:

  1. 一级剪枝
    1.   
      1 if (nums[k] > target && (nums[k] > 0 || target >= 0)) break;
      2 //注意target 可能<0,若target<0,nums[k]>targert,而nums[k]+nums[k+1]<targer或=target 的可能是存在的!
      3 //故 补充条件:要么nums[k]>0 要么target>=0
  2. 二级剪枝
    1.    1 if (nums[k] + nums[i] > target && (nums[k] + nums[i] >= 0)) break; 2 // 注意此时是 nums[k] + nums[i] 作为整体与target比较

代码如下:

 1 /**
 2  * @param {number[]} nums
 3  * @param {number} target
 4  * @return {number[][]}
 5  */
 6 var fourSum = function(nums, target) {
 7     nums.sort((a, b) => a - b)
 8     let arr = new Array();
 9     for (let k = 0; k < nums.length; k++) {
10         // 一级剪枝处理
11         if (nums[k] > target && (nums[k] > 0 || target >= 0)) break;
12         // 对num[k]去重
13         if (k > 0 && nums[k] === nums[k - 1]) continue;
14 
15         for (let i = k + 1; i < nums.length; i++) {
16             // 二级剪枝
17             if (nums[k] + nums[i] > target && (nums[k] + nums[i] >= 0)) break;
18             // 对num[i]去重
19             if (i > k + 1 && nums[i] === nums[i - 1]) continue;
20 
21             let left = i + 1;
22             let right = nums.length - 1;
23 
24             while (left < right) {
25                 if (nums[i] + nums[k] + nums[left] + nums[right] > target) right--;
26                 else if (nums[i] + nums[k] + nums[left] + nums[right] < target) left++;
27                 else {
28                     arr.push([nums[k], nums[i], nums[left], nums[right]]);
29 
30                     // 去重
31                     while (left < right && nums[right] === nums[right - 1]) right--;
32                     while (left < right && nums[left] === nums[left + 1]) left++;
33 
34                     // 双向收缩
35                     left++;
36                     right--;
37                 }
38             }
39         }
40     }
41     return arr;
42 };
View Code

收获

刷题顺利,开始喜欢上刷题了!

posted @ 2023-08-29 22:30  子酱  阅读(77)  评论(0)    收藏  举报