题目描述:对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。
方法一:使用辅助内存
string LeftRotateString(string str, int n) {
if(str.length()==0) return str;
n=n%str.length();
string Tail(str,0,n);
string Head(str,n);
return Head+Tail;
}
方法二:分段翻转
abc->cba
XYZdef->fedZYX
合并cbafedZYX->XYZdefabc
string LeftRotateString(string str, int n) {
reverse(str.begin(),str.begin()+n);
reverse(str.begin()+n,str.end());
reverse(str.begin(),str.end());
return str;
}
方法三:海豚算法
只借助若干个字节的缓存,在原内存中进行修改,时间复杂度也比较低
int gcd(int x, int y)
{
int z = y;
while(x%y!=0)
{
z = x%y;
x = y;
y = z;
}
return z;
}
void Shifting(char * pArry, int rotdistance, int len)
{
int i, j;
char temp;
int igcd = gcd(rotdistance, len);
for (i = 0; i < igcd; i++)
{
temp = pArry[i];
j = i;
for (; ;)
{
int k = j + rotdistance;
k %= len;
if ( k == i)
{
break;
}
pArry[j] = pArry[k];
j = k;
}
pArry[j] = temp;
}
}
原理是利用最大公约数。在上面的例子中,rotdistance=3,igcd=3,len=9;所以进行三次循环每次循环的(j,k)对分别是(0,3,6),(1,4,7)(2,5,8),这样所有的就都遍历一遍了。与第二种方法相比,就排除了rotdistance=0的翻转两次的情况。
方法四:分块交换
//交换pArry[a...a+m-1]和pArry[b...b+m-1]
void myswap(char *pArry, int a, int b, int m)
{
char temp;
for (int i = 0; i < m; i++)
{
temp = pArry[a + i];
pArry[a + i] = pArry[b + i];
pArry[b + i] = temp;
}
}
void Shifting(char * pArry, int rotdistance, int len)
{
if (rotdistance == 0 || rotdistance == len)
{
return;
}
int i, j, p;
i = p = rotdistance;
j = len - p;
while (i != j)
{
if (i > j)
{
myswap(pArry, p - i, p, j);
i -= j;
}
else
{
myswap(pArry, p - i, p + j - i, i);
j -= i;
}
}
myswap(pArry, p - i, p, i);
}
本方法