数组换位问题-比较容易理解的解法

本文介绍了解决数组换位问题的两种方法:三次反转算法和平移法(循环换位算法)。三次反转算法通过三次反转操作实现数组的换位,而循环换位算法则根据数组左右两边的元素数量来决定向前或向后的循环换位,减少不必要的移动次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇数组换位问题的博客,是网上搜的,自己虽然过了一遍,但是还是理解起来有困难。上次上机课,老师给我们提示了另一新颖的解法,自己下来实现了,发此博客记录一下。

算法一:三次反转算法

主要思想:设a[0, k-1]位U,a[k, n-1]为V,换位算法要求将UV变为VU。三次反转先将U反转为U¯¹,再将V反转为V¯¹,最后将U¯¹V¯¹反转为VU。

    例如:1 2 3 4 5 6 7 阶段为位置k=2,所以,左边互换为2 1,右边互换为7 6 5 4 3,最后整体互换为3 4 5 6 7 1 2.

代码如下:

#include <stdio.h>

void swap(int *a, int *b) {
	int temp;
	
	temp = *a;
	*a = *b;
	*b = temp;
}

void reverse(int a[], int i, int j) {
	while(i < j) {
		swap(&a[i], &a[j]);
		i++;
		j--;
	}
}

void move(int a[], int n, int k) {
	reverse(a, 0, k-1);
	reverse(a, k, n-1);
	reverse(a, 0, n-1);
}

int main() {
    int i;
    int k;
    int n;

	scanf("%d", &n);	//输入数组长度 
	int a[n];
    for(i = 0; i < n; i++) {
    	scanf("%d", &a[i]);		//输入数组元素 
    }
	scanf("%d", &k);	//输入截断位置

	move(a, n, k);
    
    printf("\n");
	for(i = 0; i < n; i++) {
    	printf("%d ", a[i]);
    }
    
    return 0;
}



算法二:循环换位算法(平移法)

主要思想:如果k左边的元素个数少于右边的元素个数,则向前循环换位。否则,向后循环换位。

代码如下:

#include <stdio.h>

int temp;
//向前循环换位 
void forward(int a[], int n, int k) {
	int i, j;
	
	for(i = 0; i < k; i++) {
		temp = a[0];
		for(j = 1; j < n; j++) {
			a[j-1] = a[j];
		}
		a[n-1] = temp;
	}
}

//向后循环换位 
void backward(int a[], int n, int k) {
	int i, j;
	
	for(i = k; i < n; i++) {
		temp = a[n-1];
		for(j = n-1; j > 0; j--) {
			a[j] = a[j-1];
		}
		a[0] = temp;
	}
}

//选择移动较少的数组块进行循环
void move(int a[], int n, int k) {
	if(k > n-k) backward(a, n, k);
	else forward(a, n, k);
} 

int main() {
	int i, n, k;
	
    scanf("%d", &n);	//输入数组长度 
	int a[n];
    for(i = 0; i < n; i++) {
    	scanf("%d", &a[i]);		//输入数组元素 
    }
	scanf("%d", &k);	//输入截断位置
	
	move(a, n, k);
	
	printf("\n");
	for(i = 0; i < n; i++) {
    	printf("%d ", a[i]);
    }
	
    return 0;
}

在最坏的情况下,算法所需的元素移动次数为min{k, n-k}×(n+1)。算法进用到一个辅助空间temp。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值