[LeetCode] 1182. Shortest Distance to Target Color
You are given an arraycolors
, in which there are three colors:1
,2
and3
.
You are also given some queries. Each query consists of two integersi
andc
, returnthe shortest distance between the given indexi
and the target colorc
. 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 }