You are given an array colors
, in which there are three colors: 1
, 2
and 3
.
You are also given some queries. Each query consists of two integers i
and c
, return the shortest distance between the given index i
and the target color c
. If there is no solution return -1
.
Example 1:
Input: colors = [1,1,2,1,3,2,2,3,3], queries = [[1,3],[2,2],[6,1]] Output: [3,0,3] Explanation: The nearest 3 from index 1 is at index 4 (3 steps away). The nearest 2 from index 2 is at index 2 itself (0 steps away). The nearest 1 from index 6 is at index 3 (3 steps away).
Example 2:
Input: colors = [1,2], queries = [[0,3]] Output: [-1] Explanation: There is no 3 in the array.
Constraints:
1 <= colors.length <= 5*10^4
1 <= colors[i] <= 3
1 <= queries.length <= 5*10^4
queries[i].length == 2
0 <= queries[i][0] < colors.length
1 <= queries[i][1] <= 3
与目标颜色间的最短距离。
给你一个数组 colors,里面有 1、2、 3 三种颜色。
我们需要在 colors 上进行一些查询操作 queries,其中每个待查项都由两个整数 i 和 c 组成。
现在请你帮忙设计一个算法,查找从索引 i 到具有目标颜色 c 的元素之间的最短距离。
如果不存在解决方案,请返回 -1。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-distance-to-target-color
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题我提供一个二分法的思路,算是比较好懂吧。这道题还有一个动态规划的做法,日后有机会再补充。
这个题目问的是对于每一个 query,query[0] 代表的是要找的某个 index,query[1] 代表的是要找的 color。也就是说我们每一个 query 要找的是离某个 index 最近的 color 在哪里。注意到 input 数组是无序的,但是因为找的元素是确定的,所以我们先用一个 hashmap 把 input 数组中的不同数字在 input 数组中出现的下标记录一下。注意到对于每个元素来说,我们记录 index 的 list 最后是有序的,所以我们二分的范围也就是在这些 list 中。
所以对于一个要找的元素来说,首先我们看一下他是否存在于hashmap,如果不存在直接就返回 -1 了。如果存在,我们就在 hashmap 中找到的 list 中做二分法。注意最后二分跳出的时候需要有特判,因为要找的某个 index 很有可能在list的左边或者右边。所以最后的特判是如果左指针/右指针在合法范围内,我们再去判断哪个指针离 index 更近。
时间O(nlogn)
空间O(n)
Java实现
1 class Solution { 2 public List<Integer> shortestDistanceColor(int[] colors, int[][] queries) { 3 HashMap<Integer, List<Integer>> map = new HashMap<>(); 4 // 记录每个color的index 5 for (int i = 0; i < colors.length; i++) { 6 int c = colors[i]; 7 map.putIfAbsent(c, new ArrayList<>()); 8 map.get(c).add(i); 9 } 10 11 List<Integer> res = new ArrayList<>(); 12 for (int[] query : queries) { 13 int index = query[0]; 14 int c = query[1]; 15 // corner case 16 if (!map.containsKey(c)) { 17 res.add(-1); 18 } else { 19 res.add(binarySearch(index, map.get(c))); 20 } 21 } 22 return res; 23 } 24 25 private int binarySearch(int index, List<Integer> list) { 26 int left = 0; 27 int right = list.size() - 1; 28 // left + 1 == right when exit from while loop 29 while (left + 1 < right) { 30 int mid = left + (right - left) / 2; 31 if (list.get(mid) == index) { 32 return 0; 33 } else if (list.get(mid) < index) { 34 left = mid; 35 } else { 36 right = mid; 37 } 38 } 39 // System.out.println("left is " + left + " right is " + right); 40 int res = right; 41 if (right - 1 >= 0 && Math.abs(index - list.get(right - 1)) < Math.abs(index - list.get(right))) { 42 res = right - 1; 43 } 44 return Math.abs(list.get(res) - index); 45 } 46 }