目录
问题描述:字符串0123456789 向左移动i=3位 3456789012
问题描述:字符串0123456789 向左移动i=3位 3456789012
有五种方法:
方法一:原始法
算法思想:从左向右依次移动一位,对所有数据平移;这样循环pos次
(最坏)时间复杂度:O(n**2)
空间复杂度:O(1)
void move1(char* in, int pos, int len)
{
for (size_t i = 0; i < pos; i++)
{
int temp = in[0];
for (size_t j = 1; j < len; j++)
{
in[j - 1] = in[j];
}
in[len - 1] = temp;
}
}
方法二:空间换时间
时间复杂度:O(n)
空间复杂度:O(n)
void move2(char* out, char* in, int pos, int len)
{
if (pos == 0)
out = in;
for (size_t i = pos; i < len; i++)
{
out[i - pos] = in[i];//先移动num之后的元素
}
for (size_t i = 0; i < pos; i++)
{
out[len - pos + i] = in[i];//再移动前num位
}
out[len] = '\0';
}
方法三:求模置换法
算法思想:尽量让每个数一次移动到位。总体的思想是:以i为除数对n求模,将向量遍历完并一次移动到位。
时间复杂度:O(n)
空间复杂度:O(1)
void move3(char* in, int pos, int len)
{
int temp=in[0];
for (int i = pos; in[i]==temp;)
{
in[i-pos] = in[i];
i += pos;
i = i % len;
}
}
方法四:分段递归交换法 ab1b2<->b2b1a
算法思想:ab1b2<->b2b1a
时间复杂度:O(n)
空间复杂度:O(1)
void swap(char* in, int a, int b, int pos)//swap in[a .. a+pos-1] and x[b .. b+pos-1]
{
char temp;
for (size_t i = 0; i < pos; i++)
{
temp = in[i+a];
in[a+i] = in[b+i];
in[b + i] = temp;
}
}
void move4(char* in, int pos, int len)//我总是想不出递归如何设计 ╮(╯▽╰)╭
{
int p = pos;
int i = p;
int j = len - p;
while (i != j) { //目的:交换p之后的部分
if (i>j)//b的长度小于a的长度,以a的长度为步长交换
{
swap(in, p-i, p, j);//p-i可以看做以j开始
i = i - j;
}
else //b部分可拆解为b1,b2,交换a和b2部分
{
swap(in, p - i, p + j - i, i);
j -= i;
}
}
swap(in, p - i, p, i);
}
方法五:求逆法
算法思想:把x向量分成ab两部分,a{-1} b{-1} ,ba=(a{-1} b{-1}){-1} .a{-1}代表a的逆。
时间复杂度:O(n)
空间复杂度:O(1)
void reverse(char* in, int s, int t)
{
char temp;
int i, j;
for (i = s ,j=t; i < j; i++,j--)
{
temp = in[i];
in[i] = in[j];
in[j] = temp;
}
}
void move5(char* in, int pos, int len)
{
reverse(in, 0, pos - 1);
reverse(in, pos, len - 1);
reverse(in, 0, len - 1);
}
完整代码如下:
// 字符串移位.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//0123456789 向左移动i=3位 3456789012
//2019/5/9
#include "pch.h"
#include <iostream>
#include <string>
#pragma warning(disable:4996)
using namespace std;
//方法一:从左向右依次移动一位,对所有数据平移;这样循环pos次
//(最坏)时间复杂度:O(n**2)
//空间复杂度:O(1)
void move1(char* in, int pos, int len)
{
for (size_t i = 0; i < pos; i++)
{
int temp = in[0];
for (size_t j = 1; j < len; j++)
{
in[j - 1] = in[j];
}
in[len - 1] = temp;
}
}
//方法二:空间换时间
//时间复杂度:O(n)
//空间复杂度:O(n)
void move2(char* out, char* in, int pos, int len)
{
if (pos == 0)
out = in;
for (size_t i = pos; i < len; i++)
{
out[i - pos] = in[i];//先移动num之后的元素
}
for (size_t i = 0; i < pos; i++)
{
out[len - pos + i] = in[i];//再移动前num位
}
out[len] = '\0';
}
//方法三:求模置换法
//算法思想:尽量让每个数一次移动到位。总体的思想是:以i为除数对n求模,将向量遍历完并一次移动到位。
//时间复杂度:O(n)
//空间复杂度:O(1)
void move3(char* in, int pos, int len)
{
int temp=in[0];
for (int i = pos; in[i]==temp;)
{
in[i-pos] = in[i];
i += pos;
i = i % len;
}
}
//方法四:分段递归交换法 ab1b2<->b2b1a
//算法思想:ab1b2<->b2b1a
//时间复杂度:O(n)
//空间复杂度:O(1)
void swap(char* in, int a, int b, int pos)//swap in[a .. a+pos-1] and x[b .. b+pos-1]
{
char temp;
for (size_t i = 0; i < pos; i++)
{
temp = in[i+a];
in[a+i] = in[b+i];
in[b + i] = temp;
}
}
void move4(char* in, int pos, int len)//我总是想不出递归如何设计 ╮(╯▽╰)╭
{
int p = pos;
int i = p;
int j = len - p;
while (i != j) { //目的:交换p之后的部分
if (i>j)//b的长度小于a的长度,以a的长度为步长交换
{
swap(in, p-i, p, j);//p-i可以看做以j开始
i = i - j;
}
else //b部分可拆解为b1,b2,交换a和b2部分
{
swap(in, p - i, p + j - i, i);
j -= i;
}
}
swap(in, p - i, p, i);
}
//方法五:求逆法
//算法思想:把x向量分成ab两部分,a是前i个元素,b是后n-i个元素,首先对a求逆,然后对b求逆,然后对整体求逆得到ba
//时间复杂度:O(n)
//空间复杂度:O(1)
void reverse(char* in, int s, int t)
{
char temp;
int i, j;
for (i = s ,j=t; i < j; i++,j--)
{
temp = in[i];
in[i] = in[j];
in[j] = temp;
}
}
void move5(char* in, int pos, int len)
{
reverse(in, 0, pos - 1);
reverse(in, pos, len - 1);
reverse(in, 0, len - 1);
}
int main()
{
char in[] = { '0','1','2','3','4','5','6','7','8','9','\0'};//len=10
int len = strlen(in);
int num = 3;
cout << "-----------------方法一:平移法 --------------------" << endl;
char *copy_in=new char[len];
strcpy(copy_in, in);
cout << copy_in << endl;
move1(copy_in, num, len);
cout << copy_in << endl;
cout << "-----------------方法二:空间换时间--------------------" << endl;
char* out=new char[len];
cout << in << endl;
move2(out, in, num, len);
cout << out<< endl;
cout << "-----------------方法三:求模置换法--------------------" << endl;
char *copy_in2 = new char[len];
strcpy(copy_in2, in);
cout << copy_in2 << endl;
move3(copy_in2, num, len);
cout << out << endl;
cout << "-----------------方法四:分段递归交换法-----------------" << endl;
char *copy_in3 = new char[len];
strcpy(copy_in3, in);
cout << copy_in3 << endl;
move4(copy_in3, num,len);
cout << copy_in3 << endl;
cout << "-----------------方法五:求逆法-----------------" << endl;
char *copy_in4 = new char[len];
strcpy(copy_in4, in);
cout << copy_in4 << endl;
move5(copy_in4, num, len);
cout << copy_in4 << endl;
std::cout << "Hello World!\n";
return 0;
}