Java&LeetCode 初入門——027. 移除元素
Java&LeetCode 初入門——027. 移除元素
本題與026題相似,是關於雙指標陣列的問題
文內程式碼全部採用JAVA語言。
題目
給定一個數組 nums 和一個值 val,你需要原地移除所有數值等於 val 的元素,返回移除後陣列的新長度。
不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 O(1) 額外空間的條件下完成。
元素的順序可以改變。你不需要考慮陣列中超出新長度後面的元素。
測試用例
示例 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。
注意這五個元素可為任意順序。
你不需要考慮陣列中超出新長度後面的元素。
個人解法
這裡採用的是和026相類似的雙指標法,指標 i 的方向是—>—>—>—>,從陣列起始位開始,指標 j 的方向是<—<—<—<— ,從陣列最末位開始。當i==j時,說明完全遍歷了整個陣列。
之所以產生這樣的想法,是因為每當查出一個目標值,這個值就需要被陣列中的其他非目標值替換。而新陣列的輸出值取決於新陣列的長度。如果我們不能將陣列尾端的非目標值前移,那麼就會失去這些值。。
先從 i 開始判斷,如果 i 位置的值是目標元素val,那麼就需要檢查j位置,如果 j 位置是非目標元素,則陣列長度+1,並用 j 位置的元素取代 i 位置的元素,這樣就刪除了 i 位置的值,並按預定次序移動i j的位置。如果如果 j 位置也是目標元素,就向前移動 j 直到 j 位置是非目標元素。
囉裡吧嗦,核心思想就是用陣列尾端的非val,替換陣列前端的val,每檢測到一個非val,新陣列長度+1。
執行用時: 9 ms, 在Remove Element的Java提交中擊敗了67.17% 的使用者
class Solution {
public int removeElement(int[] nums, int val) {
int i=0;
int j=nums.length-1;
int length=0;
while (i<=j) {
if (nums[i]==val) {
if (nums[j]==val) {
j--;
}
else {
nums[i]=nums[j];
j--;
length++;
i++;
}
}
else {
i++;
length++;
}
}
return length;
}
}
官方解法
方法一
思路
既然問題要求我們就地刪除給定值的所有元素,我們就必須用 O(1) 的額外空間來處理它。如何解決?我們可以保留兩個指標 i 和 j,其中 i 是慢指標,j 是快指標。
其實和個人解法差不多,只是 i 和 j 有相同的起始位置,j 跑得快,一旦檢測到非val就覆蓋 i 。程式簡短,不錯不錯。執行時間和個人解法一樣,都是9ms。
演算法
public int removeElement(int[] nums, int val) {
int i = 0;
for (int j = 0; j < nums.length; j++) {
if (nums[j] != val) {
nums[i] = nums[j];
i++;
}
}
return i;
}
方法二
思路
這個想法好像和個人解法差不多,都是雙向來看,但是他不需要分為情況討論,所以程式碼顯得簡潔。
避免if語句的方法就是,把尾部的資料複製到前面之後,繼續檢查被取代的元素位置,直到符合要求。
時間同樣是9ms。
演算法
public int removeElement(int[] nums, int val) {
int i = 0;
int n = nums.length;
while (i < n) {
if (nums[i] == val) {
nums[i] = nums[n - 1];
// reduce array size by one
n--;
} else {
i++;
}
}
return n;
}