3、查找表相关问题

内容来自刘宇波老师玩转算法面试

1、两类查找问题

image

1.1、两个数组的交集

349 - 两个数组的交集

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

350 - 两个数组的交集 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 不同底层实现的区别

image
image

更多问题
242 - 有效的字母异位词
202 - 快乐数
290 - 单词规律
205 - 同构字符串
451 - 根据字符出现频率排序

3、两数之和

1 - 两数之和

image

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");
}

更多问题
15 - 三数之和
18 - 四数之和
16 - 最接近的三数之和

4、灵活选择键值

4.1、四数相加 II

454 - 四数相加 II

image

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、回旋镖的数量

447 - 回旋镖的数量

image

/**
 * (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

image

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、二分搜索树底层实现的顺序性

220 - 存在重复元素 III

image

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;
}
posted @ 2023-05-08 18:35  lidongdongdong~  阅读(8)  评论(0编辑  收藏  举报