题目描述:将一个n元一维向量向左旋转i个位置。例如:当n=8且i=3时,向量abcdefgh旋转为defghabc。
其实这类问题方法有很多中,我就介绍两种比较特殊的方法:一种时间复杂度为O(n),空间复杂度O(1),另一种时间复杂度为O(1),空间复杂度为O(n)(以上空间复杂度不包括存储原字符串的空间)
方法一的思路:将字符串分为两个向量ab,a为前i-1个字符组成的向量,b为剩下字符组成的向量;首先将a逆序,得到a(r)b,再将b逆序,得到a(r)b(r),最后将整体逆序得到(a(r)b(r))(r) = ba;
例如字符串abcdefgh左旋转i=3,则a=abc,b=defgh
reverse(str, 0, i-1) => cbadefgh
reverse(str, i, len-1) => cbahgfed
reverse(str, 0, len-1) => defghabc
这里有个细节需要注意,当i大于等于字符串的长度时,需要对i相对于len求余,即i = i%len
具体代码如下:
#include <iostream>
#include <cstring>
using namespace std;
void exch(char &a, char &b) { char temp = a; a=b; b=temp; }
void reverse(char *str, int start, int end) //从start到end逆序str中的字符
{
char *p=NULL;
int i=start, j=end;
while(i<j)
{
exch(*(str+i),*(str+j));
i++;
j--;
}
}
void rev_str(char *str, int shift)
{
int len = strlen(str);
if(shift>=len) shift %= len;
reverse(str, 0, shift-1);
reverse(str, shift, len-1);
reverse(str, 0, len-1);
}
int main(void)
{
const int SHIFT = 9;
char str[100]="123456";
rev_str(str, SHIFT);
cout << str << endl;
return 0;
}
方法二,典型的用空间换取时间
具体思路:申请一个与原字符串等大的内存空间的临时数组,首先将b向量(将字符串分为两个向量的思路与方法一等同)复制到临时数组中,再将a向量复制到临时数组中,最后将临时数组的内容复制到原字符串中
strncpy(temp, &str[shift], len-shift)
strnpy(&temp[len-shift], str, shift);
temp[len]='\0'; //这是细节需要特别注意,因为之前temp并不是一个字符串,没有结束标志
strcpy(str, temp);
具体实现代码如下:
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
void rev_str(char *str, int shift)
{
int step=0;
int len = strlen(str);
shift = shift>=len ? shift%len : shift;
char *temp = (char *)malloc(len+1);
//在内存中进行相应位置的拷贝字符,从而达到字符旋转的目的
strncpy(temp, &str[shift], len-shift);
strncpy(&temp[len-shift], str, shift);
temp[len]='\0';
strcpy(str, temp);
}
int main(void)
{
const int SHIFT = 2;
char str[] = "123456";
rev_str(str, SHIFT);
cout << str << endl;
return 0;
}
以上方法知识其中的两种,若有更好的方法,或者我的方法有什么不妥,可以与我交流,互相学习!