电信保温杯笔记——代码随想录 刷题攻略 哈希表
电信保温杯笔记——代码随想录 刷题攻略
代码随想录 刷题攻略
电信保温杯笔记——代码随想录 刷题攻略
1.关于哈希表,你该了解这些!
2.哈希表:可以拿数组当哈希表来用,但哈希值不要太大
242.有效的字母异位词
输入字符有限且比较小,使用数组比hashmap快。
class Solution {
public boolean isAnagram(String s, String t) {
int sLen = s.length();
int tLen = t.length();
if(sLen != tLen){
return false;
}
char temp = 0;
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < sLen; i++) {
temp = s.charAt(i);
map.put(temp, map.getOrDefault(temp,0) + 1);
}
for (int i = 0; i < tLen; i++) {
temp = t.charAt(i);
if(!map.containsKey(temp)){
return false;
}
map.put(temp, map.get(temp) - 1);
if(map.get(temp) < 0){
return false;
}
}
return true;
}
}
3.哈希表:查找常用字符
1002. 查找常用字符
class Solution {
public List<String> commonChars(String[] words) {
int[] minfreq = new int[26];
Arrays.fill(minfreq, Integer.MAX_VALUE);
// 用一个26位的数组记录字母在这么多个词中的最低频率
for (String word : words) {
int[] freq = new int[26];
int length = word.length();
for (int i = 0; i < length; ++i) {
char ch = word.charAt(i);
++freq[ch - 'a'];
}
for (int i = 0; i < 26; ++i) {
minfreq[i] = Math.min(minfreq[i], freq[i]);
}
}
// 打印26个字母的最低频率
List<String> ans = new ArrayList<String>();
for (int i = 0; i < 26; ++i) {
for (int j = 0; j < minfreq[i]; ++j) {
ans.add(String.valueOf((char) (i + 'a')));
}
}
return ans;
}
}
4.哈希表:哈希值太大了,还是得用set
349. 两个数组的交集
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
int length1 = nums1.length;
int length2 = nums2.length;
int[] temp = new int[length1 > length2 ? length2 : length1];
int index0 = 0;
int index1 = 0;
int index2 = 0;
while (index1 < length1 && index2 < length2) {
int num1 = nums1[index1];
int num2 = nums2[index2];
if (num1 < num2) {
index1++;
} else if (num1 > num2) {
index2++;
} else {
if (index0 == 0 || num1 != temp[index0 - 1]) {
temp[index0] = num1;
index0++;
}
index1++;
index2++;
}
}
return Arrays.copyOfRange(temp, 0, index0);
}
}
小结
先排序+集合比map要快。
使用双指针
关键:
if (index0 == 0 || num1 != temp[index0 - 1]) {
temp[index0] = num1;
index0++;
}
5.哈希表:用set来判断快乐数
202. 快乐数
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public int getNext(int n) {
int totalSum = 0;
while (n > 0) {
int d = n % 10;
n = n / 10;
totalSum += d * d;
}
return totalSum;
}
public boolean isHappy(int n) {
int slowRunner = n;
int fastRunner = getNext(n);
while (fastRunner != 1 && slowRunner != fastRunner) {
slowRunner = getNext(slowRunner);
fastRunner = getNext(getNext(fastRunner));
}
return fastRunner == 1;
}
}
小结
使用快慢指针判断是否有环,这比使用set更节省空间。
6.哈希表:map等候多时了
1. 两数之和
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; ++i) {
if (hashtable.containsKey(target - nums[i])) {
return new int[]{hashtable.get(target - nums[i]), i};
}
hashtable.put(nums[i], i);
}
return new int[0];
}
}
7.哈希表:其实需要哈希的地方都能找到map的身影
第454题.四数相加II
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
HashMap<Integer, Integer> hashMap = new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
hashMap.put(nums1[i] + nums2[j], hashMap.getOrDefault(
nums1[i] + nums2[j], 0) + 1);
}
}
int res = 0;
for (int i = 0; i < nums3.length; i++) {
for (int j = 0; j < nums4.length; j++) {
if (hashMap.containsKey(-nums3[i] - nums4[j])) {
res += hashMap.get(-nums3[i] - nums4[j]);
}
}
}
return res;
}
}
8.哈希表:这道题目我做过?
383. 赎金信
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
if (ransomNote.length() > magazine.length()) {
return false;
}
HashMap<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);
if (map.containsKey(temp)){
map.put(temp,map.get(temp)-1);
if (map.get(temp) ==0){
map.remove(temp);
}
}else {
return false;
}
}
return true;
}
}
如果使用数组来计数,而不是使用hashmap,效率会更高。
9.哈希表:解决了两数之和,那么能解决三数之和么?
第15题. 三数之和
class Solution {
public List<List<Integer>> threeSum(int[] nums) {// 总时间复杂度:O(n^2)
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length < 3) return res;
Arrays.sort(nums);
for (int i = 0; i < nums.length - 2; i++) {
// target必须大于0
if (nums[i] > 0) break;
// 去重
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1;
int right = nums.length - 1;
int target = -nums[i];
while (left < right) {
if (nums[left] + nums[right] == target) {
res.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right])));
left++;
right--;
// 去重
while (left < right && nums[left] == nums[left - 1]) left++;
// 去重
while (left < right && nums[right] == nums[right + 1]) right--;
} else if (nums[left] + nums[right] < target) {
left++;
} else {
right--;
}
}
}
return res;
}
}
10.双指针法:一样的道理,能解决四数之和
第18题. 四数之和
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length < 4) return res;
Arrays.sort(nums);
for (int i = 0; i < nums.length - 3; i++) {
// if (nums[i] > target) break;
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i+1; j < nums.length - 2; j++) {
// if (nums[j] > target - nums[i]) break;
if (j>i+1 && nums[j] == nums[j-1]) continue;
int left = j + 1;
int right = nums.length - 1;
int newTarget = target-nums[i]-nums[j];
while (left < right) {
if (nums[left] + nums[right] == newTarget) {
res.add(new ArrayList<>(Arrays.asList(nums[i],nums[j], nums[left], nums[right])));
left++;
right--;
while (left < right && nums[left] == nums[left - 1]) left++;
while (left < right && nums[right] == nums[right + 1]) right--;
} else if (nums[left] + nums[right] < newTarget) {
left++;
} else {
right--;
}
}
}
}
return res;
}
}
小结
这题与上一题解法一样
核心代码
就是上一题的代码