Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.
Example 1:
Input: nums = [1,2,3,1], k = 3 Output: true
Example 2:
Input: nums = [1,0,1,1], k = 1 Output: true
Example 3:
Input: nums = [1,2,3,1,2,3], k = 2 Output: false
這道題是之前那道 Contains Duplicate 的延伸,不同之處在於那道題只要判斷下數組中是否有重復值,而這道題限制了數組中只許有一組重復的數字,而且其坐標差不能超過k。首先需要一個 HashMap,來記錄每個數字和其坐標的映射,然后需要一個變量d來記錄第一次出現重復數字的坐標差。由於題目要求只能有一組重復的數字,所以在遇到重復數字時,首先判斷d是否已經存了值,如果d已經有值了,說明之前有過了重復數字,則直接返回 false 即可。如果沒有,則此時給d附上值。在網上看到有些解法在這里就直接判斷d和k的關系然后返回結果了,其實這樣是不對的。因為題目要求只能有一組重復數,就是說如果后面又出現了重復數,就沒法繼續判斷了。所以正確的做法應該是掃描完整個數組后在判斷,先看d有沒有存入結果,如果沒有,則說明沒出現過重復數, 返回 false 即可。如果d有值,再跟k比較,返回對應的結果。OJ 的 test case 沒有包含所有的情況,比如當 nums = [1, 2, 3, 1, 3], k = 3 時,實際上應該返回 false,但是有些返回 true 的算法也能通過 OJ,個人認為正確的解法應該如 評論區十二樓 所示,但是由於后來題目要求變了,那么就沒啥歧義了,正確解法如下:
class Solution { public: bool containsNearbyDuplicate(vector<int>& nums, int k) { unordered_map<int, int> m; for (int i = 0; i < nums.size(); ++i) { if (m.find(nums[i]) != m.end() && i - m[nums[i]] <= k) return true; else m[nums[i]] = i; } return false; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/219
類似題目:
參考資料:
https://leetcode.com/problems/contains-duplicate-ii/
https://leetcode.com/problems/contains-duplicate-ii/discuss/61372/Simple-Java-solution