一、题目
输入一个字符串,打印出该字符串中字符的所有排列。你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = "abc" 输出:["abc","acb","bac","bca","cab","cba"]
限制:
1 <= s 的长度 <= 8
二、思路
通过递归+回溯的角度:
1、将字符串转为字符数组
2、将字符数组排序
3、调用dfs()函数,在dfs()中需要剪枝
去重(剪枝):通过相邻元素来判断是否重复;若同一层相邻元素相同则需要剪枝;
三、代码
import java.util.Arrays; class Solution { List<Character> path; List<String> res; boolean[] visited; public String[] permutation(String s) { this.path = new LinkedList<>(); this.res = new LinkedList<>(); this.visited = new boolean[s.length()]; char[] arr = s.toCharArray(); Arrays.sort(arr); dfs(arr,0); String[] strings = new String[res.size()]; System.out.println("res:"+res); for (int i = 0; i < res.size(); i++) { strings[i] = res.get(i); } return strings; } /** * 对字符数组进行全排列 * @param arr * @param k 访问的第k个元素 * */ void dfs(char[] arr,int k){ // 说明已经找到其中一条路劲了 if(arr.length == k){ res.add(listToString(path)); return; } // 进行n叉数搜索 for (int i = 0; i <arr.length; i++) { // 剪枝操作 if(i>0 && arr[i] == arr[i-1] && visited[i-1] == false){ continue; } // 判断当前结点是否访问 if(visited[i] == false){ // 没有访问过就递归访问、并修改已经访问过了 visited[i] = true; path.add(arr[i]); dfs(arr,k+1); // 回溯到上一层 path.remove(path.size()-1); visited[i] = false; } } } /** * List转为String * @param path * @return */ String listToString(List<Character> path){ StringBuilder sb = new StringBuilder(); for (int i = 0; i < path.size(); i++) { sb.append(path.get(i)); } return sb.toString(); } }
四、运行结果