文章目录
字符串
1、翻转字符串
leetcode 344.反转字符串(左右双指针)
leetcode 344.反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例 1:
- 输入:[“h”,“e”,“l”,“l”,“o”]
- 输出:[“o”,“l”,“l”,“e”,“h”]
使用双指针即可
C语言代码:
void reverseString(char* s, int sSize){
int left = 0, right = sSize - 1;
while (left < right) {
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
}
其中交换swap有两种实现方式:
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
一种就是通过位运算:
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
leetcode 541. 反转字符串 II(左右双指针)
leetcode 541. 反转字符串 II
给定一个字符串 s 和一个整数 k,你需要对从字符串开头算起的每隔 2k 个字符的前 k 个字符进行反转。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
- 输入: s = “abcdefg”, k = 2
- 输出: “bacdfeg”
C语言代码:
char* reverseStr(char* s, int k) {
for (int i = 0; i < strlen(s); i += 2*k) {
if (i + k < strlen(s)) {
int left = i, right = i + k - 1;
while (left < right) {
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
} else {
int L = i, R = strlen(s) - 1;
while (L < R) {
char tmp1 = s[L];
s[L] = s[R];
s[R] = tmp1;
L++;
R--;
}
}
}
return s;
}
leetcode 剑指 Offer 05. 替换空格(左右双指针)
leetcode 剑指 Offer 05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
- 输入:s = “We are happy.”
- 输出:“We%20are%20happy.”
C语言代码:
在原有的空间上增加空间,不需要额外分配空间
char* replaceSpace(char* s){
int count = 0, len = 0;
for (int i = 0; i < strlen(s); i++) {
len++;
if (s[i] == ' ') {
count++;
}
}
s = (char*)realloc(s, sizeof(char) * (len + 2 * count + 1));
s[len + 2 * count] = '\0';
int R = len + 2 * count - 1;
for (int L = len - 1; L >= 0; L--) {
if (s[L] != ' ') {
s[R--] = s[L];
} else {
s[R--] = '0';
s[R--] = '2';
s[R--] = '%';
}
}
return s;
}
字符串与数组的区别
字符串是若干字符组成的有限序列,也可以理解为是一个字符数组,但是很多语言对字符串做了特殊的规定,接下来我来说一说C/C++中的字符串。
在C语言中,把一个字符串存入一个数组时,也把结束符 '\0’存入数组,并以此作为该字符串是否结束的标志。
例如这段代码:
char a[5] = "asd";
for (int i = 0; a[i] != '\0'; i++) {
}
在C++中,提供一个string类,string类会提供 size接口,可以用来判断string类字符串是否结束,就不用’\0’来判断是否结束。
例如这段代码:
string a = "asd";
for (int i = 0; i < a.size(); i++) {
}
那么vector< char > 和 string 又有什么区别呢?
其实在基本操作上没有区别,但是 string提供更多的字符串处理的相关接口,例如string 重载了+,而vector却没有。
所以想处理字符串,我们还是会定义一个string类型。
leetcode 151. 翻转字符串里的单词
leetcode 151. 翻转字符串里的单词
给你一个字符串 s ,逐个翻转字符串中的所有 单词 。单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。请你返回一个翻转 s 中单词顺序并用单个空格相连的字符串。
说明:
- 输入字符串 s 可以在前面、后面或者单词间包含多余的空格。
翻转后单词间应当仅用一个空格分隔。
翻转后的字符串中不应包含额外的空格。
示例 1:
- 输入:s = “the sky is blue”
- 输出:“blue is sky the”
此题是将整个单词看作整体,再将其进行翻转
C语言代码:
char * reverseWords(char * s) {
int sLen = strlen(s);
char* res = (char*)calloc(sLen + 1, sizeof(char));
int pre = sLen - 1, index = 0;
while (pre >= 0) {
if (s[pre] == ' ') {
pre--;
} else {
int after = pre;
while (pre >= 0 && s[pre] != ' ') {
pre--;
}
int cur = pre + 1;
while (cur <= after) {
res[index++] = s[cur++];
}
res[index++] = ' ';
}
}
if (index > 0 && res[index - 1] == ' ') {
/* 输入数组中有单词的情况 */
res[index - 1] = '\0';
} else {
/* 输入数组没有单词的情况 */
res[index] = '\0';
}
return res;
}
C++代码:
class Solution {
public:
//反转字符串
void reverse(string &s, int left, int right) {
for (int i = left, j = right; i < j; i++, j--) {
swap(s[i], s[j]);
}
}
//去除多余空格
void removeExtraSpaces(string &s) {
int slow = 0, fast = 0;
//去除前导空格
while (s.size() > 0 && fast < s.size() && s[fast] == ' ') {
fast++;
}
for (; fast < s.size(); fast++) {
if (fast > 1 && s[fast] == s[fast - 1] && s[fast] == ' ') {
//去除中间多余空格
continue;
} else {
s[slow++] = s[fast];
}
}
//去除后置空格
if (slow > 1 && s[slow - 1] == ' ') {
s.resize(slow - 1);
} else {
s.resize(slow);
}
}
string reverseWords(string s) {
removeExtraSpaces(s);
reverse(s, 0, s.size() - 1);
for (int i = 0; i < s.size(); i++) {
int j = i;
while (j < s.size() && s[j] != ' ') {
j++;
}
reverse(s, i, j - 1);
i = j;
}
return s;
}
};
leetcode 剑指Offer58-II.左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
示例 1:
- 输入: s = “abcdefg”, k = 2
- 输出: “cdefgab”
示例 2:
- 输入: s = “lrloseumgh”, k = 6
- 输出: “umghlrlose”
1、维护一个新的返回数组,进行拷贝
char* reverseLeftWords(char* s, int n){
char* tmp = (char*)malloc(sizeof(char) * (strlen(s) + 1));
int index = 0;
for (int i = n; i < strlen(s); i++) {
tmp[index++] = s[i];
}
for (int i = 0; i < n; i++) {
tmp[index++] = s[i];
}
tmp[index] = '\0';
return tmp;
}
2、直接在原数组上进行操作,先翻转0到n-1,再翻转n到numsSize - 1,再翻转0到numsSize - 1即可
char* reverseLeftWords(char* s, int n){
/* 翻转前n个字符 */
int left = 0, right = n - 1;
while (left < right) {
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
/* 翻转n - strlen(s) - 1个字符 */
left = n;
right = strlen(s) - 1;
while (left < right) {
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
/* 翻转全部字符 */
left = 0;
right = strlen(s) - 1;
while (left < right) {
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
return s;
}
C++代码:
class Solution {
public:
//反转字符串
void reverse(string &s, int left, int right) {
for (int i = left, j = right; i < j; i++, j--) {
swap(s[i], s[j]);
}
}
string reverseLeftWords(string s, int n) {
reverse(s, 0, n - 1);
reverse(s, n, s.size() - 1);
reverse(s, 0, s.size() - 1);
return s;
}
};