您的位置:首页 > 其它

全排列的另一种实现方法:旋转法

2008-08-22 15:47 429 查看
基本思路如下(以1234为例):
既然说是旋转法,那么它递归的就是旋转
旋转的规则如下:全部左移一位,但最左的移到最右
1234 -> 2341 -> 3412 -> 4123,4位的旋转完成了吧

递归,简单的思路就是从大变小,4位的旋转完成了,就是3位的旋转了,大概过程如下表格

四位的旋转第一位不动

后三位的旋转
前两位不动

后二位的旋转
一位直接返回最终的结果
123423434 12341234
  43 12431243
 42323 14231423
  32 14321432
 34242 13421342
  24 13241324
思路清晰了吧

下方即是代码

import java.util.ArrayList;
import java.util.List;

/**
*
* 要点1:递归 + 旋转
* 要点2:n长度的数组,经过n次旋转,会变成原来的数组
*
* @author Daniel You
* @since 2008-8-22
*/
public class Permutation {
// 要排列的数组大小
private int size;

// 要排列的数组
private int[] array;

// 结果集合
private List<int[]> list = new ArrayList<int[]>();

// 构造方法,未做异常处理
// TODO
public Permutation(int[] array) {
this.array = array;
this.size = array.length;
}

// 开始计算的入口点
public void begin() {
this.permutation(size);
}

// 获得结果
public List<int[]> result() {
return list;
}

/**
*
* 这个就是该排列重点,递归
*
* @param newSize
*/
private void permutation(int newSize) {
if (newSize == 1) {
// 如果最后一位了,直接加到结果集了
add();
return;
}

for (int j = 0; j < newSize; j++) {
permutation(newSize - 1);
rotate(newSize);
}
}

// 添加到结果集合
private void add() {
int[] temp = new int[size];
System.arraycopy(array, 0, temp, 0, size);
list.add(temp);
}

/**
* 重点之二:旋转
* @param newSize
*/
private void rotate(int newSize) {
int j;
int position = size - newSize;
int temp = array[position];
for (j = position + 1; j < size; j++) {
array[j - 1] = array[j];
}
array[j - 1] = temp;
}

public static void main(String[] args) {
int[] is = { 1, 2, 3, 4 };
Permutation p = new Permutation(is);
p.begin();
List<int[]> result = p.result();
for(int[] i : result){
p(i);
}
}

// 测试方法,打印一个数据
private static void p(int[] i) {
System.out.printf("%d%d%d%d/n", i[0], i[1], i[2], i[3]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: