学习目标:
60天训练营打卡计划!
要判断一个元素是否出现在一个集合中,就要使用哈希表!
学习内容:
454.四数相加II
- 使用空间换时间的策略,将四个数组求和为两个数组。
- 要加强对map的熟悉。
- map用于记录相同的结果共出现了几次。
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer,Integer> map = new HashMap();
int size = nums1.length;
int sum1 = 0;
int sum2 = 0;
int res = 0;
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
sum1 = nums1[i]+nums2[j];
if(map.containsKey(sum1))
map.put(sum1,map.get(sum1)+1);
else
map.put(sum1,1);
}
}
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++){
sum2 = nums3[i]+nums4[j];
if(map.containsKey(0-sum2))
res += map.get(0-sum2);
}
}
return res;
}
}
383. 赎金信
- 与242.有效的字母异位词思路相似。
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
int r = ransomNote.length();
int m = magazine.length();
int[] tmp = new int[26];
if(r > m){
return false;
}
for(int i = 0; i < m; i++){
tmp[magazine.charAt(i)-'a']++;
}
for(int j = 0; j < r; j++){
tmp[ransomNote.charAt(j)-'a']--;
if(tmp[ransomNote.charAt(j)-'a'] < 0){
return false;
}
}
return true;
}
}
15. 三数之和
Java中二维数组操作:
- 创建: List<List> result = new ArrayList<>();
- 添加一个一维数组:result.add(Arrays.asList(nums[i], nums[left], nums[right]));
实现:
- 使用双指针法,在操作之前一定要排序!
-
- 难点:要对返回的二维数组进行去重操作,可分为两步。
第一步:先对第一个元素(代号a)nums[i]进行去重 – i > 0 && nums[i] == nums[i - 1]
并在i到nums.length之间使用双指针法,找到剩下的b和c。
第二步:找到第一个三元组后要对双指针两侧的数进行去重操作 – right > left && nums[right] == nums[right - 1] 和 right > left && nums[left] == nums[left + 1]
判断时:right-1 和left+1是为了防止下标越界。
- 难点:要对返回的二维数组进行去重操作,可分为两步。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
int size = nums.length;
int total = 0;
int left = 0;
int right = size - 1;
for(int i = 0; i < size-2; i++){
// 当遍历的第一个元素大于0时,
// 后续的其他组合一定没有符合结果的值了
if(nums[i] > 0) return res;
// a元素的去重操作
// 如果i++的话,会漏掉连续多个相同值的情况
if(i > 0 && nums[i] == nums[i-1]) continue;
left = i + 1;
right = size - 1;
while(left < right){
total = nums[i] + nums[left] + nums[right];
if(total > 0) right--;
else if(total < 0) left++;
else{
res.add(Arrays.asList(nums[i] ,nums[left] ,nums[right]));
// 对元素b去重
while(left < right && nums[left] == nums[left+1]) left++;
// 对元素c去重
while(left < right && nums[right] == nums[right-1]) right--;
right--;
left++;
}
}
}
return res;
}
}
18. 四数之和
- 基本逻辑都是相似的,将时间复杂度降低一次方。
- 先排序!
- 再通过对第一个值判断来进行剪枝操作,后进行第一次去重。
- 再进行第二次去重,使用continue,防止此次自增后的值缺少相应的去重。
- 找到第一个四元组时进行第三次去重。
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
int size = nums.length;
int left = 0;
int right = 0;
int sum = 0;
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0; i < size; i++){
if(nums[i] > 0 && nums[i] > target){
// 负数求和会变小!
break;
}
// 将重复的组合仅保留一次
if(i > 0 && nums[i] == nums[i - 1]){
continue;
// i++ 会缺少一次对i进行上述if判断
}
for(int j = i + 1; j < size; j++){
// 将重复的组合仅保留一次
if(j > i + 1 && nums[j] == nums[j - 1]){
continue;
// j++ 会缺少一次对j进行上述if判断
}
left = j + 1;
right = size - 1;
while(left < right){
sum = nums[i] + nums[j] + nums[left] + nums[right];
if(sum > target){
right--;
}
else if(sum < target){
left++;
}
else{
res.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
while(left < right && nums[left] == nums[left + 1]) left++;
while(right > left && nums[right] == nums[right - 1]) right--;
left++;
right--;
}
}
}
}
return res;
}
}
学习时间:
- 上午三小时,下午一小时(四数相加),整理文档半小时
- 12月12日复习,15和18题需要继续熟悉。