1. 程式人生 > >領釦網演算法學習筆記 - 80

領釦網演算法學習筆記 - 80

領釦網演算法學習筆記

本系列的演算法題目來自領釦網

陣列類演算法第一天

題目:

給定一個排序陣列,你需要在原地刪除重複出現的元素,使得每個元素最多出現兩次,返回移除後陣列的新長度。

示例:

給定 nums = [1,1,1,2,2,3],
函式應返回新長度 length = 5, 並且原陣列的前五個元素被修改為 1, 1, 2, 2, 3 。
給定 nums = [0,0,1,1,1,1,2,3,3],
函式應返回新長度 length = 7, 並且原陣列的前五個元素被修改為 0, 0, 1, 1, 2, 3, 3 。

說明:

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

解題過程:

思路:

根據之前的題目,看到這個題目的第一感覺是:我只要判斷是的第幾個重複值就OK了。

定義一個變數用來記錄當前是第幾個重複值,如果當前兩個判斷的值是一樣的,且為這個變數的值為0,則儲存這兩個值,把這個變數的值改為1,後續判斷時,因為這個變數值為一,所以重複值會忽略,當遇到兩個不同的值時,則儲存資料,且把這個變數的值變回0.

程式碼如下:

class Solution {
    public int removeDuplicates(int[] nums) {
        // 思路:定義一個變數用來記錄當前是第幾個重複值,如果當前兩個判斷的值是一樣的,且為前兩個則改變這個變數的值
// 如果當前變數的值改變了,則接下來的相同的資料就忽略掉 if(nums.length==0 || nums.length==1){ return nums.length; } int repeatNum = 0; // 如果repeatnum為0,則表示為前兩個值,此時改變repeatNum值,當判斷的值變化時在變回去 int numDate = 0; // 儲存新陣列的位置 for(int i=1;i<nums.length;
i++){ if(nums[numDate]==nums[i] && repeatNum == 0){ numDate++; nums[numDate] = nums[i]; repeatNum = 1; } if(nums[numDate]!=nums[i]){ numDate++; nums[numDate] = nums[i]; repeatNum = 0; } } return (numDate+1); } } // 用時15ms

後續思考:

該方法我覺得已經很簡便了,只需要迴圈一次陣列且不會多次修改比較值,但是還不是最優的,最優的方法在不看優質解答的情況下真沒思路了,證明思維還是有所欠缺的。

領釦上面該題其他高質量範例:

class Solution {
    public int removeDuplicates(int[] nums) {    
        int i = 0;
		for (int num : nums) {
			if (i < 2 || num > nums[i - 2]) {
				nums[i++] = num;
			}
		}
		return i;
    }
}
// 用時 <1ms

自我整理:

  1. 這個程式碼,不能說驚豔到我了,畢竟只有短短的這一段,但是這個思路很值得我借鑑。
思路:

​ 因為要重複值最多保留兩個,所以只要現在的值和第三個的值不一樣就可以了。不管第二個值相不相同。

class Solution {
    public int removeDuplicates(int[] nums) {
        
        if(nums.length==0 || nums==null) return 0;
        
        int k = 0;
        int count = 0;
      
        for(int i=0; i<nums.length; i++){
            if(i==0 || nums[i] != nums[i-1]) count = 0;
            else count ++;
            if(count<=1){
                nums[k++] = nums[i];
            }
        }
        return k;
    }
}
// 用時2ms

自我整理:

  1. 用時1ms的程式碼只是比小於1ms的程式碼多了個數據長度判斷,思路是一樣的。所以沒寫,

  2. 2ms這個思路其實也是一個方向吧,但是感覺沒有像上一個那樣新奇,思路還是比較大眾的。

思路:

​ 它依然是定義一個變數來記錄當前重複值的數量,根據變數的值來判定是否保留。

自我總結:

​ 其實很多時候,看著題目,我們需要發散一下思維,想一下都有哪些情況能達到題目的要求,不要侷限於一般的邏輯思維,可能目前的思維比較差,但是我覺得遇到問題時,在你很快能想到一個普遍的想法時,或許可以再多抽點時間想想有沒有更好的方法。就算沒有,發散一下思維,也能鍛鍊一下自己,使得下一次思維的擴充套件性變得更好。