问题:
假设给定一个字符串S,想要把其前k个字符左移放到字符串的尾部,比如S:beautiful,移动的结果字符串为:utifulbea;这种移动方式就叫做字符串的循环左移,且左移k位。
问题分析:
假如字符串S包含n个字符,那么明显有,循环左移k位等价于循环左移k+n位,而且循环左移和循环右移其实是一样的,如左移k位就等价于左移n-k位。
一般的,遇到这一问题,大多数人会首先想到一位一位的移动,直到满足要求,这种移位方法也可以达到算法的实现,但是从算法的性能上来看,即时间复杂度和空间复杂度上来看,并非最优,因为这是一种所谓的笨办法,也就是暴力法;对于要移动k位,这种解决方案的时间复杂度和空间复杂度分别为:O(kn)和O(1),那么有没有更好的方法呢?答案当然是肯定的。
回想下矩阵的计算中关于转置的部分有这样一个性质:,现在我们可以把这一性质利用到这以问题的解决上,即:
设字符串S = “beautiful”,其中如果想要左移前三位,则字符串A=“bea”,B= “utiful”,所以有:
这样一来,时间复杂度为O(n),空间复杂度仍为O(1),明显效率要高。
C++实现:
//翻转某一段字符串
void strReverse(string &str,int idxFrom,int idxTo)
{
while (idxFrom < idxTo) {
char tmp = str[idxFrom];
str[idxFrom ++] = str[idxTo];
str[idxTo --] = tmp;
}
}
//循环左移
void strLeftMoving(string &str,int n ,int k){
k = k % n;
strReverse(str, 0, k-1);//转置A
// cout<<""<<str<<endl;
strReverse(str, k, n-1);//转置B
// cout<<""<<str<<endl;
strReverse(str, 0, n-1);//整个字符串转置
}
int main()
{
string S = "beautiful";
strLeftMoving(S, 9, 3);
cout<<""<<S<<endl;
return 0;
}
运行结果: