KOKO-代码随想录算法训练营Day 8 |454 |383 |15|18
文章目录
一、454.四数相加II
1.题目
https://leetcode.cn/problems/4sum-ii/
2.代码
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer,Integer> map = new HashMap<>();
int n=nums1.length;
int res=0;
for (int i = 0; i <n ; i++) {
for (int j = 0; j <n ; j++) {
int target1=nums1[i]+nums2[j];
map.put(target1,map.getOrDefault(target1,0)+1);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j <n ; j++) {
int targer2=nums3[i]+nums4[j];
if(map.containsKey(0-targer2)&&map.get(0-targer2)>0){
res+=map.get(0-targer2);
}
}
}
return res;
}
3.总结
四数相加取遍每个下标,下标不重复则值不重复,用map存储key<(nums1[i]+nums2[j]),次数>,找两数相加等只需用map获取target-当前值,判断key是否存在即可。用map中的key是否存在判断两个数的和。
map中的value存的是次数,因为取的是每个下标中符合target的元素。
二、 383. 赎金信
1.题目
https://leetcode.cn/problems/ransom-note/
2.代码
public boolean canConstruct(String ransomNote, String magazine) {
int[] arr=new int[26];
for (int i = 0; i < ransomNote.length(); i++) {
arr[ransomNote.charAt(i)-'a']++;
}
for (int i = 0; i < magazine.length(); i++) {
arr[magazine.charAt(i)-'a']--;
}
for (int i = 0; i < arr.length; i++) {
if(arr[i]>0){
return false;
}
}
return true;
}
3.总结
和字母异位词类似,用标记数组的值>0或<0判断是否有被用完。
三. 15. 三数之和
1.题目:
https://leetcode.cn/problems/3sum/
2.代码:
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);//-4,-1,-1,0,1,2
if (nums[0] > 0 || nums[nums.length - 1] < 0) {
return res;
}
int i = 0;
while (i < nums.length) {
if (nums[i] > 0) {
return res;
}
int j = i + 1;
int k = nums.length - 1;
if (i > 0 && nums[i - 1] == nums[i]) {
i++;
continue; //i==i-1时跳过
}
while (j < k) {
int num = nums[i] + nums[j] + nums[k];
if (num < 0) {
j++;
while (j < k && nums[j - 1] == nums[j]) {
j++;
}
} else if (num > 0) {
k--;
while (j < k && nums[k +1] == nums[k]) {
k--;
}
} else {
List<Integer> temp = new ArrayList<>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[k]);
res.add(temp);
while (j < k && nums[k - 1] == nums[k]) {
k--;
}
while (j < k && nums[j + 1] == nums[j]) {
j++;
}
j++; //2,1
k--;
}
}
i++; //1
}
return res;
}
3.总结:
重点是去重,对left,对right的去重。
我在做该题时用了while,实际上for较简单,只需让i到nums.length即可,不用取到nums.length-2。
另外,不必对j和k在没取到目标值时进行剪枝,因为剪枝和得到的结果不为0时做的操作是相同的,相当于加了一次操作,所以不该在此处剪枝,应当在nums[i]+nums[j]+nums[k]=target时剪枝。
四. 18. 四数之和
1.题目:
https://leetcode.cn/problems/4sum/
2.代码:
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res=new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i <nums.length ; i++) {
if(nums[i]>target&&nums[i]>=0){
return res;
}
if(i>0&&nums[i-1]==nums[i]){
continue;
}
int j=i+1;
for (;j<nums.length; j++) {
int left=j+1;
int right=nums.length-1;
if(j>i+1&&nums[j-1]==nums[j]){
continue;
}
while (left<right){
int num=nums[i]+nums[j]+nums[left]+nums[right];
if(num<target){
left++;
}else if(num>target){
right--;
}else{
List<Integer> temp=new ArrayList<>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[left]);
temp.add(nums[right]);
res.add(temp);
while (left<right&&nums[right-1]==nums[right]){
right--;
}
while (left<right&&nums[left+1]==nums[left]){
left++;
}
right--;
left++;
}
}
}
}
return res;
}
3.总结:
四数之和,固定i,固定j,用j作为三数之和的i,继续用left,right.
剪枝时要对i剪,也要对j剪,对j剪应该是从j>i+1开始。