目录
454. 四数相加 II
给你四个整数数组
nums1
、nums2
、nums3
和nums4
,数组长度都是n
,请你计算有多少个元组(i, j, k, l)
能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
示例 1:
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2] 输出:2 解释: 两个元组如下: 1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0 2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0示例 2:
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0] 输出:1提示:
n == nums1.length
n == nums2.length
n == nums3.length
n == nums4.length
1 <= n <= 200
-228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228
状态:看了答案思路完成,一开始定nums1的值,然后遍历剩下三个数组的方式超时
思路: 把nums1和nums2的和有多少种情况用map存起来,然后在nums3和nums4中遍历并查看map里有无与其相加为0的数字若有则把val加到sum中。map.getOrDefault(key,val)这个方法可以指定默认值然后存取。
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
int sum=0;
HashMap<Integer,Integer> map = new HashMap<>();
for(int j=0;j<nums1.length;j++){
for(int k=0;k<nums2.length;k++){
if(map.containsKey(nums1[j]+nums2[k])){
map.put(Integer.valueOf(nums1[j]+nums2[k]),Integer.valueOf(map.get(nums1[j]+nums2[k])+1));
}else{
map.put(Integer.valueOf(nums1[j]+nums2[k]),Integer.valueOf(1));
}
}
}
for(int i=0;i<nums3.length;i++){
for(int j=0;j<nums4.length;j++){
if(map.containsKey(0-nums3[i]-nums4[j])){
sum+=map.get(0-nums3[i]-nums4[j]);
}
}
}
return sum;
}
}
383. 赎金信
给你两个字符串:
ransomNote
和magazine
,判断ransomNote
能不能由magazine
里面的字符构成。如果可以,返回
true
;否则返回false
。
magazine
中的每个字符只能在ransomNote
中使用一次。示例 1:
输入:ransomNote = "a", magazine = "b" 输出:false示例 2:
输入:ransomNote = "aa", magazine = "ab" 输出:false示例 3:
输入:ransomNote = "aa", magazine = "aab" 输出:true提示:
1 <= ransomNote.length, magazine.length <= 105
ransomNote
和magazine
由小写英文字母组成
状态:完成
思路:因为只有小写字母,所以直接构建长度为26的int数组arr用于存放magzine中的字符出现次数,字符-'a'则可以得到数组的下标。存放完magzine中出现次数后,遍历ransomNote,如果arr里该值大于0则arr中该下标-1,如果等于0则返回false。
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
if(ransomNote.length()>magazine.length()) return false;
int[] arr = new int[26];
char[] ransomNotes=ransomNote.toCharArray();
char[] magazines=magazine.toCharArray();
for(int i=0;i<magazines.length;i++){
arr[magazines[i]-'a']++;
}
for(int i=0;i<ransomNotes.length;i++){
if(arr[ransomNotes[i]-'a']>0){
arr[ransomNotes[i]-'a']--;
}else{
return false;
}
}
return true;
}
}
15. 三数之和
给你一个整数数组
nums
,判断是否存在三元组[nums[i], nums[j], nums[k]]
满足i != j
、i != k
且j != k
,同时还满足nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为
0
且不重复的三元组。注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。示例 2:
输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0 。示例 3:
输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0 。提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
状态:完成
思路:使用双指针的方式去解题更好,不用建立哈希表节约空间与时间。我先对数组采用升序排序,因为是要找到三个数和为0的,我们先指定一个数i,将他的值固定,以不变找变,left的初始值是i+1,right初始值是最后一个,如图一所示。
图1 |
-4是小于0,若i所对应的值大于0则不可能相加为0了,因为采用升序排。如果三个数相加如图一小于0,则left++,将结果变大。若大于0,则right--将结果变小,若等于0则将i,left,right写入数组,java可以用Arrays.asList(int,int,int,...)来快速创建数组,然后left++,right--,因为这两个值肯定不能选择了。这时注意结果数组不能有重复,如果left++/right--之后对应的值等于原先的值则一直+/-到不同样为止。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> arr = new ArrayList<>();
if(nums[0]>0) return arr;
for(int i=0;i<nums.length;i++){
while(i>0&&i<nums.length-1&&nums[i]==nums[i-1]) i++;
if(nums[i]>0) break;
int left=i+1;
int right=nums.length-1;
if(right==i) break;
while(left<right){
int sum=nums[left]+nums[right]+nums[i];
if(sum==0){
arr.add(Arrays.asList(nums[left],nums[right],nums[i]));
left++;
right--;
while(left<nums.length-1&&nums[left]==nums[left-1]) left++;
while(right>i&&nums[right]==nums[right+1]) right--;
}else if(sum>0){
right--;
}else if(sum<0){
left++;
}
}
}
return arr;
}
}
18. 四数之和
状态:缝缝补补写出来的,有两个点没注意。一是剪枝的时候把nums[a]>0的值给删了,但是这个target可以是正可以是负,导致错误。二是sum的结果溢出,要用long类型。
思路:一看到就知道是三数之和多嵌套了一层,但是实际写起来没有这么简单,问题主要就在剪枝和去重以及结果溢出。我的代码太乱了,还是要想清楚再做题,下面给出正确的思路及代码。
思路:链接https://programmercarl.com/0018.%E5%9B%9B%E6%95%B0%E4%B9%8B%E5%92%8C.html#%E6%80%9D%E8%B7%AF
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> list = new ArrayList<>();
if (nums.length < 4)
return list;
Arrays.sort(nums);
for (int a = 0; a < nums.length - 3; a++) {
while (a > 0 && nums[a] == nums[a - 1]){
a++;
if (a >= nums.length - 3) return list;
}
long sum_t = (long)target - nums[a];// b+c+d所要求的总和
int b = a + 1;
int c = b + 1;
int d = nums.length - 1;
long sum = (long)nums[b] + nums[c] + nums[d];
for (; b < d - 1; b++) {
System.out.println(a + " " + b + " " + c + " " + d + " ");
while(b!=a+1&&b<d&&nums[b]==nums[b-1]) b++;
c = b + 1;
while (b < c && c < d) {
sum = (long)nums[b] + nums[c] + nums[d];
if (sum == sum_t) {
list.add(Arrays.asList(nums[a], nums[b], nums[c], nums[d]));
c++;
d--;
while (c < d && nums[c] == nums[c - 1])
c++;
while (d > c && nums[d] == nums[d + 1])
d--;
} else if (sum > sum_t) {
d--;
} else if (sum < sum_t) {
c++;
}
}
d = nums.length - 1;
}
}
return list;
}
}
感想:今天的题目难度主要都集中于最后一题。没想到最后一题竟然这么多坑,其实就比第三题多一个循环,但是就是要想的点有很多。继续坚持下去。
标签:ransomNote,right,nums,int,Day7,sum,随想录,哈希,nums1 From: https://blog.csdn.net/SuperSwaggy/article/details/136646573