領釦-26/27/80/283 陣列專題 做好初始定義 雙指標 MD
阿新 • • 發佈:2018-12-16
目錄
Markdown版本筆記 | 我的GitHub首頁 | 我的部落格 | 我的微信 | 我的郵箱 |
---|---|---|---|---|
MyAndroidBlogs |
baiqiantao | baiqiantao | bqt20094 | [email protected] |
領釦-26/27/80/283 陣列專題 做好初始定義 雙指標 MD
***
目錄
===
陣列專題:做好初始定義
做陣列類演算法問題的時候,我們常常需要定義一個變數,明確該變數的定義,並且在書寫整個邏輯的時候,要不停的維護住這個變數的意義。也特別需要注意初始值和邊界的問題。
移動零 Move Zeroes -283
陣列 雙指標
問題
給定一個數組 nums,編寫一個函式將所有 0 移動到陣列的末尾,同時保持非零元素的相對順序
。
示例:
輸入: [0,1,0,3,12]
輸出: [1,3,12,0,0]
說明:
必須在原陣列上操作,不能拷貝額外的陣列
。- 儘量減少操作次數。
答案
class Solution { public void moveZeroes(int[] nums) { int count = 0;//零的個數 for (int i = 0; i < nums.length; i++) { if (nums[i] == 0) { count++; } else { nums[i - count] = nums[i]; //非零往前移 } } int n = nums.length; while (count > 0) { nums[n - count] = 0; //填充後面的零 count--; } } }
移除元素 Remove Element -27
陣列 雙指標
問題
給定一個數組 nums 和一個值 val,你需要原地移除
所有數值等於 val 的元素,返回移除後陣列的新長度
。
- 不要使用額外的陣列空間,你必須在原地修改輸入陣列。
- 元素的順序可以改變。
- 你不需要考慮陣列中超出新長度後面的元素。
示例 1:
給定 nums = [3,2,2,3], val = 3,
函式應該返回新的長度 2, 並且 nums 中的前兩個元素均為 2。
示例 2:
給定 nums = [0,1,2,2,3,0,4,2], val = 2,
函式應該返回新的長度 5, 並且 nums 中的前五個元素為 0, 1, 3, 0, 4。
注意這五個元素可為任意順序。
答案
這題廢話連篇,其實和上一題核心步驟完全相同,而比上一題還容易。
class Solution {
public int removeElement(int[] nums, int val) {
int count = 0;//個數
for (int i = 0; i < nums.length; i++) {
if (nums[i] == val) {
count++;
} else {
nums[i - count] = nums[i]; //往前移
}
}
return nums.length - count;
}
}
刪除排序陣列中的重複項 -26
陣列 雙指標
問題
給定一個排序陣列,你需要在原地刪除重複出現的元素,使得每個元素只出現一次,返回移除後陣列的新長度。
- 不要使用額外的陣列空間,你必須在原地修改輸入陣列。
- 你不需要考慮陣列中超出新長度後面的元素。
示例 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。
記錄位置法
沃日,這個問題我修改了很多了版本,都有問題,全是邊界問題搞得怪!
問題分析起來很簡單,就是記錄重複元素的個數 count,然後把後面不重複的元素根據 count 移到前面來。
class Solution {
public int removeDuplicates(int[] nums) {
int count = 0;//刪除個數個數,1, 2, 2, 3, 3, 4
for (int i = 0; i < nums.length - count; i++) {
for (int j = i + count + 1; j < nums.length && nums[j] == nums[i + count]; j++) {
count++;
}
nums[i] = nums[i + count]; //往前移
}
return nums.length - count;
}
}
快慢指標法
解題思路是,我們使用快慢指標
來記錄遍歷的座標,最開始時兩個指標都指向第一個數字
- 如果兩個指標指的數字相同,則快指標向前走一步
- 如果不同,則兩個指標都向前走一步
這樣當快指標走完整個陣列後,慢指標當前的座標加1就是陣列中不同數字的個數。
class Solution {
public int removeDuplicates(int[] nums) {
if (nums.length == 0) return 0;
int fast = 1, slow = 0;
while (fast < nums.length) {
if (nums[fast] != nums[slow]) {
slow++;
nums[slow] = nums[fast];
//這兩行程式碼可以簡化為 nums[++slow] = nums[fast];
}
fast++;
}
return slow + 1;
}
}
刪除排序陣列中的重複項 II -80
陣列 雙指標
問題
給定一個排序陣列,你需要在原地刪除重複出現的元素,使得每個元素最多出現兩次
,返回移除後陣列的新長度。
- 不要使用額外的陣列空間,你必須在原地修改輸入陣列。
- 你不需要考慮陣列中超出新長度後面的元素。
答案
這道題和上面相比沒有多大的區別,關鍵是邏輯問題,如果腦筋轉不過來彎,那很難正確處理指標位置的。
class Solution {
public int removeDuplicates(int[] nums) {
if (nums.length <= 2) return nums.length;
int fast = 1, slow = 0;
boolean isRepeat = false;
while (fast < nums.length) {
if (nums[fast] == nums[slow] && isRepeat) fast++; //【3】之後再發現重複的數後,直接跳過,直到發現另一個數
else {
isRepeat = nums[fast] == nums[slow];//【1】判斷是不是重複的數
nums[++slow] = nums[fast++]; //【2】第一次發現重複的數後,並沒有跳過這個數,而是按照正常邏輯接收了這個數
}
}
return slow + 1;
}
}
2018-12-16