首先,说明一下。我看过题解,至于文章算不算原创,我就不敢保证了。如果,不算原创,咱在这就对不起了。
题意呈上,望主子能理解:给你一串文本串str 与位移数k,现在让你在O(n)的时间复杂度,与O(1)的空间复杂度,是的原来的文本串整体位移K位。
例如:str = "abcdefg", k = 3;那么结果就应该是defgabc
目前为止:已经想到有3种方案,欢迎补充。
方案一:看题解的做法是:
1.假设串长为n;
2.先将原串分为两个字串;
3.如果左移那么就是str[0 … k-1]与str[k…n-1],反之为str[0 … len-k-1]与str[len - k - 1…n-1];
4.将两个字串各自翻转得到整体的str
5.再将最后的str翻转即可。
这样时间刚刚好为O(N);
演示一遍:str = "abcdefg", k = 3
1.n = strlen(str);
2.str[0…2] = “abc” str[3…6] = “defg”
3.翻转字串,得到str=“cbagfed”
4.最后在讲str翻转得:str = “defgabc”
方案二:自己的想法,不知道正确与否;
1.从原串中任意一处出发;
2.然后使用记录当前的位置上的字符,赋给想移位k的地方;
3.一直循环下去,知道循环位置达到n次后就停止;
例如:str=“abcd” k = 3 。我的初始地点第一位,那么可以得到:
第一趟:aacd ch=‘b’
第二趟:aabd ch=‘c’
第三趟:aabc ch=‘d’
第四趟:dabc 结束。
当str=“abcde” k=2是,我的思路如上图。
可后来我们考虑一下,如果如果n % k == 0,结果就不对,只是因为n = k * x,x为一个循环节。所以遇到此情况我们要特判。向前向后移一位继续进行下去,不过我不是很清楚这种方案是否可行。望大神指导,在下不甚欢喜。
方案三:这个方案来自于我的师弟;
1.将str[0…k - 1]与str[k…2*k- 1]交换,以此类推;
2.当出现len-xk<k时就改变k的循环节,使k=xk+k-len-1;
3.重复1,2步骤;直至到达最后的len。
例如:abcdefg 4
第一趟:efgdabc k=1
第二趟:efgadbc k = 1
第三趟:efgabdc k = 1
第四趟:efgabcd 结束
最后,电脑没装作图的,只能随便画了下,见谅。
第一次,写博客,见谅。
附代码两份,代码比较戳,见谅。
#include <iostream>//自己的思路代码
using namespace std;
#include <cstring>
#include <string>
const int MAX = 100 + 10;
char str[MAX];
//int res(char *str, int )
int main()
{
int k, num, start, i;//start表示循环次数,num表示是否回到了循环起点,i跳转点。
char ch, s;
while (cin >> str >> k)
{
int len = strlen(str);
ch = str[len - 1];
start = 0, i = len - 1;
num = len - 1;
while (start++ < len)
{
s = str[(i + len - k) % len];
str[(i + len - k) % len] = ch;
ch = s;
i = (i + len - k) % len;
if (i == ((num + k + len) % len) && start != len)//当发现找到循环节点,我们就将i移向下一位即可。
{
str[num] = ch;
start++;
ch = str[(i + len + 1) % len];
num = i = (i + len + 1) % len;
}
}
puts(str);
}
return 0;
}
#include <iostream>//题解所述的代码
using namespace std;
#include <cstring>
#include <string>
const int MAX = 100 + 10;
char str[MAX];
int sum;
void resarse(char *str, int start, int end)
{
while (start < end)
{
swap(str[start], str[end]);
start++;
end--;
sum++;
}
}
int main()
{
int k;
while (cin >> str >> k)
{
int len = strlen(str);
k %= len;
sum = 0;
resarse(str, 0, k - 1);
resarse(str, k, len - 1);
resarse(str, 0, len - 1);
puts(str);
printf("%d\n", sum);
}
return 0;
}
#include <iostream>//方案三
using namespace std;
const int MAX = 100 + 10;
char str[MAX];
bool change(char *str, int start, int end, int k)
{
for(int i = start; i < end; i++)
{
if (end - i - 1 >= k)
{
swap(str[i], str[i + k]);
if (end - i - 1 == k && end % k == 0) return true;//找到最后一个循环节点
}
else
{
if (end == i + 1) return true;
k = k + i - end + 1;//将循环节点改变,类似于辗转相除
if (change(str, i, end, k)) return true;
}
}
}
int main()
{
int k, i;
while (cin >> str >> k)
{
int len = strlen(str);
change(str, 0, len, k);
puts(str);
}
return 0;
}