字符串移位

目录

 

问题描述:字符串0123456789 向左移动i=3位 3456789012

方法一:原始法

方法二:空间换时间

方法三:求模置换法

方法四:分段递归交换法 ab1b2<->b2b1a

方法五:求逆法


问题描述:字符串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;
}

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值