思路:在深搜的过程中不断加入子集合,并且同层次(同一层for)的搜索里面去掉重复元素
class Solution {
private List<List<Integer>> res;
public List<List<Integer>> subsetsWithDup(int[] nums) {
res = new ArrayList<>();
List<Integer> ans = new ArrayList<>();
res.add(new ArrayList<>());
Arrays.sort(nums);
dfs(nums,ans,0);
return res;
}
public void dfs(int[] nums,List<Integer> ans,int it){
if(it == nums.length){
return;
}
int last = -11;
for(int i=it;i<nums.length;i++){
if(nums[i]==last){
continue;
}
ans.add(nums[i]);
res.add(new ArrayList<>(ans));
dfs(nums,ans,i+1);
ans.remove(ans.size()-1);
last = nums[i];
}
}
}
思路:大体和之前一样,但是由于不可以自己排序,所以需要用set去重不能用last
class Solution {
private List<List<Integer>> res;
public List<List<Integer>> findSubsequences(int[] nums) {
res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
dfs(nums,path,0);
return res;
}
public void dfs(int[] nums,List<Integer> path,int it){
if(it == nums.length){
return ;
}
Set<Integer> iset = new HashSet<>();
for(int i=it;i<nums.length;i++){
if(iset.contains(nums[i])||(path.size()>0&&nums[i]<path.get(path.size()-1))) continue;
path.add(nums[i]);
if(path.size()>=2) res.add(new ArrayList<>(path));
dfs(nums,path,i+1);
path.remove(path.size()-1);
iset.add(nums[i]);
}
}
}
思路:dfs,用set去维护不重复,没有顺序,每次for都从0开始,已经存在的元素跳过
class Solution {
List<List<Integer>> res;
public List<List<Integer>> permute(int[] nums) {
res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
Set<Integer> iset = new HashSet<>();
dfs(nums,path,iset);
return res;
}
public void dfs(int[] nums, List<Integer> path,Set<Integer> iset){
if(path.size()==nums.length){
res.add(new ArrayList<>(path));
return ;
}
for(int i=0;i<nums.length;i++){
if(iset.contains(nums[i]))continue;
iset.add(nums[i]);
path.add(nums[i]);
dfs(nums,path,iset);
iset.remove(nums[i]);
path.remove(path.size()-1);
}
}
}
思路:因为可能存在重复元素,set维护元素下标,同一层for再用一个set维护不出现重复的排列。
存在问题:执行速度慢,看了一下题解,不用set,用数组标记,同层用排序之后相邻去比较
class Solution {
List<List<Integer>> res;
public List<List<Integer>> permuteUnique(int[] nums) {
res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
Set<Integer> iset = new HashSet<>();
dfs(nums,path,iset);
return res;
}
public void dfs(int[] nums, List<Integer> path,Set<Integer> iset){
if(path.size()==nums.length){
res.add(new ArrayList<>(path));
return ;
}
Set<Integer> forset = new HashSet<>();
for(int i=0;i<nums.length;i++){
if(iset.contains(i)||forset.contains(nums[i])){
forset.add(nums[i]);
continue;
}
iset.add(i);
path.add(nums[i]);
dfs(nums,path,iset);
iset.remove(i);
path.remove(path.size()-1);
}
}
}
// 官方题解
class Solution {
boolean[] vis;
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
List<Integer> perm = new ArrayList<Integer>();
vis = new boolean[nums.length];
Arrays.sort(nums);
backtrack(nums, ans, 0, perm);
return ans;
}
public void backtrack(int[] nums, List<List<Integer>> ans, int idx, List<Integer> perm) {
if (idx == nums.length) {
ans.add(new ArrayList<Integer>(perm));
return;
}
for (int i = 0; i < nums.length; ++i) {
if (vis[i] || (i > 0 && nums[i] == nums[i - 1] && !vis[i - 1])) {
continue;
}
perm.add(nums[i]);
vis[i] = true;
backtrack(nums, ans, idx + 1, perm);
vis[i] = false;
perm.remove(idx);
}
}
}
思路:欧拉回路。使用map存两城市间的路径,一直选择最小的,虽然不一定是完整通路,但是一定是路径的一部分,所以可以先选择,如果走不完整说明是末尾那段,先写进去;然后再从剩下的路径里面找最小,继续走
class Solution {
private List<String> res = new ArrayList<>();
private Map<String,PriorityQueue<String>> map = new HashMap<>();
public List<String> findItinerary(List<List<String>> tickets) {
for(List<String> ticket:tickets){
String start = ticket.get(0);
String dst = ticket.get(1);
if(!map.containsKey(start)){
map.put(start,new PriorityQueue<String>());
}
map.get(start).offer(dst);
}
dfs("JFK");
Collections.reverse(res);
return res;
}
public void dfs(String start){
while(map.containsKey(start)&&map.get(start).size()>0){
dfs(map.get(start).poll());
}
res.add(start);
}
}