回溯法:全排列

102 篇文章 0 订阅
70 篇文章 0 订阅

全排列

递归实现:把元素换到数组首位,剩下的部分做全排列

def constraint():
    return True

def bound():
    return True

def perm_backtracking(depth,lst):
    size = len(lst)
    
    if depth == size:
        print(lst)
    else:
        for i in range(depth,size):          
            if constraint() and bound():
                lst[depth],lst[i] = lst[i],lst[depth]
                perm_backtracking(depth+1,lst)
                lst[depth],lst[i] = lst[i],lst[depth]

迭代实现,可以参考完全n叉树,这个应该是一个通用的迭代的处理方法,在这里:只要不在同一列就行了

def perm_backtracking_iteration(depth,lst):
    size = len(lst)
    Selected =[-1]*size
    # 排列数,列号不能重复
    def place(k):
        for i in range(k):
            if Selected[i] == Selected[k]:
                return False
        return True
    

    
    while depth >=0:
        
        Selected[depth] +=1
        # 直到选择一个可行的解
        while Selected[depth]<size and not place(depth):
            Selected[depth] +=1
       # 这个就是回溯条件,子集树不为空
        if Selected[depth] <= size-1:
            if depth == size-1:
#                print Selected
					# 解码结果,Selected里面对应的是选择了哪一个数
                for i in Selected:
                    print lst[i],
                print ""
            else:
            # 到达下一层时,初始化下一层的子树的范围
                depth +=1
                Selected[depth] =-1
        # 回溯,还是从上一层的未选的的地方走
        else:
            depth -=1


        
      
A = ['A','B','C','D']
perm_backtracking(0,A)

['A', 'B', 'C', 'D']
['A', 'B', 'D', 'C']
['A', 'C', 'B', 'D']
['A', 'C', 'D', 'B']
['A', 'D', 'C', 'B']
['A', 'D', 'B', 'C']
['B', 'A', 'C', 'D']
['B', 'A', 'D', 'C']
['B', 'C', 'A', 'D']
['B', 'C', 'D', 'A']
['B', 'D', 'C', 'A']
['B', 'D', 'A', 'C']
['C', 'B', 'A', 'D']
['C', 'B', 'D', 'A']
['C', 'A', 'B', 'D']
['C', 'A', 'D', 'B']
['C', 'D', 'A', 'B']
['C', 'D', 'B', 'A']
['D', 'B', 'C', 'A']
['D', 'B', 'A', 'C']
['D', 'C', 'B', 'A']
['D', 'C', 'A', 'B']
['D', 'A', 'C', 'B']
['D', 'A', 'B', 'C']

还可以基于排列树的迭代方式:

def perm_backtracking_iteration2(depth,lst):
    size = len(lst)
    Selected =[i for i in range(size)]
    change = [-1]*size   
    count = 0
    
    while depth >=0:
        # range(Selected[depth],size)记录的是剩余的次数,这里面还不能表现到底是那几次?估计还可以改进
        if Selected[depth] < size:
            
            for i in range(Selected[depth],size):
                 # 交换且记录交换
                lst[depth],lst[i] = lst[i],lst[depth]
                change[depth] = i
                
                Selected[depth] +=1
                
                if depth == size-1:
                    count +=1
                    print lst
                    print count

                else:                    
                    depth +=1
                    Selected[depth] = depth
                    break
        else:
         # 子集树为空了,回溯到上一层,在最底部是没有交换动作的,因为change[depth]就是本身,
		#   所以需要先-1,再交换,可以自己先调试一遍
            depth -=1  
            lst[depth],lst[change[depth]] = lst[change[depth]],lst[depth]
            change[depth] = -1




A = ['A','B','C','D']
#perm_backtracking(0,A)
perm_backtracking_iteration2(0,A)


['A', 'B', 'C', 'D']
1
['A', 'B', 'D', 'C']
2
['A', 'C', 'B', 'D']
3
['A', 'C', 'D', 'B']
4
['A', 'D', 'C', 'B']
5
['A', 'D', 'B', 'C']
6
['B', 'A', 'C', 'D']
7
['B', 'A', 'D', 'C']
8
['B', 'C', 'A', 'D']
9
['B', 'C', 'D', 'A']
10
['B', 'D', 'C', 'A']
11
['B', 'D', 'A', 'C']
12
['C', 'B', 'A', 'D']
13
['C', 'B', 'D', 'A']
14
['C', 'A', 'B', 'D']
15
['C', 'A', 'D', 'B']
16
['C', 'D', 'A', 'B']
17
['C', 'D', 'B', 'A']
18
['D', 'B', 'C', 'A']
19
['D', 'B', 'A', 'C']
20
['D', 'C', 'B', 'A']
21
['D', 'C', 'A', 'B']
22
['D', 'A', 'C', 'B']
23
['D', 'A', 'B', 'C']
24
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您讲解一下 Java 如何使用回溯法解决全排列问题。 回溯法是一种暴力枚举的搜索方法,通常用于在所有可能的情况中寻找解决方案。在全排列问题中,我们需要找出一组的所有排列,即所有的不同顺序。下面是使用回溯法解决全排列问题的 Java 代码: ```java public class Permutations { public static void main(String[] args) { int[] nums = {1, 2, 3}; List<List<Integer>> result = permute(nums); System.out.println(result); } public static List<List<Integer>> permute(int[] nums) { List<List<Integer>> result = new ArrayList<>(); List<Integer> list = new ArrayList<>(); boolean[] used = new boolean[nums.length]; backtrack(result, list, nums, used); return result; } public static void backtrack(List<List<Integer>> result, List<Integer> list, int[] nums, boolean[] used) { if (list.size() == nums.length) { result.add(new ArrayList<>(list)); } else { for (int i = 0; i < nums.length; i++) { if (used[i]) continue; list.add(nums[i]); used[i] = true; backtrack(result, list, nums, used); used[i] = false; list.remove(list.size() - 1); } } } } ``` 在这个代码中,我们定义了一个 `permute` 方法,它接收一个整组 `nums`,并返回所有可能的排列。在方法中,我们定义了一个 `result` 变量保存所有排列的结果,一个 `list` 变量表示当前排列,以及一个 `used` 组表示哪些字已经被使用过了。 我们使用 `backtrack` 方法来递归地搜索所有可能的排列。如果当前排列的长度等于组的长度,说明找到了一个排列,将其加入到 `result` 中。否则,我们遍历组中所有未被使用过的字,将其添加到当前排列中,并将其标记为已使用。接着,我们递归搜索下一个字。搜索完成后,我们需要将当前字从排列中移除,并将其标记为未使用,以便进行下一轮搜索。 这就是使用回溯法解决全排列问题的 Java 代码。希望对您有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值