题目如下:用1,2,2,3,4,5这6个数字,用Java写一个main函数,打印出所有不同的排列,如:123254,522134等,要求:“3”与“5”不能相邻,“4”不能排在第3位。(看完题目先不要急着看答案,自己尝试做一下,或者你的做法更好^_^)
解题方案是把相邻问题抽象成一个2维数组,用0与1组成,如[0,1]或者[1,0]就表示0与1相邻的时候,如下图:
0 1 1 1 1 1
1 0 1 1 1 1
1 1 0 1 1 1
1 1 1 0 1 1
1 1 1 1 0 1
1 1 1 1 1 0
解释:0表示不能相邻,1表示可以相邻(当然你掉转也可以) [1,1],[2,2]...[6,6]这些当然为0了,自己与自己又怎可能相邻=。=
另外还需要设计一个boolean数组,标识第几个元素可用(即还没被用来排列)
这一种的解题思路来源于图遍历的深度遍历(搜索),关于深度遍历的详细可以参考
http://zhidao.baidu.com/question/17057725.html
参考代码如下:
import java.util.*;
public class DepthSearch {
//要排列的字符串数组
private String[] b = {"1","2","2","3","4","5"};
int n = b.length;
private String result ="";
//判断数组中哪个元素还可用与排列的标志位
private boolean[] visit = new boolean[n];
//用于标识相邻元素相通与否的2维数组
private int[][] a = new int[n][n];
//用于存放的排列结果的集合
private Set<String> set = new TreeSet<String>();
//计算有多少个元素被加入到TreeSet里面
private int count;
//执行main函数
public static void main(String[] args) {
new DepthSearch().start();
}
private void start(){
//初始化2维数组,1表示相连,0表示不通
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(i==j){
a[i][j]=0;
}
else{
a[i][j]=1;
}
}
}
//加入不能相邻元素的限制条件,把2维数组对应该元素设置为0,这里是3与5不能相邻(对应第4个元素和第6个元素)
a[3][5]=0;
a[5][3]=0;
//表示以第1到第6个元素为第1位的情况进行排列(循环6次)
for(int i=0;i<n;i++){
this.sort(i);
}
System.out.println("set中元素为"+set.size()+"个");
System.out.println("TreeSet所过滤掉的元素共有:"+(count-set.size())+"个");
System.out.println("所有排列如下:");
for(String s:set){
System.out.print(s+" , ");
}
}
private void sort(int startIndex){
//被拿了出来的元素设置标志为true,表示不可用,false为可用
result = result + b[startIndex];
visit[startIndex] = true;
//当长度等于6的时候,即满足一种排列组合,加到TreeSet里面
if(result.length()==6){
//用if判断:4不能放在第3位
if(result.indexOf("4")!=2){
set.add(result);
count++;
}
}
//2维数组a[][]表示当前元素与相邻元素,若为1,即表示可以相邻,false表示下一个元素可用
for(int i=0;i<n;i++){
if(a[startIndex][i]==1 && visit[i]==false){
sort(i);
}
}
//若不符合跳出循环,即result减去一个再进行排列,直到跳出最外循环为止
result = result.substring(0,result.length()-1);
visit[startIndex] = false;
}
}
有2个地方需要注意:
1)其实sort方法是6层for嵌套,当走到第6个for循环,所有条件都不满足的时候,就会先走最后两步
result = result.substring(0,result.length()-1);
visit[startIndex] = false; 减去一个字符并把那个字符设为可用,然后返回到第5层for循环,如果跑完也不满足要求就会再减一个返回第4层的for循环,以此类推。当把以第一个元素为第1位的所有排列组合计算出来并加到TreeSet里面之后,就会进行以第2个元素为第一位的所有排列组合的计算,一直到最后一位。
2)因为字符串“122345”出现两个2,所以排列会有重复,需要放到Set里面过滤一下,用HashSet也可以,而且更快,TreeSet打印出来的时候按从小到大的顺序好看一点。
分享到:
相关推荐
C#深度优先遍历实现全排列 C#深度优先遍历实现全排列是...在实际应用中,C#深度优先遍历实现全排列可以用来解决许多问题,例如,排列问题、组合问题等。同时,它也可以用来解决一些实际问题,例如,排列人员、物品等。
在Python中,可以使用内置的`itertools`模块来简化全排列问题的解决,`itertools.permutations()`函数可以直接生成一个可迭代对象,包含了输入序列的所有排列。 总结起来,"python练习fibonacci全排列"这个主题涵盖...
在全排列问题中,我们可以用回溯法配合DFS来实现。基本步骤如下: - 从序列的第一个元素开始,将其标记为已使用。 - 对序列中剩余的元素,依次与第一个元素进行排列,并递归地进行全排列。 - 当所有元素都尝试过...
**DFS(Depth-First Search,深度优先搜索)**作为一种经典的图遍历算法,广泛应用于各种问题中,包括但不限于迷宫问题、迷宫寻路、连通性检测等。 #### 递归DFS深度优先遍历的核心原理 在深入探讨具体的实例之前...
本篇将详细介绍两种常用的Java方法来解决全排列问题,并探讨相关知识点。 ### 1. 递归法 递归法是一种自上而下解决问题的方法,它通过调用自身来解决子问题。在全排列问题中,我们可以从最简单的情况(只有一个...
在编程领域,全排列是一个经典的算法问题,它涉及到数组或字符串的所有可能的顺序组合。当给定一个包含N个不同元素的集合时,全排列就是要列出所有可能的N!(N的阶乘)种排列方式。在这个场景中,我们将探讨如何使用...
在本例中,我们将深入探讨如何使用深度优先搜索(DFS)解决全排列问题。 深度优先搜索是一种用于遍历或搜索树或图的算法。在全排列问题中,我们可以将每一步选择一个未使用的数字看作是一个节点,而所有可能的选择...
全排列是一种经典的算法问题,它涉及在给定的有限序列中找出所有可能的元素排列方式。在本例中,我们关注的是非递归算法来实现全排列,这通常使用回溯法或者迭代的方式来完成,特别是在有新元素动态加入时,需要能够...
全排列算法是计算机科学中的一种经典算法,主要应用于解决如何生成一个给定集合的所有可能排列的问题。在给定的题目中,作者通过一个简单的递归方法实现了全排列的计算。以下是对该算法的详细解析: 首先,我们来看...
递归是最直观的解决全排列问题的方法。我们首先选择第一个位置的元素,然后对剩下的元素进行全排列。这个过程可以表示为递归函数,如下: - 基本情况:当需要排列的元素只有一个时,只有一个排列(自身)。 - ...
在C++中实现全排列可以使用回溯法,这是一种在尝试解决问题时,当发现当前选择无法导致有效解时,会退回一步并尝试其他选择的方法。以下是一个简单的C++代码实现全排列的示例: ```cpp #include #include using ...
在描述中提到了一个博客链接,虽然具体内容没有给出,但通常博主会详细解释如何用非递归的方式解决全排列问题。非递归算法通常采用迭代或回溯的方式来完成,这种方式相对于递归可能会更节省内存,因为递归深度过大...
通过上述两种方法,我们可以有效地解决全排列问题,理解回溯法和DFS的思想对于解决类似问题具有重要的指导意义。在实际编程中,根据问题的特点选择合适的方法,能够提高算法的效率和代码的可读性。
这种算法通常使用栈或递归来实现,递归版本易于理解,而迭代版本则更高效,避免了深度递归可能导致的堆栈溢出问题。 在C#中,我们可以创建一个递归函数来实现全排列。以下是一个简单的C#代码示例: ```csharp ...
实现全排列的方法有很多,本文主要介绍使用PHP语言实现基于图的深度优先遍历(DFS,Depth-First Search)算法来生成1到n的全排列。 深度优先遍历是一种用于遍历或搜索树或图的算法。这里所指的图是抽象意义上的,而...
总结来说,生成字符串全排列的问题可以通过回溯法有效地解决。这种方法的关键在于递归地尝试所有可能的选择,并在无法继续时及时回溯,避免无效的工作。回溯法不仅可以应用于字符串排列,还可以解决许多其他组合优化...
全排列问题可以通过递归来优雅地解决。具体策略如下: 1. **基本情况**:当数组中只有一个元素时,其全排列就是该元素本身,这是一次简单的返回。 2. **递归步骤**:对于长度为n的数组,我们可以选择数组中的任一...
解决这个问题的关键在于设计一个递归函数,它能够遍历所有可能的排列。以下是一个可能的解法: ```javascript function permute(nums) { let result = []; function backtrack(first = 0) { if (first === nums....
总结一下,本资源包主要涵盖了C++编程语言中的算法知识,特别是如何使用回溯法解决全排列问题。通过学习和实践这个题目的解法,开发者可以深化对C++编程的理解,提高解决实际问题的能力,同时为准备LeetCode等算法...