JS leetcode 刪除排序數組中的重復項 題解分析


壹 ❀ 引

一日一題,今天的題目來自於leetcode26. 刪除排序數組中的重復項,其實在之前我們已經做了一道類似的題目,可參考JS leetcode 移除元素 題解分析,關於本題描述如下:

給定一個排序數組,你需要在 原地 刪除重復出現的元素,使得每個元素只出現一次,返回移除后數組的新長度。

不要使用額外的數組空間,你必須在 原地 修改輸入數組 並在使用 O(1) 額外空間的條件下完成。

示例 1:

給定數組 nums = [1,1,2], 

函數應該返回新的長度 2, 並且原數組 nums 的前兩個元素被修改為 1, 2。 

你不需要考慮數組中超出新長度后面的元素
示例 2:

給定 nums = [0,0,1,1,1,2,2,3,3,4],

函數應該返回新的長度 5, 並且原數組 nums 的前五個元素被修改為 0, 1, 2, 3, 4。

你不需要考慮數組中超出新長度后面的元素

我們先來簡單分析題目,再給出解題思路。

貳 ❀ 解題思路

經過leetcode算法題移除元素的教育,這次解題得額外抓住兩個重點:

第一,題目真正的要求是獲取不重復元素的長度,所以即使不刪除重復元素也是允許的。

第二,不需要考慮數組中超出新長度后的元素,這句話的意思其實已經暗示,我們可以將不重復的元素集中在數組前面,后面的重復元素可以不管,比如

[1,2,2,3] => [1,2,3,2] 返回3,因為不重復的元素為 1,2,3

當然,我們可以先站在刪除重復元素的角度來思考這個問題,這對於前端開發者來說更容易接受,直接上代碼:

/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function (nums) {
    for (var i = 0; i < nums.length;) {
        if (nums.indexOf(nums[i]) !== i) {
            nums.splice(i, 1);
        } else {
            i++;
        };
    };
    return nums.length;
};

思路很簡單,因為indexOf獲取的都是每個元素第一次出現的問題,所以只要當前元素的i不是第一次出現,那就說明是重復元素,利用splice刪除執行元素即可。

而站在不刪除元素的角度,這就得利用雙指針進行元素覆蓋,我們先上代碼,再解釋原理:

/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function (nums) {
    if(nums.length === 0){
        return 0;
    };
    var s = 0, //慢指針,每賦值一次,慢指針往右移動一位
        f = 1, //快指針,只要重復就往右移動一位
        len = nums.length;
    for (; f < len; f++) {
        if (nums[s] !== nums[f]) {
            nums[s + 1] = nums[f];
            s++;
        };
    };
    return s + 1;
};

我們以[1,1,2,3]為例,注意,題目已經說了數組為已排序數組,所以相同元素必定相鄰。

我們指定2個指針,慢指針s(slow)與快指針f(fast),慢指針主要負責當元素不同時進行賦值,快指針主要負責數組遍歷,對每個元素進行比較。

說到底,就是每次比較完成之后,只要這個元素沒重復,就把這個元素通過賦值的形式,依次排在s指針索引的后面;若比較相同就啥都不干,直接讓快指針繼續往后移動。

我們通過圖解,來模擬[1,1,2,3]的賦值過程:

可以看到,一開始由於s為0,f為1,進行了第一次比較,如果相同,s作為起點元素保持不變,f作為快指針繼續尋找下個比較目標;

而只要s與f的元素不同,則將f的元素復制到s的后一位,以此類推,由於s的索引是0,經過幾次復制自增幾次,最后獲取的長度需要額外加1,大致上就是這個思路。

我最開始也是繞了半天,但是通過圖解,真是感嘆雙指針的微妙之處。

當然,雙指針代碼處的if操作其實也可以改寫成如下形式,思路是一樣的,不過我還是認為上述寫法好理解一點,先賦值,s再移動:

if (nums[s] !== nums[f]) {
    s++;
    nums[s] = nums[f];
};

那么關於本題的分析就到這里了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM