代码随心录第七天|Leecode 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和

Leecode 454.四数相加II

题目描述:https://leetcode.cn/problems/4sum-ii/description/

 思路:不需要去重。

1.首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
2.遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
3.定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
4.再遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
5.最后返回统计值 count 就可以了

 

假设  A = [1, 2, 3] , B = [-1, -2, -3] , C = [4, 5] , D = [-4, -5] 。

统计  A  和  B  数组元素和的出现次数:

- 当  a = 1 , b = -1  时, a + b = 0 , umap[0] = 1 。

- 当  a = 1 , b = -2  时, a + b = -1 , umap[-1] = 1 。

- 当  a = 1 , b = -3  时, a + b = -2 , umap[-2] = 1 。

- 当  a = 2 , b = -1  时, a + b = 1 , umap[1] = 1 。

- 当  a = 2 , b = -2  时, a + b = 0 , umap[0] = 2 。

- 当  a = 2 , b = -3  时, a + b = -1 , umap[-1] = 2 。

- 当  a = 3 , b = -1  时, a + b = 2 , umap[2] = 1 。

- 当  a = 3 , b = -2  时, a + b = 1 , umap[1] = 2 。

- 当  a = 3 , b = -3  时, a + b = 0 , umap[0] = 3 。

统计满足条件的四元组数量:

- 遍历  C  和  D  数组:

- 当  c = 4 , d = -4  时, 0 - (c + d) = 0 , count += umap[0] , count  变为  3 。

- 当  c = 4 , d = -5  时, 0 - (c + d) = 1 , count += umap[1] , count  变为  5 。

- 当  c = 5 , d = -4  时, 0 - (c + d) = -1 , count += umap[-1] , count  变为  7 。

- 当  c = 5 , d = -5  时, 0 - (c + d) = 0 , count += umap[0] , count  变为  10 。

- 最终  count = 10 ,即满足  a + b + c + d = 0  的四元组有 10 个。

 

Leecode 383. 赎金信 

题目描述:https://leetcode.cn/problems/ransom-note/description/

 思路:解法一----for循环;解法二---哈希表(字母异位词的变式)。

解答:

解法一:

 解法二:

 

假设  ransomNote = "aab" , magazine = "aabb" 。

初始化

首先,定义了长度为26的数组  record  并初始化为  {0} ,用于记录  magazine  中每个字母出现的次数。

初步判断

 ransomNote.size()  为3, magazine.size()  为4,由于  3 < 4 ,不满足  ransomNote.size() > magazine.size()  的条件,所以继续执行后续代码。

统计  magazine  中字符出现次数

执行  for (int i = 0; i < magazine.length(); i++) { record[magazine[i] - 'a']++; }  这一循环:

- 当  i = 0  时, magazine[0]  为  'a' , 'a' - 'a' = 0 ,则  record[0]++ ,此时  record  数组变为  {1, 0, 0, ..., 0} 。

- 当  i = 1  时, magazine[1]  为  'a' , 'a' - 'a' = 0 ,则  record[0]++ ,此时  record  数组变为  {2, 0, 0, ..., 0} 。

- 当  i = 2  时, magazine[2]  为  'b' , 'b' - 'a' = 1 ,则  record[1]++ ,此时  record  数组变为  {2, 1, 0, ..., 0} 。

- 当  i = 3  时, magazine[3]  为  'b' , 'b' - 'a' = 1 ,则  record[1]++ ,此时  record  数组变为  {2, 2, 0, ..., 0} 。

检查能否构建  ransomNote 

执行  for (int j = 0; j < ransomNote.length(); j++) { record[ransomNote[j] - 'a']--; if (record[ransomNote[j] - 'a'] < 0) { return false; } }  这一循环:

- 当  j = 0  时, ransomNote[0]  为  'a' , 'a' - 'a' = 0 ,则  record[0]-- ,此时  record  数组变为  {1, 2, 0, ..., 0} 。

- 当  j = 1  时, ransomNote[1]  为  'a' , 'a' - 'a' = 0 ,则  record[0]-- ,此时  record  数组变为  {0, 2, 0, ..., 0} 。

- 当  j = 2  时, ransomNote[2]  为  'b' , 'b' - 'a' = 1 ,则  record[1]-- ,此时  record  数组变为  {0, 1, 0, ..., 0} 。

在整个遍历  ransomNote  的过程中, record  数组的元素值始终没有小于0,所以遍历结束后,执行  return true ,即可以用  magazine = "aabb"  构建出  ransomNote = "aab"

 15. 三数之和

题目链接:https://leetcode.cn/problems/3sum/description/

题目描述:

 思路:解法一---哈希法(去重);解法二---双指针

解答:

解法一

解法二:

首先将数组排序,然后有一层for循环,i从下标0的地方开始,同时定一个下标left 定义在i+1的位置上,定义下标right 在数组结尾的位置上。

依然还是在数组中找到 abc 使得a + b +c =0,我们这里相当于 a = nums[i],b = nums[left],c = nums[right]。

接下来如何移动left 和right呢, 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些。

如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了,left 就向右移动,才能让三数之和大一些,直到left与right相遇为止。

 

Leecode 18. 四数之和 

 题目链接:https://leetcode.cn/problems/4sum/description/

题目描述:

 思路:

四数之和,和15.三数之和 是一个思路,都是使用双指针法, 基本解法就是在15.三数之和 (opens new window)的基础上再套一层for循环。

但是有一些细节需要注意,例如: 不要判断nums[k] > target 就返回了,三数之和 可以通过 nums[i] > 0 就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。比如:数组是[-4, -3, -2, -1],target是-10,不能因为-4 > -10而跳过。但是我们依旧可以去做剪枝,逻辑变成nums[k] > target && (nums[k] >=0 || target >= 0)就可以了。

15.三数之和 (opens new window)的双指针解法是一层for循环num[i]为确定值,然后循环内有left和right下标作为双指针,找到nums[i] + nums[left] + nums[right] == 0。

四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况,三数之和的时间复杂度是O(n^2),四数之和的时间复杂度是O(n^3) 。

解答:

 

posted @ 2025-04-11 22:26  米布丁  阅读(444)  评论(0)    收藏  举报