領釦網演算法學習筆記 - 80
阿新 • • 發佈:2018-11-24
領釦網演算法學習筆記
本系列的演算法題目來自領釦網
陣列類演算法第一天
題目:
給定一個排序陣列,你需要在原地刪除重複出現的元素,使得每個元素最多出現兩次,返回移除後陣列的新長度。
示例:
給定 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 。
說明:
- 不要使用額外的陣列空間,
- 你必須在原地修改輸入陣列並在使用 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
自我整理:
- 這個程式碼,不能說驚豔到我了,畢竟只有短短的這一段,但是這個思路很值得我借鑑。
思路:
因為要重複值最多保留兩個,所以只要現在的值和第三個的值不一樣就可以了。不管第二個值相不相同。
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
自我整理:
-
用時1ms的程式碼只是比小於1ms的程式碼多了個數據長度判斷,思路是一樣的。所以沒寫,
-
2ms這個思路其實也是一個方向吧,但是感覺沒有像上一個那樣新奇,思路還是比較大眾的。
思路:
它依然是定義一個變數來記錄當前重複值的數量,根據變數的值來判定是否保留。
自我總結:
其實很多時候,看著題目,我們需要發散一下思維,想一下都有哪些情況能達到題目的要求,不要侷限於一般的邏輯思維,可能目前的思維比較差,但是我覺得遇到問題時,在你很快能想到一個普遍的想法時,或許可以再多抽點時間想想有沒有更好的方法。就算沒有,發散一下思維,也能鍛鍊一下自己,使得下一次思維的擴充套件性變得更好。