題目:
給你一個數組 nums 和一個值 val,你需要 原地 移除所有數值等於 val 的元素,並返回移除后數組的新長度。 不要使用額外的數組空間,你必須僅使用 O(1) 額外空間並 原地 修改輸入數組。 元素的順序可以改變。你不需要考慮數組中超出新長度后面的元素。 示例 1: 輸入:nums = [3,2,2,3], val = 3 輸出:2, nums = [2,2] 解釋:函數應該返回新的長度 2, 並且 nums 中的前兩個元素均為 2。你不需要考慮數組中超出新長度后面的元素。例如,函數返回的新長度為 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也會被視作正確答案。 示例 2: 輸入:nums = [0,1,2,2,3,0,4,2], val = 2 輸出:5, nums = [0,1,4,0,3] 解釋:函數應該返回新的長度 5, 並且 nums 中的前五個元素為 0, 1, 3, 0, 4。注意這五個元素可為任意順序。你不需要考慮數組中超出新長度后面的元素。
思路: 最直接的方式是依次遍歷數值,遇到和val一樣的數字就讓后面的數依次前移,覆蓋當前與val數值一樣的數。
代碼:
class Solution { public: int removeElement(vector<int>& nums, int val) { int size=nums.size(); for(int i=0;i<size;i++) { if(nums[i]==val) { for(int j=i+1;j<size;j++) { nums[j-1]=nums[j]; } i--; size--; } } return size; } };
時間復雜度O(n^2),空間復雜度O(1),LeetCode的運行很迷。。。運行時長0ms,內存8.6M,只擊敗23%的用戶
查看評論區看到@代碼隨想錄的雙指針方法,如下:
雙指針法(快慢指針法)在數組和鏈表的操作中是非常常見的,很多考察數組、鏈表、字符串等操作的面試題,都使用雙指針法。
以輸入:nums = [0,1,2,2,3,0,4,2], val = 2為例子
開始是slow指針是0,fast指針開始遍歷數組,初始為0。slow指向的元素是准備被覆蓋的,如果val與當前fast指向數據的值一樣,那么slow就放棄抵抗(不自增),讓下一次滿足if的時候覆蓋掉當前slow指向數據
,若不一樣,則slow自增,避免被覆蓋。
1次循環: slow為0 fast為0 ,numFast為0,不等於val=2,執行if內語句 num[0]=0
2次循環: slow為1 fast為1 ,numFast為1,不等於val=2,執行if內語句 num[1]=1
3次循環: slow為2 fast為2 ,numFast為2, 等於val=2,不執行if語句
4次循環: slow為2 fast為3, numFast為2, 等於val=2,不執行if語句
5次循環: slow為2 fast為4, numFast為3, 不等於val=2,執行if內語句 num[2]=3
6次循環: slow為3 fast為5, numFast為0, 不等於val=2,執行if內語句 num[3]=0
…………
如此就完成了對指定數據val的覆蓋,時間復雜度O(n),空間復雜度O(1)
class Solution { public: int removeElement(vector<int>& nums, int val) { int slowIndex = 0; for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) { if (val != nums[fastIndex]) { nums[slowIndex++] = nums[fastIndex]; } } return slowIndex; } };
理論上后一種的運行效果更好的,但是LeetCode的運行結果是4ms,8.5M,內存方面超過85%的用戶,挺迷的