目标
实现将顺序表(数组)中的结点循环右移 k 位的运算。要求算法的时间复杂度为 O(n),空间复杂度为 O(1)。
解决方法
方案1---逆序法
#include <iostream>
using namespace std;
#define MAXSIZE 100
typedef struct {
int *elem;
int length;
}Array;//大家不用纠结用不用创建结构体,都可以
int arr[MAXSIZE] = {1,2,3,4,5,6,7};
void reverse(int start, int end);
int main() {
int k;
Array array;
array.length = 7;
array.elem = arr;
cout << "input K:";
cin >> k;
k = k % array.length;//简单优化一下输入数据
reverse(0, array.length - 1);//先全部逆序
reverse(0, k - 1); //逆序前半部分
reverse(k, array.length - 1);//逆序后半部分(也可以最后进行全部逆序)
for (int i = 0; i <= array.length - 1; i++) {
cout << arr[i] << " ";
}
return 0;
}
//核心:
void reverse(int start, int end) {
int num = (end - start + 1) / 2;//因为前后交换,所有循环一半
for (int i = 1; i <= num; i++) {
int tmp;
tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
end--;
start++;
}
}
例如:移动4位
原数组 123456
全部逆置 654321
前半部分逆置 + 后半部分逆置 345612
方案2---公式法
右移动K位后 该数据所在位置
核心公式 : 该数据下标 =(原位置下标 + K)% 数据总数
但需要创建一个新数组来存储移动后的所有数据
#include <iostream>
using namespace std;
#define MAXSIZE 100
typedef struct {
int *elem;
int length;
}Array;//大家不用纠结用不用创建结构体,都可以
int arr[MAXSIZE] = {1,2,3,4,5,6,7};
void reverse(int start, int end);
int main() {
int k;
int newarr[MAXSIZE] = {0};
Array array;
array.length = 7;
array.elem = arr;
cout << "input K:";
cin >> k;
k = k % array.length;//简单优化一下输入数据
for (int i = 0; i <= array.length -1; i++) {
newarr[(i + k) % array.length] = arr[i];
}
for (int i = 0; i <= array.length - 1; i++) {
cout << newarr[i] << " ";
}
return 0;
}
方案3---自创的 哈哈哈哈
既然被迫新开辟数组,那我们也可以尝试另一种与公式法类似的方法。
我用新数组去 “扫描” 原数组,但不是头 “扫描”,而是从算出的应该是第一个数的下标开始 “扫描”。
例如:移动4位
从字符4 开始存入新数组。
我就不展示代码了,就是给出我一开始的想法。哈哈哈哈
解决方法还有,我就写出了我感觉不错的方案1和方案2。
如果有不准确的地方,欢迎大家指正。