参考
问题描述
设计一个算法,将数组A[1:n]中的元素循环右移k位,要求只使用一个元素的附加空间,元素移动或交换次数为O(n).
然后这样是不行的。
转而去网上求助。
假如原数组: 1 2 3 4 5 6 7 需要右移4次,那么我们想要的结果是: 5 6 7 1 2 3 4。
1.将1234逆置 变成 4321
2.将567逆置 变成 765
3.将两个逆置数组拼接: 4321765
4.将这个已拼接的数组逆置: 5671234 就成了我们想要的结果了。
————————————————
版权声明:本文为CSDN博主「chomol」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mayh554024289/article/details/47914237
如果把部分逆置的话,确实只需要一个元素的附加空间,而且时间复杂度为O(n)
其实这就是把字符串看做两个整体来移动。1234567–>1234|567–>567|1234
分析
从第一个元素开始,在移动k位之前,将他要移动到的位置的元素先存储起来。然后将其移动到那个位置,再将其存储的元素移动k位。依次类推。循环到把所有元素都移动完的时候结束。(总共移动次数等于元素个数)
但是有个问题就是,比如有9个元素,
code
void move(char str[], int k)
{
int len, i = 0, goal = 0;//数组长度,要移动的元素的位置,目标移动位置
char tem;
len = strlen(str);
while(len--)
{
goal = (i + k) % len;//实现循环移动的操作
tem = str[goal];//赋值
str[goal] = str[i];//存储下来要即将移动到的位置的元素
i = goal;
}
}
最初写出来的程序。我觉得没毛病啊,但是什么都输出不了。
呸,一堆错误。谁让你len--
了?len不是就变了吗???而且这个算法是错误的根本不能移动每一位元素。
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
void move(char str[], int k);//将str数组中的元素循环移动k位
void inverse(char str[], int start, int end);//将字符串的[start, end]部分逆置
int main()
{
char str[100];
int k;//要移动的位置
cout<<"请输入字符串"<<endl;
cin>>str;
cout<<"请输入移动位置"<<endl;
cin>>k;
move(str, k);
cout<<"结果:"<<endl;
cout<<str;
return 0;
}
void move(char str[], int k)
{
int len = strlen(str);//字符串长度
inverse(str, len - k % len, len - 1);//逆置右半边字符串
inverse(str, 0, len - k - 1);//逆置左半边字符串
inverse(str, 0, len - 1);//逆置所有字符串
}
void inverse(char str[], int start, int end)
{
int i, j;
char tem;
for(i = start, j = end; i <= (start + end) / 2; i++, j--)
{
tem = str[i];
str[i] = str[j];
str[j] = tem;
}
}
输出正确
总结
1.每次不要只举了一个例子就以为能找到规律。要多找几个例子,还要想到特殊情况。
2.注意分开测试,每写出一个函数就做一下测试。