一、理论基础
-
哈希表(英文名字为Hash table,散列表):根据关键码的值而直接进行访问的数据机构。
-
场景:来快速判断一个元素是否出现集合里,牺牲空间换时间
-
哈希函数:将数据映射成hash表上的索引
-
哈希碰撞:哈希过程中,不同的输入被映射为相同的哈希值。
-
拉链法:将冲突的元素存储在链表上
-
线性探测法:在当前位置向后探测找到一个空闲的位置来存储数据
-
二、有效字母的异位词
-
题目
-
给定两个字符串
s
和t
,编写一个函数来判断t
是否是s
的字母异位词。注意:若
s
和t
中每个字符出现的次数都相同,则称s
和t
互为字母异位词。
-
-
思路
-
代码
class Solution { public boolean isAnagram(String s, String t) { int[] nums = new int[26]; for (char ch : s.toCharArray()) { nums[ch - 'a']++; } for (char ch : t.toCharArray()) { nums[ch - 'a']--; } for (int num : nums) { if (num != 0) { return false; } } return true; } }
三、两个数组的交集
-
题目
- 给定两个数组
nums1
和nums2
,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
- 给定两个数组
-
思路
-
代码
class Solution { public int[] intersection(int[] nums1, int[] nums2) { int[] array = new int[1001]; for (int nums : nums1) { array[nums]++; } List<Integer> list = new ArrayList<>(); for (int nums : nums2) { if (0 != array[nums]) { list.add(nums); array[nums] = 0; } } return list.stream().mapToInt(i -> i).toArray(); } }
四、快乐数
-
题目
-
编写一个算法来判断一个数
n
是不是快乐数。- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
-
如果
n
是 快乐数 就返回true
;不是,则返回false
。
-
-
思路
- 循环一定会重复
- 判断是否重复即可
-
代码
class Solution { public boolean isHappy(int n) { Set<Integer> set = new HashSet<>(); while (n != 1) { int sum = 0; while (n != 0) { sum += Math.pow(n % 10, 2); n /= 10; } n = sum; if (!set.add(n)) { return false; } } return true; } }
五、两数之和
-
题目
- 给定一个整数数组
nums
和一个整数目标值target
,请你在该数组中找出 和为目标值target
的那 两个 整数,并返回它们的数组下标。
- 给定一个整数数组
-
思路
-
代码
class Solution { public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { if (map.containsKey(target - nums[i])) { return new int[]{map.get(target - nums[i]), i}; } map.put(nums[i], i); } return new int[]{-1, -1}; } }
六、四数相加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
-
-
-
思路
-
代码
class Solution { public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) { Map<Integer, Integer> map = new HashMap<>(); int res = 0; for (int n1 : nums1) { for (int n2 : nums2) { map.put(n1 + n2, map.getOrDefault(n1 + n2, 0) + 1); } } for (int n3 : nums3) { for (int n4 : nums4) { res += map.getOrDefault(-n3 - n4, 0); } } return res; } }
七、赎金信
-
题目
-
给你两个字符串:
ransomNote
和magazine
,判断ransomNote
能不能由magazine
里面的字符构成。-
如果可以,返回
true
;否则返回false
。 -
magazine
中的每个字符只能在ransomNote
中使用一次。
-
-
-
思路
-
代码
class Solution { public boolean canConstruct(String ransomNote, String magazine) { int[] record = new int[26]; for (char ch : magazine.toCharArray()) { record[ch - 'a']++; } for (char ch : ransomNote.toCharArray()) { if (record[ch - 'a']-- == 0) { return false; } } return true; } }
八、三数之和
-
题目
-
给你一个整数数组
nums
,判断是否存在三元组[nums[i], nums[j], nums[k]]
满足i != j
、i != k
且j != k
,同时还满足nums[i] + nums[j] + nums[k] == 0
。\-
请你返回所有和为
0
且不重复的三元组。
-
-
-
思路
-
代码
class Solution { public List<List<Integer>> threeSum(int[] nums) { Arrays.sort(nums); List<List<Integer>> lists = new ArrayList<>(); if (nums[0] > 0 || nums[nums.length - 1] < 0) { return lists; } for (int i = 0; i < nums.length - 1; i++) { if (i > 0 && nums[i] == nums[i - 1]) { continue; } int left = i + 1; int right = nums.length - 1; while (left < right) { int a = nums[i]; int b = nums[left]; int c = nums[right]; int sum = a + b + c; if (sum == 0) { lists.add(new ArrayList<>() { { add(a); add(b); add(c); } }); while (right > left && nums[right] == nums[--right]) {} while (right > left && nums[left] == nums[++left]) {} } else if (sum > 0) { right--; } else { left++; } } } return lists; } }
九、四数之和
-
题目
-
给你一个由
n
个整数组成的数组nums
,和一个目标值target
。请你找出并返回满足下述全部条件且不重复的四元组[nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复)-
0 <= a, b, c, d < n
-
a
、b
、c
和d
互不相同 -
nums[a] + nums[b] + nums[c] + nums[d] == target
-
-
-
思路
- 第一层循环
- 找到三个数为目标值
-
代码
class Solution { public List<List<Integer>> fourSum(int[] nums, int target) { Arrays.sort(nums); List<List<Integer>> list = new ArrayList<>(); for (int i = 0; i < nums.length; i++) { 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; } if (nums[i] > target && nums[i] > 0) { return list; } int left = j + 1; int right = nums.length - 1; while (right > left) { int a = nums[i]; int b = nums[j]; int c = nums[left]; int d = nums[right]; int sum = a + b + c + d; if (sum == target) { list.add(new ArrayList<>() { { add(a); add(b); add(c); add(d); } }); while (right > left && nums[right] == nums[--right]) {} while (right > left && nums[left] == nums[++left]) {} } else if (sum > target) { right--; } else { left++; } } } } return list; } }