引言
题目一:给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。 例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。
题目一
这一题也是双指针的思想,题目的目的就是要替换数字变成单词。这个涉及到了对于线性数据结构的填充或者删除。如果我们按照正常的遍历顺序(正序遍历)每次插入一个数据,就必须要把原来的位置全部移动到后面去,也就是双循环O(n^2)的时间复杂度。
所以我们对于这一类问题,我们选择在开辟了空间之后用后序遍历的做法,这种做法的优势就是我们不需要移动任何的元素。首先我们对于原来的数组和现在的新数组都是后续遍历,也就是说原来的数组最后一个字母一定移动到新数组的最后一个,然后不断地往前面推,这样直接就可以确定位置,而不需要向前序遍历一样,每一次那个位置我们都需要不断地往后面进行调整。
cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
int count = 0;
while(cin >> s) {
int oldIndex = s.size() - 1;
for(int i = 0; i < s.size(); i++) {
if(s[i] >= '0' && s[i] <= '9') {
count++;
}
}
s.resize(s.size() + count * 5);
int newIndex = s.size() - 1;
while(newIndex >= 0) {
if(s[oldIndex] >= '0' && s[oldIndex] <= '9') {
s[newIndex--] = 'r';
s[newIndex--] = 'e';
s[newIndex--] = 'b';
s[newIndex--] = 'm';
s[newIndex--] = 'u';
s[newIndex--] = 'n';
} else {
s[newIndex--] = s[oldIndex];
}
oldIndex--;
}
cout << s << endl;
}
return 0;
}
第二题
这一题就是把所有的0移动到最后面去,这一题依然是双指针的思想,双指针的一般解法有两种,第一种是两个指针同向行驶,还有一种是一个在左边,一个在右边,面对面夹逼。
对于第一种情况,我们一般是快慢指针,慢指针用来更新数组,快指针用来遍历数组,而快慢指针真正分开的条件也就是我们要找的值。这里我们分开的条件是快指针遇到了0。如果一直没有遇到0,那其实这两个指针一直都是在一起的,直到遇到了0,那慢指针就开始更新数组了,这个更新数组的方式其实就是快指针把数据通过swap送过来,而快指针依然向后遍历,随着0的越来越多,两个指针越来越远。
cpp
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slow = 0;
for(int fast = 0; fast < nums.size(); fast++) {
if(nums[fast] != 0) {
swap(nums[fast], nums[slow]);
slow++;
}
}
}
};
// 1 2 3 0 5 0 6 7
题目三
相比于栈,这个题目用双指针的空间复杂度更小,时间复杂度相同。对于两个字符串的比较,我们也可以考虑双指针。这一题'#'会影响一个数组的前面的数,所以我们肯定不可以正序遍历,相比于回忆过去,我们更喜欢预测未来。所以我们选择后序遍历,这个好处就是我们可以把因为'#'而消除的结点直接去掉,反正最后也不参加我们的比较。当去掉了之后,如果某一次的移动,发现有不相等,那么就返回false。注意一下,我们说的移动是正常的移动,而不是因为'#'而被迫的移动,所以我们每一次比较的都是最后留在数组里面的数,只不过是从后面往前面比较而已。不过还是要注意一下子就是,不要比较越界了,还是要加一些判断条件的。
cpp
class Solution {
public:
bool backspaceCompare(string s, string t) {
int str1 = s.size() - 1;
int str2 = t.size() - 1;
int skip1 = 0;
int skip2 = 0;
while(str1 >= 0 || str2 >= 0) {
while(str1 >= 0) {
if(s[str1] == '#') {
skip1++;
str1--;
} else if(skip1 > 0) {
str1--;
skip1--;
} else {
break;
}
}
while(str2 >= 0) {
if(t[str2] == '#') {
skip2++;
str2--;
} else if(skip2 > 0) {
str2--;
skip2--;
} else {
break;
}
}
if(str1 >= 0 && str2 >= 0) {
if(s[str1] != t[str2]) {
return false;
}
} else {
if(str1 >= 0 || str2 >= 0) {
return false;
}
}
str1--;
str2--;
}
return true;
}
};
总结
本篇文章介绍了双指针对两个数组,同边和不同边的做法,三种做法都是双指针,但是思想完全不一样,大家还是要多多体会!
本篇文章就到这里结束了!!!希望这篇文章可以帮助到大家~~~