27.移除元素
这题最简单的想法就是直接遍历每一个元素,每发现一个元素就将后面的元素全部前移一位来覆盖,因此可以写出以下代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int sizeNums = nums.size();
for (int i = 0;i<sizeNums;i++){
if(nums[i] == val){
for(int j = i;j<sizeNums-1;j++){
nums[j] = nums[j+1];
}
i--;
sizeNums--;
}
}
return sizeNums;
}
};
两个问题:
- 为什么要? :因为如果有两个val连续,例如然后,那么当运行到第一个2的时候进行了前移,如果此时没有,那么,此时数组为,就错过了刚才前移进来覆盖的那个了。
- 为什么要?:因为每一次前移整体的长度都会减少,如果不这样做会超时的。
代码随想录的方法为双指针法,可以结合里面的动图加以理解,具体为:
- 有两个指针,第一个指针称为快指针,其用来寻找减去目标元素后的数组的元素,第二个指针称为慢指针,用来指向需要覆盖的位置,也就是原数组中目标元素的位置
- 一开始一起移动,当找到目标元素后慢指针指向该位置,只有覆盖之后慢指针才可以移动,快指针就往后找不是目标元素的位置,然后来覆盖。
代码为:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int fastIndex = 0;
int slowIndex = 0;
int numsSize = nums.size();
int reMoveNums = 0;
for(;fastIndex < numsSize;fastIndex++){
if(val != nums[fastIndex]){
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
};
26、删除数组中的相同元素
本题和上述题目可以采用相同的思路,同样是快指针和慢指针,但由于需要判断两个元素之间是否相等,那么初始化就快指针指向1,慢指针指向0,然后当它们不相同的时候,慢指针先移动一位,跟快指针位置相同,再执行赋值操作。而相同时慢指针就停止,直到快指针移动到下一个不相同的元素,此时慢指针++,移动到下一个不同元素所应该在的正确位置,再进行赋值即可。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int fastIndex = 1;
int slowIndex = 0;
int sizeNums = nums.size();
for(;fastIndex < sizeNums;fastIndex++){
if(nums[slowIndex] != nums[fastIndex]){
slowIndex++;
nums[slowIndex] = nums[fastIndex];
}
}
return slowIndex+1;
}
};
283、移动零
本次也可以采用双指针的形式,一开始我想的是一个指针从头开始一个指针从尾开始,然后交换位置,但考虑到需要保留原来元素的顺序,因此需要两个指针一起从头开始,然后遇到0时慢指针停止等待快指针找到非零元素来交换。
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int leftIndex = 0;
int rightIndex = 0;
while(rightIndex < nums.size()){
if(nums[rightIndex] != 0){
swap(nums[leftIndex],nums[rightIndex]);
leftIndex++;
}
rightIndex++;
}
}
};
844、比较含退格的字符串
这题我也是参考了力扣官方的答案,本来是写的将字符串处理之后再比较,但觉得这种双指针更有趣。
关键思路就是只有从字符串的后面开始看起,我们才能够知道哪一些字符需要删除掉,因为字符是否需要删除只跟它后面的退格号有关。
class Solution {
public:
bool backspaceCompare(string s, string t) {
int sIndex = s.length() - 1;
int tIndex = t.length() - 1;
int skipS = 0; //用来存放遍历中当前字符串s有的退格个数
int skipT = 0; //用来存放遍历中当前字符串t有的退格个数
while( sIndex >= 0 || tIndex >= 0){ //需要有一个仍然仍然未遍历结束
while( sIndex >= 0){
if ( s[sIndex] == '#'){ //如果等于退格,那么就退格号++,然后继续向前遍历
skipS++;
sIndex--;
}else if(skipS > 0){ //不等于退格,但是当前退格号不为0,那么这个字符是需要删除的,不需要比
skipS--; //删除掉一个字符,skipS更新
sIndex--;
}else{
break; //如果是字符并且sikpS等于0,说明这个字符不用删除掉,那么break来比较
}
}
while(tIndex >= 0){
if(t[tIndex] == '#'){
skipT++;
tIndex--;
}else if(skipT > 0){
skipT--;
tIndex--;
}else{
break;
}
}
if(sIndex >=0 && tIndex >= 0){
if(s[sIndex] != t[tIndex]){
return false;
}
}else{
if(sIndex >= 0 || tIndex >= 0){
return false;
}
}
sIndex--;
tIndex--;
}
return true;
}
};
977、有序数组的平方
本次最直接的想法就是想平方然后直接排序,排序本来想用自己写的排序算法但想起来还有sort函数,因此代码为:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i = 0;i < nums.size();i++){
nums[i] = nums[i] * nums[i];
}
sort(nums.begin(),nums.end());
return nums;
}
};
另一种方法是找边界,因此如果能够找到正负的边界,我们把正的和负的看成两个数组,然后对它们进行平方后的归并排序,就可以完成了。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int sizeNums = nums.size();
int markIndex = -1;
for(int i = 0; i < sizeNums ; i++){
if(nums[i] < 0){
markIndex = i;
}else{
break;
}
}
vector<int>reNums;
int leftIndex = markIndex;
int rightIndex = markIndex + 1;
while( leftIndex >= 0 || rightIndex <= sizeNums-1){
if(leftIndex < 0){
//说明小于0的已经都归进去了
reNums.push_back(nums[rightIndex] * nums[rightIndex]);
rightIndex++;
}
else if(rightIndex == sizeNums){
//说明大于0的已经都归进去了
reNums.push_back(nums[leftIndex] * nums[leftIndex]);
leftIndex--;
}
else if(nums[leftIndex] * nums[leftIndex] < nums[rightIndex] * nums[rightIndex]){
reNums.push_back(nums[leftIndex] * nums[leftIndex]);
leftIndex--;
}else{
reNums.push_back(nums[rightIndex] * nums[rightIndex]);
rightIndex++;
}
}
return reNums;
}
};
代码随想录中所采用的是双指针法:因为平方之后,可能的最大值必然在最左侧或者最右侧,那么可以用两个指针来从左右分别向内移动,不断找到最大值然后复制到新的数组之中
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int leftIndex = 0;
int rightIndex = nums.size() - 1;
int reIndex = nums.size()-1;
vector<int> reNums(nums.size(),0);
while(leftIndex <= rightIndex){
if(nums[leftIndex] * nums[leftIndex] > nums[rightIndex] * nums[rightIndex]){
reNums[reIndex] = nums[leftIndex] * nums[leftIndex];
reIndex--;
leftIndex++;
}else{
reNums[reIndex] =nums[rightIndex] * nums[rightIndex];
reIndex--;
rightIndex--;
}
}
return reNums;
}
};