3、查找表相关问题
1、两类查找问题
1.1、两个数组的交集
public static int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set = new HashSet<>();
for (int i : nums1) set.add(i);
Set<Integer> res = new HashSet<>();
for (int i : nums2) {
if (set.contains(i)) res.add(i);
}
return res.stream().mapToInt(Integer::intValue).toArray();
}
1.2、两个数组的交集 II
public static int[] intersect(int[] nums1, int[] nums2) {
Map<Integer, Integer> map = new HashMap<>();
for (int i : nums1) map.put(i, map.getOrDefault(i, 0) + 1);
List<Integer> list = new ArrayList<>();
for (int i : nums2) {
if (map.getOrDefault(i, 0) != 0) {
list.add(i);
map.put(i, map.get(i) - 1);
}
}
return list.stream().mapToInt(Integer::intValue).toArray();
}
2、Set 和 Map 不同底层实现的区别
更多问题
242 - 有效的字母异位词
202 - 快乐数
290 - 单词规律
205 - 同构字符串
451 - 根据字符出现频率排序
3、两数之和
public static int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>(); // value : index
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) return new int[]{i, map.get(complement)};
else map.put(nums[i], i);
}
throw new IllegalArgumentException("The input has no solution");
}
4、灵活选择键值
4.1、四数相加 II
public static int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
// Key -> i + j, Value -> 个数
Map<Integer, Integer> map = new HashMap<>();
for (int i : nums1) {
for (int j : nums2) {
int sum = i + j;
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
}
int res = 0;
for (int k : nums3) {
for (int l : nums4) {
int sum = k + l;
res += map.getOrDefault(-sum, 0);
}
}
return res;
}
更多问题
49 - 字母异位词分组
4.2、回旋镖的数量
/**
* (i, j, k) 使得 distance(points[i], points[j]) == distance(points[i], points[k])
*/
public static int numberOfBoomerangs(int[][] points) {
int res = 0;
for (int i = 0; i < points.length; i++) {
// Key -> distance(point[i] ,point[x]), Value -> 个数
Map<Integer, Integer> map = new HashMap<>();
for (int x = 0; x < points.length; x++) {
if (x == i) continue;
int distance = getDistance(points[i], points[x]);
map.put(distance, map.getOrDefault(distance, 0) + 1);
}
for (int value : map.values()) {
if (value >= 2) res += value * (value - 1);
}
}
return res;
}
public static int getDistance(int[] pointA, int[] pointB) {
int xDiff = pointA[0] - pointB[0];
int yDiff = pointA[1] - pointB[1];
return (xDiff * xDiff) + (yDiff * yDiff);
}
更多问题
149 - 直线上最多的点数
5、滑动窗口 + 查找表
219 - 存在重复元素 II
推荐 containsNearbyDuplicate2
public static boolean containsNearbyDuplicate1(int[] nums, int k) {
// nums[l ... r] 是滑动窗口
int l = 0;
int r = Math.min(l + k, nums.length - 1);
Set<Integer> set = new HashSet<>();
for (int i = l; i <= r; i++) {
if (set.contains(nums[i])) return true;
set.add(nums[i]);
}
while (r + 1 < nums.length) {
set.remove(nums[l++]);
r++;
if (set.contains(nums[r])) return true;
set.add(nums[r]);
}
return false;
}
public static boolean containsNearbyDuplicate2(int[] nums, int k) {
Set<Integer> set = new HashSet<>(); // 窗口大小为 k + 1
for (int i = 0; i < nums.length; i++) {
if (set.contains(nums[i])) return true;
else set.add(nums[i]);
// 保持 set 中最多有 k 个元素
if (set.size() == k + 1) set.remove(nums[i - k]);
}
return false;
}
更多问题
217 - 存在重复元素
6、二分搜索树底层实现的顺序性
public static boolean containsNearbyAlmostDuplicate1(int[] nums, int indexDiff, int valueDiff) {
TreeSet<Long> set = new TreeSet<>(); // 窗口大小为 indexDiff + 1
for (int i = 0; i < nums.length; i++) {
// [min ... max] = [num - valueDiff ... num + valueDiff]
int num = nums[i];
long min = num - valueDiff;
long max = num + valueDiff;
Long ceiling = set.ceiling(min);
if (ceiling != null && ceiling <= max) return true;
else set.add((long) num);
// 保持 set 中最多有 indexDiff 个元素
if (set.size() == indexDiff + 1) set.remove((long) nums[i - indexDiff]);
}
return false;
}
public static boolean containsNearbyAlmostDuplicate2(int[] nums, int indexDiff, int valueDiff) {
TreeSet<Long> set = new TreeSet<>(); // 窗口大小为 indexDiff + 1
for (int i = 0; i < nums.length; i++) {
// [min ... max] = [num - valueDiff ... num + valueDiff]
int num = nums[i];
long min = num - valueDiff;
long max = num + valueDiff;
Long floor = set.floor(max);
if (floor != null && floor >= min) return true;
else set.add((long) num);
if (set.size() == indexDiff + 1) set.remove((long) nums[i - indexDiff]);
}
return false;
}
本文来自博客园,作者:lidongdongdong~,转载请注明原文链接:https://www.cnblogs.com/lidong422339/p/17382802.html