对换和循环移位是一回事

----本文只是个人一点拙见,高手请忽略此文。

今天在看《编程之美》,里面有道很经典的题目--数组循环移位。之所以说它经典,是因为它多次出现各大IT公司的笔试、面试题上,而且这道题还曾经入选计算机考研的算法题。相信很多人都知道解法了,而且不只一种解法。书上也给出了三种解法,分别用了移位、考虑周全的移位和对换。看了书中的解法,除了了解题目本身的解法外,突然恍然大悟,原来对换和循环移位就是一回事啊!为什么这么说呢?让我们来看个最经典的交换算法,以交换一位为例:

让我们来看个最经典的交换算法,以交换一位为例:

static void swap(int a, int b) {
	int temp = a;
	a = b;
	b = temp;
}
这算法相信学过编程的人都知道,简单得不能再简单了。它使用了一个变量做为临时变量,临时存储数据。如下图所示,箭头表示交换过程。

可是我们可以换一种角度来看,它的意思的是说,在一个有两个数的数组{a,b}中,a向右循环移位,a代替了b原来所在的位置,b则移到了a 的位置,从而变成了{b,a}。是吧,也就是说两个数的交换和两个数的循环移位一位等效。如此推理,交换一个长度为n的数组,就是对一个长度为n的数组循环移位n/2位。

知道了这个概念有什么用呢,这有助于理解插入算法。所谓插入算法的核心函数是在第i位插入一个数,并且让这个数组从这个位置开始右移。这个函数我们可以理解为数组在末位插入了这个数,然后这个数组从第i位开始到数组的末端进行循环右移一位,这样新插入的数因为右移就会移动第i个位置去。代码如下

/**
	 * 右移
	 * 
	 * @param arrs
	 *            数组
	 * @param i
	 *            起始位置
	 * @param j
	 *            结束位置
	 */
	static void shift(int[] arrs, int i, int j) {
		int temp = arrs[j];
		for (int k = j - 1; k >= i; k--)
			arrs[k + 1] = arrs[k];
		arrs[i] = temp;
	}
	/**
	 * 插入
	 * @param arrs 数组
	 * @param i 插入的位置
	 * @param k 新插入的数值
	 */
	static void insert(int[] arrs,int i,int k){
		int[] newArrs = Arrays.copyOf(arrs, arrs.length*2);
		newArrs[arrs.length] = k; //把这个数放在末尾
		shift(newArrs, i, arrs.length);
	}

很多人可能对shift方法记不住,记不清k从多少开始,或者到底是arrs[k]赋值给arrs[k+1]还是arrs[k+1]赋值给arrs[k]。既然交换和循环移位是一回事,那么我们可以以交换来理解。也就是说,他们的过程可以这样理解:数组的末位a[j]和a[j-1]交换,然后a[j-1]和a[j-2]交换,...,直到a[i+1]和a[i]交换。这样就把a[j]移到了a[i]原来的位置上。

如果把每一步写出来就是这样:

int temp = arrs[j];
arrs[j] = arrs[j-1];
arrs[j-1] = temp;
temp = arrs[j-1];
arrs[j-1] = arrs[j-2];
arrs[j-2] = temp;
...
temp = arrs[i+1];
arrs[i+1] = arrs[i];
arrs[i] = temp;

约去无效的代码:

int temp = arrs[j];
arrs[j] = arrs[j-1];
arrs[j-1] = arrs[j-2];
...
arrs[i+1] = arrs[i];
arrs[i] = temp;

用循环写的话就是上面的方法。因此,如果shift方法记不住的话,可以多想想交换,代码就能起想来了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值