【双指针类型】---LeetCode和牛客刷题记录
目录
1.LeetCode--283
具体解法以及代码解释
具体解决代码:
2.LeetCode--1089
具体解法过程:
思路一(暴力求解)
思路一具体实现代码
思路二(相对复杂,但双百通过解答)
思路二具体实现代码:
1.LeetCode--283
283. 移动零 - 力扣(LeetCode)

这是一道关于双指针的简单题。主要思路为双指针,只需遍历一遍,并同时移动0的位置即可完成。
具体解法以及代码解释
1.先定义两个int类型的dest和cur。
2.dest含义为在遍历整个数组的过程中,dest指向的是移动0元素后最后一个非0元素的数组下标。(注意,dest需要初始化为-1,不能为0,主要为了适配判断逻辑)
3.cur为遍历过程中遇到0元素时的数组下标。
4.开始遍历,当前指向元素为非0,直接跳过。否则,先将dest++(dest的定义,接下来需要移动0元素的位置),然后将当前元素(0元素)下标赋值给cur,最后交换cur和dest指向的值即可。
具体解决代码:
class Solution {
public:void moveZeroes(vector<int>& nums) {//dest是指向最后一个非0元素的位置,cur是遍历到0元素时的位置。//并且注意,dest初始化应该设置为-1int dest = -1, cur = 0;for (int i = 0; i < nums.size(); i++) {if (0 == nums[i]) {continue;}dest++;cur = i;swap(nums[dest], nums[cur]);}}
};
2.LeetCode--1089
1089. 复写零 - 力扣(LeetCode)

具体解法:双指针
具体解法过程:
思路一(暴力求解)
就按照题目的要求来,先从左往右遍历,遇到非0值,正常向后继续遍历。一旦遇到了0值,则从该处开始整体向后移动一位,越界的数据直接丢掉。(具体实现为:从末端数据开始一步一步覆写到该遇见0值的下标)
思路一具体实现代码
class Solution {
public:void duplicateZeros(vector<int>& arr) {int end = arr.size() - 1;int cur = 0;while(cur < end){if(0 == arr[cur]){while(end != cur){arr[end] = arr[end-1];end--;}cur++;end = arr.size()-1;}cur++;}}
};
思路二(相对复杂,但双百通过解答)
1.假设可以另开一个相同长度的数组(tmp数组)
那么简单,只需要从左至右遍历原数组,遇见非0填写一次。遇见0连续填写两次。(直到tmp数组满了就停止即可)
2.那么,直接在原数组操作,不另外开辟数组,该逻辑可行么?
不可行。因为如果遇见0后,直接写两次,会覆盖原数组中需要向右移动的数据。
3.如果从左至右遍历不可行,那么从左至左可行么?
可以的,不会造成覆盖数据的情况。但是我们在此之前,我们需要先从左至右一遍遍历一遍,确定从右至左的开始位置。
下图就是从右向左开始的位置。
(上图中从左至右的修改逻辑)
当cur指向非0数据,dest只需要将当前指向数据改为cur同样指向的数据即可。当cur指向0时,将当前指向的数据和左边一个数据都改为0
(修改后的数据结果)
4.特殊情况
以上数据在从左至右遍历后,dest指向越界了。这种需要另外处理一下。
在从左只有遍历结束后,判断dest的位置,如果越界了,需要先dest--,然后将dest指向的位置置零。然后开始从右至左遍历的逻辑。
思路二具体实现代码:
class Solution {
public:void duplicateZeros(vector<int>& arr) {int cur = 0,dest = -1;int len = arr.size()-1;while(dest < len){if(arr[cur] == 0){dest +=2;}else{dest++;}if(dest >= len){break;}cur++;}if(dest == arr.size()){arr[len] = 0;dest-=2;cur--;}while(cur >= 0){if(arr[cur] == 0){arr[dest--] = 0;arr[dest--] = 0;cur--;}else{arr[dest] = arr[cur];dest--;cur--;}}}
};




