1、383. 赎金信
跟昨天的题大同小异,因为只有26个字母,所以可以建个有26个坑位的数组。
做完昨天的题目,这个题没啥新意。
class Solution {public boolean canConstruct(String ransomNote, String magazine) {int[] hashTable = new int[26];char[] chars1 = ransomNote.toCharArray();char[] chars2 = magazine.toCharArray();for(char c : chars2){hashTable[c - 'a']++;}for(char c : chars1){if(hashTable[c - 'a'] == 0){return false;}hashTable[c-'a']--;}return true;}
}
2、454. 四数相加 II
开始上强度了,200个数据,直接暴力,200的4次方不行。
可以把四层for拆成两层,把nums1和nums2求和得到的数据放到它们的哈希表中,value记录出现的次数。这样就拆成两个哈希表了,遍历一个哈希表,那么-key就是另一个哈希表中需要存在的值,如果存在,这两个哈希表的value之积就是一个解。
举例说明:key1=-1, value1=2 和 key2=1, value=3
那是不是意味着有:-1 -1, 1 1 1。对每个-1来说,都能找到3个1。所以有2*3个。
class Solution {public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {HashMap<Integer, Integer> map1 = new HashMap<>();HashMap<Integer, Integer> map2 = new HashMap<>();int ans = 0;merge(nums1, nums2, map1);merge(nums3, nums4, map2);for(int x : map1.keySet()){int target = -x;if(map2.containsKey(target)){ans += map1.get(x)*map2.get(target);}}return ans;}public void merge(int[] a1, int[] a2, HashMap<Integer, Integer> map){for(int x : a1){for(int y : a2){int n = x+y;if(map.containsKey(n)){map.put(n, map.get(n)+1);}else{map.put(n, 1);}}}}
}
3、15. 三数之和
第一次是这么做的,不对。
思路来自上一题,但是我再想如何去重呢?总不能查一次List中有没有nums[i]、nums[j]、nums[k]的组合吧,想了很久没想出来。
class Solution {public List<List<Integer>> threeSum(int[] nums) {ArrayList<List<Integer>> list = new ArrayList<>();HashMap<Integer, Integer> map = new HashMap<>();for(int i = 0; i < nums.length; i++){//记录最后一次的下标map.put(nums[i], i);}for(int i = 0; i < nums.length; i++){for(int j = i+1; j < nums.length; j++){if(map.containsKey(-nums[i]-nums[j])){int k = map.get(-nums[i]-nums[j]);if(k != i && k != j){list.add(List.of(nums[i], nums[j], nums[k]));}}}}return list;}
}
参考了另一种巧妙的思路,双指针。
先给数组排个序。
然后遍历数组,i就是遍历的元素,j和k是双指针,通过移动j和k来取得答案。
思路到这里,那么和上面的代码没啥区别,所以核心还是想如何去重。
因为是排完序的,那么我只需要保证i和上一个元素不相等即可,如下图,如果i和上一个元素相等,说明接下来得到的值肯定都是重复的。
然后是对nums[j]和nums[k]去重,比如这种的,会找到两组(-1, 0, 1)。
所以每次找完之后,都要不停地移动j,直到与上一个元素不同,k同理。
class Solution {public List<List<Integer>> threeSum(int[] nums) {ArrayList<List<Integer>> list = new ArrayList<>();int j = 0, k = 0;Arrays.sort(nums);for(int i = 0; i < nums.length-2; i++){if(nums[i] > 0){//第一个都大于0,那肯定加不成0了。break;}if(i > 0 && nums[i] == nums[i-1]){//去重nums[i]continue;}j = i+1;k = nums.length-1;while(j < k){if(nums[j] + nums[k] + nums[i] == 0){list.add(List.of(nums[i], nums[j], nums[k]));while(j<nums.length-1 && nums[j] == nums[j+1]) j++;//去重nums[j]while(k>i && nums[k] == nums[k-1]) k--;//去重nums[k]j++;k--;}else if(nums[j] + nums[k] + nums[i] > 0){k--;}else if(nums[j] + nums[k] + nums[i] < 0){j++;}}}return list;}
}