454. 四數相加 II
// 這道題使用雜湊就可解決,使用一個map儲存前兩個陣列中,所有組合產生的sum的頻率;對於後兩個陣列中所有的組合,每出現一個和的相反數出現在map中,則代表出現了這個相反數頻率個組合可以滿足四數相加為0
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer, Integer> map12 = new HashMap<>();
for(int n1 : nums1){
for(int n2: nums2){
map12.put(n1+n2, map12.getOrDefault(n1+n2, 0) + 1);
}
}
int ans = 0;
for(int n1 : nums3){
for(int n2: nums4){
ans += map12.getOrDefault(-(n1+n2), 0);
}
}
return ans;
}
}
15. 三數之和
總體思路看了題解後會寫了,但左右指標那裡繞了我很久,一直想不明白為什麼可以保證不漏掉解。剛剛才理解。這個要從第一輪迭代開始算起,此時left = i + 1, right = nums.length - 1, 對於他們而言,沒有左側或右側的選擇。此時若sum > 0,則必然可以保證right對應的數字一定不存在與任何解(以num[i]為第一個數字)中。對於sum < 0也是相同的,所以若是指標移動,則一定可以保證,不包含這個數字的解或者已經被儲存了。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0; i < nums.length - 2; i++){
if(nums[i] > 0) return ans;
if(i > 0 && nums[i] == nums[i-1]) continue;
int left = i + 1;
int right = nums.length - 1;
while(left < right){
if(nums[i] + nums[left] + nums[right] == 0) {
ans.add(Arrays.asList(nums[i], nums[left], nums[right]));
while(left < right && nums[left]==nums[left+1]) left++;
while(left < right && nums[right]==nums[right-1]) right--;
left++; right--;
}else if(nums[i] + nums[left] + nums[right] > 0) right--;
else left++;
}
}
return ans;
}
}
18. 四數之和
三數之和會了做這個就會簡單許多,就是增加了一層迴圈。需要注意的時,題目給了nums[i]的取值範圍,$-109<nums[i]<109$,因此,四個數字之和可能越界,需要使用long來儲存結果。
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
for(int i = 0; i < nums.length - 3; i++){
if(i > 0 && nums[i]==nums[i-1]) continue;
for(int j = i+1; j < nums.length - 2; j++){
if(j > i + 1 && nums[j] == nums[j-1]) continue;
int left = j + 1, right = nums.length - 1;
while(left < right){
long sum = (long)nums[left] + nums[right] + nums[i] + nums[j]; //使用long避免越界
if(sum == target) {
ans.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
while(left < right && nums[left] == nums[left+1]) left++;
while(left < right && nums[right] == nums[right-1]) right--;
left++; right--;
}else if(sum > target) right--;
else left++;
}
}
}
return ans;
}
}