public class Permutation {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
permute(arr, 0, arr.length - 1);
}
public static void permute(int[] arr, int left, int right) {
if (left == right) {
printArray(arr);
} else {
for (int i = left; i <= right; i++) {
swap(arr, left, i);
permute(arr, left + 1, right);
swap(arr, left, i); // 恢复数组状态,进行下一次交换
}
}
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void printArray(int[] arr) {
for (int num : arr) {
System.out.print(num + " ");
}
System.out.println();
}
}
解释一下原理
在上述代码中,permute
方法是递归函数,它接收一个数组 arr
,以及左边界 left
和右边界 right
。初始调用时,left
设为 0,right
设为数组长度减 1。
递归过程中,首先判断 left
是否等于 right
,如果相等,则表示已经完成了一种排列,将数组打印出来。
如果 left
不等于 right
,则进行循环遍历,将 arr[left]
与从 left
到 right
的每个元素进行交换,并递归调用 permute
函数。
在每次递归调用后,需要恢复数组的状态,以便进行下一次交换。
例如设数组arr为{1,2,3}也就是对123进行全排列
假设输入数组为 [1, 2, 3]
,初始调用 permute(arr, 0, arr.length - 1)
。
-
第一次递归调用:
left = 0
,right = 2
,不满足left == right
,进入循环。i = 0
,进行交换swap(arr, 0, 0)
,数组变为[1, 2, 3]
。- 递归调用
permute(arr, 1, 2)
。
-
第二次递归调用:
left = 1
,right = 2
,不满足left == right
,进入循环。i = 1
,进行交换swap(arr, 1, 1)
,数组仍然是[1, 2, 3]
。- 递归调用
permute(arr, 2, 2)
。
-
第三次递归调用:
left = 2
,right = 2
,满足left == right
,执行打印操作printArray(arr)
,输出[1, 2, 3]
。
-
返回到第二次递归调用:
- 继续循环,
i = 2
,进行交换swap(arr, 1, 2)
,数组变为[1, 3, 2]
。 - 递归调用
permute(arr, 2, 2)
。
- 继续循环,
-
第四次递归调用:
left = 2
,right = 2
,满足left == right
,执行打印操作printArray(arr)
,输出[1, 3, 2]
。
-
返回到第二次递归调用:
- 继续循环,
i = 2
,进行交换swap(arr, 1, 2)
,恢复数组为[1, 2, 3]
。 - 继续循环,
i = 2
,进行交换swap(arr, 1, 2)
,数组仍然是[1, 2, 3]
。
- 继续循环,
-
返回到第一次递归调用:
- 继续循环,
i = 1
,进行交换swap(arr, 0, 1)
,数组变为[2, 1, 3]
。 - 递归调用
permute(arr, 1, 2)
。
- 继续循环,
-
第五次递归调用:
left = 1
,right = 2
,不满足left == right
,进入循环。i = 1
,进行交换swap(arr, 1, 1)
,数组仍然是[2, 1, 3]
。- 递归调用
permute(arr, 2, 2)
。
-
第六次递归调用:
left = 2
,right = 2
,满足left == right
,执行打印操作printArray(arr)
,输出[2, 1, 3]
。
-
返回到第五次递归调用:
- 继续循环,
i = 2
,进行交换swap(arr, 1, 2)
,数组变为[2, 3, 1]
。 - 递归调用
permute(arr, 2, 2)
。
- 继续循环,
-
第七次递归调用:
left = 2
,right = 2
,满足left == right
,执行打印操作printArray(arr)
,输出[2, 3, 1]
。
-
返回到第五次递归调用:
- 继续循环,
i = 2
,进行交换swap(arr, 1, 2)
,恢复数组为[2, 1, 3]
。
- 继续循环,
-
返回到第一次递归调用:
- 继续循环,i = 2
,进行交换swap(arr, 0, 2)
,数组变为[3, 2, 1]
。
- 递归调用permute(arr, 1, 2)
。 -
第八次递归调用:
left = 1
,right = 2
,不满足left == right
,进入循环。i = 1
,进行交换swap(arr, 1, 1)
,数组仍然是[3, 2, 1]
。- 递归调用
permute(arr, 2, 2)
。
-
第九次递归调用:
left = 2
,right = 2
,满足left == right
,执行打印操作printArray(arr)
,输出[3, 2, 1]
。
-
返回到第八次递归调用:
- 继续循环,
i = 2
,进行交换swap(arr, 1, 2)
,数组变为[3, 1, 2]
。 - 递归调用
permute(arr, 2, 2)
。
- 继续循环,
-
第十次递归调用:
left = 2
,right = 2
,满足left == right
,执行打印操作printArray(arr)
,输出[3, 1, 2]
。
-
返回到第八次递归调用:
- 继续循环,
i = 2
,进行交换swap(arr, 1, 2)
,恢复数组为[3, 2, 1]
。
- 继续循环,
-
返回到第一次递归调用:
- 继续循环,
i = 2
,进行交换swap(arr, 0, 2)
,恢复数组为[1, 2, 3]
。
- 继续循环,
最终,该递归算法会生成并打印出数组 [1, 2, 3]
的所有全排列。