/*
* 左旋转字符串:
* abcdef,左旋转2,得到cdefab
* -------------------------
* void LeftRotate(char* arr, int length, int num);
* 时间复杂度O(n), 空间复杂度O(1)
*/
void LeftRotate(char* arr, int length, int num);
void TestLeftRotate();
// 指针版本实现
void ReversePchar(char *pStart, char *pEnd);
void LeftRotate_2(char *str, unsigned num);
// 解法2:逐步右移前半部分,直到结束。
void LeftRotate_3(char *str, unsigned num);
// 使用两个指针,表达更清晰
void LeftRotate_4(char *str, unsigned num);
// 递归实现方式
void LeftRotateRecursive(char *p1, unsigned len1, char *p2, unsigned len2, bool left);
void LeftRotate_5(char *str, unsigned num);
void Swap_2(char *p1, char *p2, unsigned len);
// 循环链实现
void LeftRotate_6(char *str, unsigned num);
void LoopLink(char *pStart, char *pMiddle, char *pEnd);
int MyGcd(int m, int n);
// 交换p1和p2的内容,共交换num次
void Swap(char *p1, char *p2, unsigned num);
// 最后一次交换,需满足:len1 > len2
void LastSwap(char *p1, unsigned len1, char *p2, unsigned len2);
void RightShift(int *arr, int N, int K);
void TestRightShift();
/*
* 交换两部分的内容: 线性时间内实现右移操作。三次翻转算法!
* ab123->123ab
* 1.逆序:ba321
* 2.分别逆序:ba->ab 321->123
* 3.得到结果:ab123
*/
void RightShift_2(int *arr, int N, int K);
void RightShift_3(int *arr, int N, int K);
/*
* 逆序排列:abcd->dcba
* 从第几位开始
* 到第几位结束
*/
void Reverse(int *arr, int start, int end);
void Reverse(char *arr, int start, int end);
#include <iostream>
#include <assert.h>
#include <string>
#include "1_LeftRotate.h"
using namespace std;
// 不做输入验证了...
void RightShift(int *arr, int N, int K)
{
// 开始考虑不周:K>N K < 0
K = K % N;
while (K--)
{
int tmp = arr[N - 1];
for (int i = N - 1; i > 0; --i)
{
arr[i] = arr[i - 1];
}
arr[0] = tmp;
}
}
void TestRightShift()
{
int arr[6] = {1, 2, 3, 4, 5, 6};
RightShift(arr, 6, 2);
int arr2[6] = {1, 2, 3, 4, 5, 6};
RightShift_2(arr2, 6, 3);
int arr3[6] = {1, 2, 3, 4, 5, 6};
RightShift_3(arr3, 6, 3);
}
void Reverse(int *arr, int start, int end)
{
for ( ; start < end; start++, end--)
{
int tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
}
}
void Reverse(char *arr, int start, int end)
{
for ( ; start < end; start++, end--)
{
char tmp = arr[start];
arr[start] = arr[end];
arr[end] = tmp;
}
}
void ReversePchar(char *pStart, char *pEnd)
{
assert(pStart != NULL);
assert(pEnd != NULL);
while (pStart < pEnd)
{
char tmp = *pStart;
*pStart = *pEnd;
*pEnd = tmp;
pStart++;
pEnd--;
}
}
void RightShift_2(int *arr, int N, int K)
{
K = K % N;
Reverse(arr, 0, N - K - 1);
Reverse(arr, N - K, N - 1);
Reverse(arr, 0, N - 1);
}
void RightShift_3(int *arr, int N, int K)
{
K = K % N;
Reverse(arr, 0, N - 1);
Reverse(arr, 0, K - 1);
Reverse(arr, K, N - 1);
}
void LeftRotate(char* arr, int length, int num)
{
num = num % length;
num = length - num;
Reverse(arr, 0, length - 1);
Reverse(arr, 0, num - 1);
Reverse(arr, num, length - 1);
}
void LeftRotate_2(char *str, unsigned num)
{
unsigned length = strlen(str);
num = num % length;
ReversePchar(str, str + num - 1);
ReversePchar(str + num, str + length - 1);
ReversePchar(str, str + length - 1);
}
void TestLeftRotate()
{
//char arr[] = {'a', 'b', 'c', 'd', 'e', 'f'};
//LeftRotate(arr, 6, 2);
//char arr2[] = "abcdef";
//LeftRotate_2(arr2, 3);
//cout << arr2 << endl;
//char arr3[] = "abcdefghi";
LeftRotate_3(arr3, 3);
//LeftRotate_4(arr3, 3);
//cout << arr3 << endl;
//char arr4[] = "abcdefghij";
LeftRotate_3(arr4, 3);
//LeftRotate_4(arr4, 3);
//cout << arr4 << endl;
char str[] = "abcdef";
//LeftRotate_5(str, 2);
LeftRotate_6(str, 2);
cout << str << endl;
char str2[] = "abcdefg";
LeftRotate_6(str2, 2);
cout << str2 << endl;
}
void LeftRotate_3(char *str, unsigned num)
{
unsigned length = strlen(str);
unsigned pos = 0;
while (pos + num + num <= length)
{
Swap(str + pos, str + pos + num, num);
pos += num;
}
if (length % num != 0)
{
LastSwap(str + pos, num, str + pos + num, length - pos - num);
}
}
void LeftRotate_4(char *str, unsigned num)
{
unsigned length = strlen(str);
char *p1 = str;
char *p2 = str + num;
while (p2 + num <= str + length)
{
Swap(p1, p2, num);
p1 = p2;
p2 += num;
}
if (p2 != str + length)
{
LastSwap(p1, num, p2, str + length - p2);
}
}
void Swap(char *p1, char *p2, unsigned num)
{
while (num--)
{
assert(p1 != NULL);
assert(p2 != NULL);
char tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2++;
}
}
void LastSwap(char *p1, unsigned len1, char *p2, unsigned len2)
{
// 将p1从后往前移动到p2的位置
char *p1End = p1 + len1 - 1;
char *p2End = p2 + len2 - 1;
char *tmp = new char[len2];
// 保存p2
for (unsigned i = 0; i < len2; ++i)
{
tmp[i] = *(p2 + i);
}
// 将p1移动到相应位置
for (unsigned i = 0; i < len1; ++i)
{
*p2End-- = *p1End--;
}
// 将p2保存到相应位置
for (unsigned i = 0; i < len2; ++i)
{
*(p1 + i) = tmp[i];
}
delete []tmp;
}
// 将p1所指向的长度为len1的字符串与p2所指向的长度为len2的字符串交换位置
// 前提是:len1 <= len2
void LeftRotateRecursive(char *p1, unsigned len1, char *p2, unsigned len2, bool left)
{
if (len1 == 0)
return;
// 可以考虑一次移动到位!!!
while (len1 <= len2)
{
Swap_2(p1, p2, len1);
if (left)
{
p1 += len1;
p2 += len1;
}
else
{
p1 -= len1;
p2 -= len1;
}
len2 -= len1;
}
if (len1 > len2)
{
LeftRotateRecursive(p2, len2, p1 + len1 - 1, len1, !left);
}
}
void LeftRotate_5(char *str, unsigned num)
{
unsigned length = strlen(str);
unsigned last = length - num;
LeftRotateRecursive(str, num, str + num, last, num <= last);
}
void Swap_2(char *p1, char *p2, unsigned len)
{
while (len--)
{
assert(p1 != NULL);
assert(p2 != NULL);
swap(*p1++, *p2++);
}
}
void LeftRotate_6(char *str, unsigned num)
{
LoopLink(str, str + num, str + strlen(str));
}
void LoopLink(char *pStart, char *pMiddle, char *pEnd)
{
unsigned n = pEnd - pStart;
unsigned k = pMiddle - pStart;
unsigned d = MyGcd(n, k);
// 一共有d个循环链
for (unsigned i = 0; i < d; ++i)
{
char first = *(pStart + i);
unsigned j = i;
do
{
*(pStart + j) = *(pStart + (j + k) % n);
j = (j + k) % n;
} while (j != i);
*(pStart + (i + n - k) % n) = first;
}
}
int MyGcd(int m, int n)
{
while (n > 0)
{
int r = m % n;
m = n;
n = r;
}
return m;
}