将给定的字符串反转 空间是O(1)
遍历字符串然后存放到新的数组里,但是不满足空间O(1)
想到反转链表使用双指针的思想,所以使用双指针法反转字符串,字符串也是一种数组,所以元素在内存中是连续分布,定义两个指针i,j,一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。
使用swap交换两个指针处的值。
class Solution {
public:
void reverseString(vector& s) {
for(int i=0, j=s.size()-1;i
swap有两种实现方式
1.数值交换
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
2.位运算
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
i)根据整数k,从字符串开头计数,每次计数到2k,就反转2k中的前k个字符;
ii)剩余字符少于k个,则剩余字符全部反转;
iii)剩余字符大于等于k,小于2k,则只反转前k个字符
首先应用字符串的长度对2k取余, 先处理剩下的字符串,使用for循环+swap函数反转;然后用字符串的长度除以2k,看有多少个2k,然后再对每一个字符串内的数据进行for循环+swap函数,很冗余,不推荐。
在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。
所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。
class Solution {
public:
string reverseStr(string s, int k) {
for(int i=0;i
之所以是i+k<=s.size(),为什么有等号,可以举一个典型的例子:
abc字符串 k=3 当i=0时,i+k=3,而s.size()=3,因此可以取等号
class Solution {
public:
void reverse(string& s, int start, int end){
for(int i=start,j=end;i
class Solution {
public:
string reverseStr(string s, int k) {
int n = s.size(),pos = 0;
while(pos
但是这个程序里面有一个疑问:???就是这段代码为什么会报错???
注意分情况要画{}呀,是因为没有打印{},所以continue会直接拦截住 reverse(s.begin()+i, s.end()),使这一句永远都不会执行。
class Solution {
public:
string reverseStr(string s, int k) {
for(int i=0;i
(力扣:将'.'替换为空格) 将空格换成%20 注意%20其实是3个字符:% 2 0
还是遍历的思想,遇到空格,就替换为20%,不行,一个位置只能换一个位置,但是20%有两个位置,无法换
首先扩充数组到每个空格替换成"%20"之后的大小。先数有多少个空格,有多少个就在后面补上它的2倍,因为有3个字符嘛,相比原来,多了两个个字符;
然后从后向前替换空格,也就是双指针法,过程如下:
i指向新长度的末尾,j指向旧长度的末尾。
当j指针指向不为空格的元素时,将该元素后移到i指针指向的位置,然后i指针和j指针同时向前移一位再判断j指针指向的位置处是否为空格,若不是空格,则继续讲该元素移到i指针指向的位置,若是j指针指向的位置是空格,则i指针处填冲字符0,然后i指针向前移动一位,填充字符2,i指针再向前移动一位,填充%,然后j指针再移动,继续判断该位置处的字符是否为空格.
很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这样做有许多好处:
class Solution {
public:
string replaceSpace(string s) {
int count = 0; // 统计空格的个数
int sOldSize = s.size();
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') {
count++;
}
}
// 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
s.resize(s.size() + count * 2);
int sNewSize = s.size();
// 从后先前将空格替换为"%20"
for (int i = sNewSize - 1, j = sOldSize - 1; j < i; i--, j--) {
if (s[j] != ' ') {
s[i] = s[j];
} else {
s[i] = '0';
s[i - 1] = '2';
s[i - 2] = '%';
i -= 2;
}
}
return s;
}
};
//力扣题目代码
class Solution {
public:
string pathEncryption(string path) {
int count = 0;//统计.的个数
int size = path.size();
for(int i=0;i
反转字符串中单词(没有空格)的顺序,s中使用大于等于1个空格将单词分开,返回的单词顺序颠倒且仅在单词之间用单个空格分隔。
以空格结束作为一个单词的标志,或者是判断一个单词,判断这个单词两端都要空格,采用双指针
解题思路
i)移除多余空格
ii)将整个字符串反转
iii)将每个单词反转
所以,将这段程序进行拆解,分解成两个任务,去空格和翻转
翻转的程序好写
void reverse(string& s,int start,int end){
for(int i=start,j=end;i
难点是去空格的程序,因为是有选择的去空格,该段程序有两个解法
①分类讨论去空格
void removeExtraSpaces(string& s){
int slow = 0, fast = 0;
//去掉字符串前面的空格
while(s.size()>0 && fast0 && s[fast-1]==s[fast] && s[fast]==' '){
continue;
}//知道fast的紧挨着的两个元素不是空格时为止
else{
s[slow] = s[fast];
slow++;
}//slow指向不为空格的元素,即英文字母
}
if(slow-1>0 && s[slow-1]==' '){//去掉字符串末尾的空格
s.resize(slow-1); //resize操作
}
else{
s.resize(slow);//重新设置字符串的大小
}
}
②使用双指针法去除空格(这个对我来讲有点难理解)
void removeExtraSpaces(string& s){//去除所有空格,并在相邻单词之间添加空格,快慢指针
int slow = 0;
for(int fast=0;fast
完整代码(解法1):
class Solution {
public:
void removeExtraSpaces(string& s){
int slow = 0, fast = 0;
//去掉字符串前面的空格
while(s.size()>0 && fast0 && s[fast-1]==s[fast] && s[fast]==' '){
continue;
}//知道fast的紧挨着的两个元素不是空格时为止
else{
s[slow] = s[fast];
slow++;
}//slow指向不为空格的元素,即英文字母
}
if(slow-1>0 && s[slow-1]==' '){//去掉字符串末尾的空格
s.resize(slow-1); //resize操作
}
else{
s.resize(slow);//重新设置字符串的大小
}
}
void reverse(string& s,int start,int end){
for(int i=start,j=end;i
完整代码(解法2):
class Solution {
public:
void removeExtraSpaces(string& s){//去除所有空格,并在相邻单词之间添加空格,快慢指针
int slow = 0;
for(int fast=0;fast
将代码自己按照逻辑又过了一遍,添加了一些没有的注释。
class Solution {
public:
//首先去除字符串中所有的空格,定义一个函数
void removespace(string& s){
//空格在开头
int slow = 0, fast = 0;
while(s.size()>0 && fast0 && s[fast]==s[fast-1] && s[fast]==' '){
continue;
}
else s[slow++] = s[fast];
}
//空格在结尾
if(slow-1>0 && s[slow-1]==' '){
s.resize(slow-1);//这里为啥要是slow-1呢,因为前一段处理中间的数据时,for循环最后进行了slow++
}
else s.resize(slow);
}
//接着翻转,定义一个函数
void reverse(string& s,int start,int end){
for(int i=start,j=end;i
把字符串前面的若干个字符转移到字符串的尾部。
局部反转+整体反转
具体步骤为:
class Solution {
public:
string reverseLeftWords(string s, int n) {
reverse(s.begin(), s.begin() + n);
reverse(s.begin() + n, s.end());
reverse(s.begin(), s.end());
return s;
}
};