问题描述:
将一个数组向右循环移位 k 位,要求只使用两个参数,时间复杂度为 O(N)。
思路 1:
采用蛙跳的方式,用当前的元素 i,替换第i+k个元素,这样逐一替换N次后,数组被移位完成。
当然这时要区分能两种情况,N
能整除k 和 N
不能整除k,这时跳的方式是不一样的。
时间复杂度 O(N)
假设 N = 7 k = 3 (N不能整除k), 假设 N = 9 k = 3 (N能整除k)
思路 2:
例如 1 2 3 4 5 6 7,移位3位后会变成 5 6 7 1 2 3 4。
找规律, 发现 5 6 7是会被移动的,所以书中的想法是把数组分成两个部分 一部分是 0 到 N-k-1,
另一部分是 N - k 到 N。
第一次变化: 将数组中 0 到
N-k-1进行翻转
第二次变化: 将数组中
N - k 到 N进行翻转
第三次变化: 将整个数组进行翻转
1 2 3 4
5 6 7 == 第一次变化 ==>
4 3 2 1
5 6 7
== 第二次变化 ==> 4 3 2 1 7 6 5 == 第三次变化 ==> 5 6 7 1 2 3 4
要遍历两次数组 2xN,时间复杂度 O(N)
#include <iostream>
using namespace std;
void printarr(int arr[], int len)
{
int i = 0;
for (i = 0 ; i < len; i++)
{
cout << arr[i] << " ";
}
cout << endl << endl;
}
/////////////////////////////////////////////////////
// algorithm one
/////////////////////////////////////////////////////
void swap1(int arr[], int len, int k)
{
int i = 0, cnt=0;
cout << "Algorithm 1: "<< "shift: " << k << endl;
k %= len;
if (len%k == 0)
{
cnt = 0;
while(cnt < k)
{
for (i = cnt+k; i < len; i=i+k)
{
arr[cnt] = arr[cnt] ^ arr[i];
arr[i] = arr[i] ^ arr[cnt];
arr[cnt] = arr[cnt] ^ arr[i];
}
cnt++;
}
}
else
{
while(cnt < len-1)
{
i = i + k;
if (i < len)
{
cout << arr[0] << "<==>" << arr[i] << endl;
arr[0] = arr[0] ^ arr[i];
arr[i] = arr[i] ^ arr[0];
arr[0] = arr[0] ^ arr[i];
}
else
{
i = i%len;
cout << arr[0] << "<==>" << arr[i] << endl;
arr[0] = arr[0] ^ arr[i];
arr[i] = arr[i] ^ arr[0];
arr[0] = arr[0] ^ arr[i];
}
cnt++;
}
}
printarr(arr, len);
}
/////////////////////////////////////////////////////
// algorithm two
/////////////////////////////////////////////////////
void reserve(int arr[], int l, int r)
{
int tmp = 0;
for(; l < r; l++, r--)
{
tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
}
void swap2(int arr[], int len, int k)
{
cout << "Algorithm 2: "<< "shift: " << k << endl;
k %= len;
reserve(arr, 0, len-k-1);
reserve(arr, len-k, len-1);
reserve(arr, 0, len-1);
printarr(arr, len);
}
int main()
{
int len = 0, k = 0;
int test[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
len = sizeof(test)/sizeof(test[0]);
int *parr = new int[len];
k = 4;
memcpy(parr, test, len*sizeof(int));
cout << "----------------------------------" << endl;
printarr(parr, len);
swap1(parr, len, k);
memcpy(parr, test, len*sizeof(int));
swap2(parr, len, k);
k = 2;
memcpy(parr, test, len*sizeof(int));
cout << "----------------------------------" << endl;
printarr(parr, len);
swap1(parr, len, k);
memcpy(parr, test, len*sizeof(int));
swap2(parr, len, k);
k = 1;
memcpy(parr, test, len*sizeof(int));
cout << "----------------------------------" << endl;
printarr(parr, len);
swap1(parr, len, k);
memcpy(parr, test, len*sizeof(int));
swap2(parr, len, k);
k = 3;
memcpy(parr, test, len*sizeof(int));
cout << "----------------------------------" << endl;
printarr(parr, len);
swap1(parr, len, k);
memcpy(parr, test, len*sizeof(int));
swap2(parr, len, k);
delete[] parr;
cin >> len;
return 0;
}