参考文献链接:代码随想录
本人代码是Java版本的,如有别的版本需要请上代码随想录网站查看。
昨天中秋节偷懒了一天,今天补上第六天的题目。
第454题.四数相加II
解题思路
四数相加求和为0,我们把四个数组分成两个两个。前两个数组遍历求和并放入map集合,<和值,出现次数>。
然后去遍历后两个数组,算出 0 - 数组3的值 - 数组4的值,算出的这个值去看map集合是否存在,存在的话说明满足题意和为0.
代码示例
getOrDefault是Map集合的一个api,他的意思是如果能从map集合get到值就get否则给一个默认返回值。
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer,Integer> firstMap = new HashMap<>();
for(int i = 0;i < nums1.length;++i){
for(int j = 0;j < nums2.length;++j){
int temp = nums1[i] + nums2[j];
firstMap.put(temp, firstMap.getOrDefault(temp, 0) + 1);
}
}
int count = 0;
for(int i = 0;i < nums3.length;++i){
for(int j = 0;j < nums4.length;++j){
int temp = 0 - nums3[i] - nums4[j];
count = count + firstMap.getOrDefault(temp, 0);
}
}
return count;
}
}
383. 赎金信
解题思路
这道题目还是很容易的,一看到某个元素是否在某个地方存在这种题就用哈希表,再判断他需不需要map,因为这道题某个字母可以出现好几次,所以需要map的value去存次数。
代码示例
现把magazine每个字母出现的次数存入map,遍历ransomNote去看map中有没有,每判断完一次就让map中的次数减一,如果某次判断map中没有该字母,那就返回false。
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
Map<Character,Integer> map = new HashMap<>();
for(int i = 0;i < magazine.length();++i){
char temp = magazine.charAt(i);
map.put(temp,map.getOrDefault(temp,0) + 1);
}
for(int i = 0;i < ransomNote.length();++i){
char temp = ransomNote.charAt(i);
int result = map.getOrDefault(temp,0) - 1;
if(result < 0){
return false;
}
map.put(temp,result);
}
return true;
}
}
第15题. 三数之和
解题思路
这道题目是一个数组中要找到三个数相加为0,那就很复杂了呀,如何还用哈希表的话重复的情况不太好找。
做的时候思考了很久也不知道怎么解决,后来看了代码随想录发现了种好理解的办法,双指针法。
双指针
我们先把数组排序,然后套一层for循环(i++),在i+1的位置设置左指针,在数组末尾设置右指针。
那么指针如何移动?
如果当前情况三数之和>0,说明我们要减小,right–。如果<0,left++。这下知道为什么数组要排序了吧。
代码示例
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
for(int i = 0;i<nums.length;i++){
if(nums[i]>0){
return list;
}
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){
right--;
}else if(nums[i] + nums[left] + nums[right] < 0) {
left++;
}else{
List<Integer> integer = new ArrayList();
integer.add(nums[i]);
integer.add(nums[left]);
integer.add(nums[right]);
list.add(integer);
while(right>left&&nums[right]==nums[right-1]){
right--;
}
while(right>left&&nums[left]==nums[left+1]){
left++;
}
right--;
left++;
}
}
}
return list;
}
}
第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++){
if (nums[i] > 0 && nums[i] > target) {
return result;
}
if(i>0&&nums[i]==nums[i-1]){
continue;
}
for(int j = i+1;j<nums.length;j++){
if(j>i+1&&nums[j]==nums[j-1]){
continue;
}
int left = j+1;
int right = nums.length-1;
while(right>left){
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
if(sum > target){
right--;
}else if(sum < target){
left++;
}else{
List<Integer> re = new ArrayList<>();
re.add(nums[i]);
re.add(nums[j]);
re.add(nums[left]);
re.add(nums[right]);
result.add(re);
while(right>left && nums[right] == nums[right-1]){
right--;
}
while(right>left && nums[left] == nums[left+1]){
left++;
}
left++;
right--;
}
}
}
}
return result;
}
}