数组的移动问题

#include<stdio.h>
#include<assert.h>

void Left_Move_Array(int* a, int size)//数组向左移一位
{
	assert(a != nullptr && size > 0);//数组检查,结果为真向下执行
	int temp = a[0];//保存首元素
	for (int i = 0; i < size - 1; ++i)//左移size - 1 次
	{
		a[i] = a[i + 1];
	}
	a[size - 1] = temp;//首元素置于数组末尾
	return;
}

void Right_Move_Array(int *a, int size)//数组向右移一位
{
	assert(a != nullptr && size > 0);//数组检查
	int temp = a[size - 1];//保存数组最后一个元素
	for (int i = size - 1; i > 0; --i)//执行size - 1 次,各元素右移一位
	{
		a[i] = a[i - 1];
	}
	a[0] = temp;//末尾元素置于数组首位
	return;
}

void Left_Move_Array_Key(int* a, int size, int k)//左移k位
{
	assert(a != nullptr && size > 0);//检查
	k = k % size;//提高效率,若数组规模为10,那么移动4次和移动14次是一样的
	if (k >= 0)
	{
		while (k--)//左移k位相当于一次移动一位,移动k次
		{
			Left_Move_Array(a, size);
		}
	}
	else
	{
		while (k++)//若输入的值是负值,左移相当于右移
		{
			Right_Move_Array(a, size);
		}
	}

	return;
}

void Right_Move_Array_Key(int* a, int size, int k)//右移k位
{
	assert(a != nullptr && size > 0);//检查
	Left_Move_Array_Key(a, size, -k);//刚好与左移k位相反
	return;
}
int main()
{
	const int n = 10;
	int ar[n] = { 1,2,3,4,5,6,7,8,9,10 };
	Right_Move_Array_Key(ar, n, 3);
	for (int j = 0; j < n; ++j)
	{
		printf("%d\n", ar[j]);
	}

	return 0;
	
}

上述代码时间复杂度较大,下面我们来看一种复杂度较小的解法,以左移为例。假如要讲一个数组左移k位,我们可以将数组从下标k处分开,将0到k-1下标分为一组,将k到n-1分为一组,然后将每个数组最左边元素(设为left)和最右边元素(设为right)交换,然后left++且right- - ,直至left = right时为止,然后再将整个数组的两端元素两两交换即可完成。
例如一个数组ar = {1,2,3,4,5,6,7,8,9,10},要左移4位,我们可以把下标为0~3的元素,即1 2 3 4 分为一组,剩下的元素分为一组,然后两两交换使其原地逆置,即变为{4,3,2,1,10,9,8,7,6,5},再将整个数组两两交换即变为{5,6,7,8,9,10,1,2,3,4},左移完成,这样的解法可以将时间复杂度降至O(k)。
代码如下:

#include<stdio.h>
#include<assert.h>
void swap(int* a, int* b)//交换函数
{
	int temp = *a;
	*a = *b;
	*b = temp;
	return;
}
void Resreve(int* br, int left, int right)//数组就地逆置函数
{
	assert(br != nullptr && left < right);//数组检查
	while (left < right)//当left < right 时 将 left和right交换反复执行
	{
		swap(&br[left], &br[right]);
		left++;
		right--;
	}
	return;
}

void Left_Move_Key(int* br, int k, int n)//左移函数
{
	assert(br != nullptr && n > 0);//数组检查
	Resreve(br, 0, k - 1);//就地逆置前k-1个元素
	Resreve(br, k, n - 1);//就地逆置后n - k 个元素
	Resreve(br, 0, n - 1);//在整个数组中将两端元素两两交换完成左移任务
}

int main()
{
	const int n = 10;
	int ar[n] = { 1,2,3,4,5,6,7,8,9,10 };
	Left_Move_Key(ar, 4, n);

	for (int i = 0; i < n; ++i)
	{
		printf("%4d", ar[i]);
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值