(1)左旋转字符串

/*
 * 左旋转字符串:
 *	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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值