454.四数相加II
初始思路:
暴力解法!四重循环!但是无法暴力,暴力会超出时间限制
题解复盘:
四重循环的时间复杂度是n的四次方,有两数之和我们联想到两重循环可以有一个map中存遍历过的数字简化为1重循环,那么四重循环也可用一个map存遍历过的数字简化为3重循环,当然这还不够简单,仍然可以用一个map存遍历过的两数之后,这样时间的复杂度就可简化为n的平方。
- 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
- 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
- 定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
- 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
- 最后返回统计值 count 就可以了
class Solution { public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) { HashMap<Integer,Integer> hm = new HashMap<>(); for(int i = 0;i<nums1.length;i++){ for(int j = 0;j<nums2.length;j++){ int sum = nums1[i] + nums2[j]; if(hm.containsKey(sum)){ int value = hm.get(sum); value = value + 1; hm.put(sum, value); } else{ hm.put(sum,1); } } } int count = 0; for(int i = 0;i<nums3.length;i++){ for(int j = 0;j<nums4.length;j++){ int target = 0-nums3[i] - nums4[j]; if(hm.containsKey(target)){ int value = hm.get(target); count = count + value; } } } return count; } }
383. 赎金信
初始思路&&题解复盘:
跟有效的字母异位词基本一致,唯一的更改就是遍历数组时条件改为如果有地方<0,return false即可
15. 三数之和
初始思路:
梦破碎的地方,首先肯定是按照两数之和的逻辑,用target = 0-nums[i]-nums[j];然后找出所有的三元组,再进行去重,很明显去重失败了
题解复盘:
复习一些Arrays语法:
Arrays.asList():Arrays.asList() 详解-CSDN博客
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[right]+nums[left];
if(sum>0){right--;}
else if(sum<0){left++;}
else{
result.add(Arrays.asList(nums[i],nums[left],nums[right]));
while(right>left&&nums[right-1]==nums[right]){right--;}
while(right>left&&nums[left+1]==nums[left]){left++;}
right--;
left++;
}
}
}
return result;
}
}
注意这里不能写成if(sum>0)right--if(sum<0)left++这样就会导致是在移动之后进入下一个if,逻辑就会出现问题。
18. 四数之和
同三数之和解法,两层for循环,但有一些细节需要修改。
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++) {
// nums[i] > target 直接返回, 剪枝操作
if (nums[i] > 0 && nums[i] > target) {
return result;
}
if (i > 0 && nums[i - 1] == nums[i]) { // 对nums[i]去重
continue;
}
for (int j = i + 1; j < nums.length; j++) {
if (j > i + 1 && nums[j - 1] == nums[j]) { // 对nums[j]去重
continue;
}
int left = j + 1;
int right = nums.length - 1;
while (right > left) {
// nums[k] + nums[i] + nums[left] + nums[right] > target int会溢出
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
if (sum > target) {
right--;
} else if (sum < target) {
left++;
} else {
result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
// 对nums[left]和nums[right]去重
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
left++;
right--;
}
}
}
}
return result;
}
}
1.剪枝处的修改。
// nums[i] > target 直接返回, 剪枝操作
if (nums[i] > 0 && nums[i] > target) {
return result;
}
2. j的去重
if (j > i + 1 && nums[j - 1] == nums[j]) { // 对nums[j]去重
continue;
}
3.int变为long(这里就是有一个测试范例过不去的原因)
// nums[k] + nums[i] + nums[left] + nums[right] > target int会溢出
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];