1. 程式人生 > >[LeetCode] Contains Duplicate II 包含重複值之二

[LeetCode] Contains Duplicate II 包含重複值之二

Given an array of integers and an integer k, return true if and only if there are two distinct indices i and j in the array such that nums[i] = nums[j] and the difference between i and j is at most k. (Old Version)

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 difference between i and j is at most k. (New Version)

這道題是之前那道Contains Duplicate 包含重複值的延伸,不同之處在於那道題只要我們判斷下陣列中是否有重複值,而這道題限制了陣列中只許有一組重複的數字,而且他們座標差不能超過k。那麼我們首先需要一個雜湊表,來記錄每個數字和其座標的對映,然後我們需要一個變數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。個人認為正確的解法應該入下:

// Wrong Soulution
class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        unordered_map<int, int> m;
        int d = 0;
        for (int i = 0; i < nums.size(); ++i) {
            if (m.find(nums[i]) != m.end()) {
                if
(d > 0) return false; d = i - m[nums[i]]; } m[nums[i]] = i; } return d == 0 ? false : d <= k; } };

坑爹啊,題目要求變了,那麼就沒啥歧義了,正確解法如下:

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

相似題目: