天天看點

【ACM成神之路】一道初級算法題,我改了又改,自信的點下送出,突然想退休...

事情是這個樣子的,在月黑風高的夜晚,小編沒事閑的看了一眼LC,發現LC官方有一個初級算法的題目集合,之後小編就躍躍欲試。

緣起

第一道題是 删除有序數組中的重複項 。

就沖着這個題目,小編也感覺這道題難不倒我。

題目是這個樣子的:

給你一個 升序排列 的數組 nums ,請你 原地 删除重複出現的元素,使每個元素 隻出現一次 ,傳回删除後數組的新長度。元素的 相對順序 應該保持 一緻 。

由于在某些語言中不能改變數組的長度,是以必須将結果放在數組nums的第一部分。更規範地說,如果在删除重複項>之後有 k 個元素,那麼 nums 的前 k 個元素應該儲存最終結果。

将最終結果插入 nums 的前 k 個位置後傳回 k 。

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

示例 1:

輸入:nums = [1,1,2]

輸出:2, nums = [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]

解釋:函數應該傳回新的長度 5 , 并且原數組 nums 的前五個元素被修改為 0, 1, 2, 3, 4 。不需要考慮數組中超出新長度後面的元素。

1 <= nums.length <= 3 * 104

-104 <= nums[i] <= 104

nums 已按 升序 排列

說時遲,那時快,小編根本就不屑于讀這種小題的示例和提示,便直接把滑鼠滑到了代碼框,自信滿滿的寫下了一篇完美的算法,不用送出,就感覺這算法一定超過99%的使用者

緣滅

小編的算法思路是這樣的。

  1. 将不重複的資料,重新在數組的最前面插入一遍。
  2. 兩個指針,第一個指針記錄待插入的位置,第二個指針周遊整個數組,找出不重複的資料

于是就有了下面這段代碼。

class Solution {
    public int removeDuplicates(int[] nums) {

        int len = nums.length;

        Set<Integer> set = new HashSet();
        int i = 0;
        for(int j = 0;j<len;j++){
            if(!set.contains(nums[j])){
                set.add(nums[j]);
                nums[i] = nums[j];
                i++;
            }
        }
        return      

當小編自信滿滿的點選了送出之後................

【ACM成神之路】一道初級算法題,我改了又改,自信的點下送出,突然想退休...
擊敗了7.9%的使用者

随後小編不信邪的又潤了一遍代碼。果然計算機不會騙我,還是7.9%......。

【ACM成神之路】一道初級算法題,我改了又改,自信的點下送出,突然想退休...
俗話說打人不打臉,小編剛認為自己天衣無縫的代碼,至少超過99%,你就來個7.9%,這不止打臉,還拿鞋底子打啊。

退休吧

小編就帶着一絲狂怒,來到了題解專區。根據官方題解所述,小編的雙指針思想是對的,NICE。 但是有個關鍵的條件,資料是升序的,是以重複的資料,一定都是前後挨着的,根據這個條件,我看着官方題解改了改代碼。

和上面我寫的不同的有一點。就是我用的set集合判斷是否資料重複,但是官方依據上述的條件,直接判斷兩個挨着的資料是否重複,如果不重複就把資料放到待插入的指針處。

class Solution {
    public int removeDuplicates(int[] nums) {

        int len = nums.length;

        int i = 1;
        for(int j = 1;j<len;j++){
            if(nums[j] != nums[j-1]){
                nums[i] = nums[j];
                i++;
            }
        }
        return      

寫到代碼,小編潤了一下,還得是官方,小編洗洗睡了,加油吧,兄弟們!