题目链接:344.反转字符串
题目虽然要求说“不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题”,但这个问题也能看出利用对半交换的方法可以快速满足题目要求。可以通过额外定义一个中间变量的方式交换,也可以通过位运算的方法交换,建议使用位运算的方式,整体代码给出如下:
void reverseString(char* s, int sSize){
int mid = sSize / 2;
int i = 0;
while (i < mid) {
s[i] ^= s[sSize - 1 - i];
s[sSize - 1 - i] ^= s[i];
s[i] ^= s[sSize - 1 - i];
++i;
}
}
时间复杂度O(N)
空间复杂度O(1)
题目链接:541. 反转字符串II
题目可以使用双指针叫上上一题的元素交换方式进行求解,关键是边界条件的判定问题,分为三个情况,1、恰好元素个数为偶数,2、剩余字符少于K个,3、剩余字符大于等于K个,小于2K个。三个条件分别判定即可求解,代码给出如下:
void swap(char *s, char *p, int k) {
int i = 0;
while (i < k / 2) {
*(p + i) ^= *(p + k - 1 - i);
*(p + k - 1 - i) ^= *(p + i);
*(p + i) ^= *(p + k - 1 - i);
++i;
}
}
char * reverseStr(char * s, int k){
char *p = s;
char *q = s;
while (*q != '\0') {
if (((int)(q - p) == (2*k - 1))) {
swap(s, p, k);
p = q + 1;
}
if (((int)(q - p) < k) && (*(q + 1) == '\0')) {
swap(s, p, (int)(q - p) + 1);
return s;
}
if ((*(q + 1) == '\0')){
swap(s, p, k);
return s;
}
q++;
}
return s;
}
时间复杂度O(N^2)
空间复杂度O(1)
题目链接:剑指Offer.05替换空格
题目本身不难,但这一题的关键是数组最后一定要加'\0'这个细节,这在malloc返回数组的时候就要注意了,整体代码给出如下:
char* replaceSpace(char* s){
int i = 0;
char *p = s;
while (*p != '\0') {
if (*p == ' ')
++i;
++p;
}
char *ret = (char *)malloc(sizeof(char) * (strlen(s) + 2 * i + 1));
char *q = ret;
p = s;
while (*p != '\0') {
if (*p != ' ') {
*(q++) = *(p++);
} else {
*(q++) = '%';
*(q++) = '2';
*(q++) = '0';
++p;
}
}
*q = '\0';
return ret;
}
时间复杂度O(N)
空间复杂度O(N)
题目链接:151.翻转字符串里的单词
这一题首先需要去除字符串中多余的空格,接着我们可以将整个字符串反转,接着分别对每个单词进行翻转就可以求解,代码给出如下:
void remove_space(char *s) {
int start = 0;
int end = strlen(s) - 1;
int index = 0;
while (s[start] == ' ')
++start;
while (s[end] == ' ')
--end;
for (int i = start; i <= end; ++i) {
if (s[i] == ' ' && s[i + 1] == ' ')
continue;
s[index++] = s[i];
}
s[index] = '\0';
}
void swap(char *s, int left, int len) {
int middle = len / 2;
for (int i = left; i < (middle + left); ++i) {
s[i] ^= s[left + len - 1 - (i - left)];
s[left + len - 1 - (i - left)] ^= s[i];
s[i] ^= s[left + len - 1 - (i - left)];
}
}
void reverse(char* s, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
char * reverseWords(char * s){
remove_space(s);
swap(s, 0, strlen(s));
//reverse(s, 0, strlen(s) - 1); // 翻转整个字符串
int i = 0;
int j = 0;
for (j = 0; j <= strlen(s); ++j) {
if ((s[j] == ' ') || (s[j] == '\0')) {
swap(s, i, j - i);
//reverse(s, i, j-1); // 翻转单词
i = j + 1;
}
}
return s;
}
时间复杂度O(N^2)
空间复杂度O(1)
题目链接:剑指Offer58-II.左旋转字符串
这一题看到后我想到的是定义一个额外的数组,使得题目给出指针指向定义的数组,这样数组的非'\0'元素就是题目给出元素,接着将前n个复制到最后,然后返回定义数组首地址+n,这样就可以求解,代码给出如下:
char* reverseLeftWords(char* s, int n){
char *r = (char *)malloc(sizeof(char) * (strlen(s) + n + 1));
int i;
for (i = 0; i < strlen(s); ++i) {
r[i] = s[i];
}
for (int j = 0; j < n; ++j) {
r[i++] = s[j];
}
r[i] = '\0';
return r + n;
}
时间复杂度O(N)
空间复杂度O(N)
看完Carl老哥给出的方法,感觉到翻转元素的妙处所在,具体内容参考代码随想录。
今天感觉总体来说还算简单,但写代码的时候存在不细心、容易出现数组越界的情况,希望之后更加细心,加油!