[Algorithm]九章五.DFS
来源:互联网 发布:朕是什么意思网络此意 编辑:程序博客网 时间:2024/06/05 00:43
17. Subsets: 点击打开链接
public class Solution { public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> result=new ArrayList<>(); if(nums==null || nums.length==0){ return result; } Arrays.sort(nums); helper(result,new ArrayList<>(),nums,0); return result; } private void helper(List<List<Integer>> result,List<Integer> list,int[] nums,int start){ result.add(new ArrayList<>(list)); for(int i=start;i<nums.length;i++){ list.add(nums[i]); helper(result,list,nums,i+1); list.remove(list.size()-1); } }}
18. Sebsets II: 点击打开链接
class Solution { /** * @param nums: A set of numbers. * @return: A list of lists. All valid subsets. */ public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] nums) { ArrayList<ArrayList<Integer>> results=new ArrayList<>(); ArrayList<Integer> list=new ArrayList<>(); Arrays.sort(nums); if(nums==null){ return results; } if(nums.length==0){ results.add(list); return results; } helper(nums,0,results,list); return results; } private void helper(int[] nums, int startIndex,ArrayList<ArrayList<Integer>> results,ArrayList<Integer> list){ results.add(new ArrayList<>(list)); for(int i=startIndex;i<nums.length;i++){ //此处if语句也说明了之前数组排序的重要性 if(i!=0 && nums[i]==nums[i-1] && i>startIndex){ //首先要防止数组角标越界:i!=0 continue; //比较前后两个数是针对后面再一次出现同一个数的情况 } //如果前一个同样的数还没有放进去过,就不能放后一个同样的数; list.add(nums[i]); helper(nums,i+1,results,list); list.remove(list.size()-1); } }}
135.Combination Sum: 点击打开链接
1. [2]
-> [2,2]
-> [2,2,2]
-> [2,2,2,2], 判断和大于target,后面的[2,2,2,3],[2,2,2,6],[2,2,2,7]都不用再判断,break。
2. 回到i++,也就是外一圈的helper,[2,2,3]里判断,此时正好等于target,return。
判断[2,2,6],和大于target,后面的整个[2,2,7]都垮掉。
3. 再回到外一圈的helper,[2,3]里判断,以此类推。
4. 直到以[2]开头的都判断完,回到最外层helper,再判断以[3]开头的。
注意:当一个元素可以用很多次,结果又不能有重复list,就要取出原数组的重复元素
public class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> result=new ArrayList<>(); List<Integer> list=new ArrayList<>(); if(candidates==null || candidates.length==0){ return result; } int[] nums=removeDuplicates(candidates); helper(nums,target,0,0,result,list); return result; } //递归的定义:寻找所有以list开头的满足条件的组合,放到result里 private void helper(int[] nums,int target,int startIndex,int sum,List<List<Integer>> result,List<Integer> list){ if(sum==target){ //递归的出口 result.add(new ArrayList<Integer>(list)); return; } for(int i=startIndex;i<nums.length;i++){ //这里的for循环执行两种功能,如果可以继续加值,里层的helper用的 if(sum+nums[i]>target){ //还有就是remove最后一个元素后,同一层的下一个组合用的 break; //一旦break,跳出整体for循环,并不是本层for循环 } list.add(nums[i]); helper(nums,target,i,sum+nums[i],result,list); //i的取值也很讲究:只要是元素可以重复使用,下次取的时候还是位置i list.remove(list.size()-1); } } private int[] removeDuplicates(int[] candidates){ //去重是必要的,不然result里可能会有重复小list Arrays.sort(candidates); ArrayList<Integer> list=new ArrayList<>(); for(int i=0;i<candidates.length;i++){ if(!list.contains(candidates[i])){ list.add(candidates[i]); } } int[] nums=new int[list.size()]; for(int i=0;i<list.size();i++){ nums[i]=list.get(i); } return nums; }}
public class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> result=new ArrayList<>(); List<Integer> list=new ArrayList<>(); if(candidates==null || candidates.length==0){ return result; } int[] nums=removeDuplicates(candidates); helper(nums,target,0,0,result,list); return result; } private void helper(int[] nums,int target,int startIndex,int sum,List<List<Integer>> result,List<Integer> list){ if(sum==target){ result.add(new ArrayList<Integer>(list)); return; } for(int i=startIndex;i<nums.length;i++){ if(sum<target){ list.add(nums[i]); helper(nums,target,i,sum+nums[i],result,list); list.remove(list.size()-1); } } } private int[] removeDuplicates(int[] nums){ Arrays.sort(nums); int index=0; for(int i=0;i<nums.length;i++){ if(nums[i]!=nums[index]){ index++; nums[index]=nums[i]; } } int[] result=new int[index+1]; for(int i=0;i<result.length;i++){ result[i]=nums[i]; } return result; }}
153. Combination Sum II : 点击打开链接
public class Solution { public List<List<Integer>> combinationSum2(int[] candidates, int target) { List<List<Integer>> result=new ArrayList<>(); List<Integer> list=new ArrayList<>(); if(candidates==null || candidates.length==0){ return result; } Arrays.sort(candidates); helper(candidates,target,0,0,result,list); return result; } private void helper(int[] nums,int target,int startIndex,int sum,List<List<Integer>> result,List<Integer> list){ if(sum==target){ result.add(new ArrayList<Integer>(list)); return; } for(int i=startIndex;i<nums.length;i++){ if(sum<target){ if(i!=0 && nums[i]==nums[i-1] && i!=startIndex){ //因为i-1等于startIndex continue; //nums[i-1]没有被拿过,就不能拿nums[i] } list.add(nums[i]); helper(nums,target,i+1,sum+nums[i],result,list); list.remove(list.size()-1); } } } }
136. Palindrome Partitioning: 点击打开链接
public class Solution { /** * @param s: A string * @return: A list of lists of string */ public List<List<String>> partition(String s) { List<List<String>> result=new ArrayList<>(); List<String> list=new ArrayList<>(); if(s==null || s.length()==0){ return result; } helper(s,0,result,list); return result; } private void helper(String s,int startIndex,List<List<String>> result,List<String> list){ if(startIndex==s.length()){ result.add(new ArrayList<>(list)); return; } for(int i=startIndex;i<s.length();i++){ String sub=s.substring(startIndex,i+1); if(!isPalindrome(sub)){ continue; //并不是最大层for循环整体垮掉,只是终止本层for循环 } list.add(sub); helper(s,i+1,result,list); list.remove(list.size()-1); } } private boolean isPalindrome(String s){ for(int i=0, j=s.length()-1; i<j ; i++, j--){ if(s.charAt(i)!=s.charAt(j)){ return false; } } return true; }}
15. Permutations: 点击打开链接
public class Solution { public List<List<Integer>> permute(int[] nums) { //recursion方法一 List<List<Integer>> result=new ArrayList<>(); if(nums==null || nums.length==0){ return result; } int[] visited=new int[nums.length]; for(int i=0;i<nums.length;i++){ visited[i]=0; } helper(result,new ArrayList<>(),nums,visited); return result; } private void helper(List<List<Integer>> result,List<Integer> list,int[] nums,int[] visited){ if(list.size()==nums.length){ result.add(new ArrayList<>(list)); return; } for(int i=0;i<nums.length;i++){ if(visited[i]==1){ continue; } list.add(nums[i]); visited[i]=1; helper(result,list,nums,visited); list.remove(list.size()-1); visited[i]=0; } }}
class Solution { //recursion方法二 /** * @param nums: A list of integers. * @return: A list of permutations. */ public List<List<Integer>> permute(int[] nums) { List<List<Integer>> result=new ArrayList<>(); List<Integer> list=new ArrayList<>(); if(nums==null){ return result; } if(nums.length==0){ result.add(list); return result; } helper(result,list,nums); return result; } private void helper(List<List<Integer>> result, List<Integer> list, int[] nums){ if(list.size()==nums.length){ result.add(new ArrayList<>(list)); return; } for(int i=0;i<nums.length;i++){ if(list.contains(nums[i])){ continue; } list.add(nums[i]); helper(result,list,nums); list.remove(list.size()-1); } }}
16. Permuations II : 点击打开链接
class Solution { /** * @param nums: A list of integers. * @return: A list of permutations. */ public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> result=new ArrayList<>(); List<Integer> list=new ArrayList<>(); if(nums==null){ return result; } if(nums.length==0){ result.add(list); return result; } Arrays.sort(nums); int[] visited=new int[nums.length]; for(int i=0;i<visited.length;i++){ visited[i]=0; } helper(result,list,nums,visited); return result; } private void helper(List<List<Integer>> result, List<Integer> list, int[] nums, int[] visited){ if(list.size()==nums.length){ result.add(new ArrayList<>(list)); return; } for(int i=0;i<nums.length;i++){ if(visited[i]==1 || (i!=0 && nums[i]==nums[i-1] && visited[i-1]==0)){ continue; //如果有相同元素的情况下,如果前面的元素还没有使用的时候,就不能让后面这个元素使用 } //也就是轮到这个元素的时候,它已经被放进去了,或者它前面的元素还没有被放进去 list.add(nums[i]); visited[i]=1; helper(result,list,nums,visited); list.remove(list.size()-1); visited[i]=0; } }}
33. N-Queens: 点击打开链接
1.同的一行不能存在两个皇后,但是又正好是N个皇后又要放在N行上,这就意味着每一行都有且仅有一个皇后,于是我们可以按照这样的方式来枚举这道题目的所有方案:依次枚举每一行皇后的位置,在这个枚举过程中确保不会在每一列、每一条斜线上出现两个皇后,对于行里面的每一个元素,都要遍历一次这个元素对应的一整列。
2.以[1,3,0,2]的ArrayList为例,也就是arrayList.get(0)=1, arrayList.get(1)=3, arrayList.get(2)=0, arrayList.get(3)=2
。Q。。。。。QQ。。。。。Q。3.明确造成斜线攻击的条件:同一个斜线上的坐标之差相等,反方向上是同一个斜线上坐标之和相等。
class Solution { /** * Get all distinct N-Queen solutions * @param n: The number of queens * @return: All distinct solutions * For example, A string '...Q' shows a queen on forth position */ ArrayList<ArrayList<String>> solveNQueens(int n) { ArrayList<ArrayList<String>> result=new ArrayList<>(); ArrayList<Integer> cols=new ArrayList<>(); if(n<=0){ return result; } search(result,cols,n); return result; } private void search(ArrayList<ArrayList<String>> result, ArrayList<Integer> cols, int n){ if(cols.size()==n){ result.add(drawChessBoard(cols)); return; } for(int colIndex=0;colIndex<n;colIndex++){ if(!isValid(cols,colIndex)){ continue; } cols.add(colIndex); search(result,cols,n); cols.remove(cols.size()-1); } } private boolean isValid (ArrayList<Integer> cols,int column){ //判断有效落子位置 int row=cols.size(); for(int rowIndex=0;rowIndex<cols.size();rowIndex++){ //行里面的每一个元素,都要遍历一次这个元素对应的一整列 if(cols.get(rowIndex)==column){ //造成列攻击 return false; } if(rowIndex+cols.get(rowIndex)==row+column){ //造成斜线攻击 return false; } if(rowIndex-cols.get(rowIndex)==row-column){ //造成斜线攻击 return false; } } return true; } private ArrayList<String> drawChessBoard(ArrayList<Integer> cols) { //每一个solution画成棋盘 ArrayList<String> solution = new ArrayList<>(); for (int i = 0; i < cols.size(); i++) { StringBuilder sb = new StringBuilder(); for (int j = 0; j < cols.size(); j++) { if(j == cols.get(i)){ sb.append('Q'); }else{ sb.append('.'); } } solution.add(sb.toString()); } return solution; //最后以这样的形式表示棋盘[.Q.., ...Q, Q..., ..Q.], 以[1,3,0,2]为例 }}
34.N-Queens II : 点击打开链接
N-QueensII相对于I其实是更简单了,不让打印满足条件的棋盘,而是输出满足条件的棋盘个数。
class Solution { /** * Calculate the total number of distinct N-Queen solutions. * @param n: The number of queens. * @return: The total number of distinct solutions. */ public int sum; public int totalNQueens(int n) { sum=0; search(new ArrayList<Integer>(), n); return sum; } private void search(ArrayList<Integer> solution,int n){ //注意这边不用初始化sum=0; if(solution.size()==n){ sum++; return; } for(int colIndex=0; colIndex<n; colIndex++){ if(!isValid(solution,colIndex)){ continue; } solution.add(colIndex); search(solution,n); solution.remove(solution.size()-1); } } private boolean isValid(ArrayList<Integer> solution,int column){ int row=solution.size(); for(int rowIndex=0;rowIndex<solution.size();rowIndex++){ if(solution.get(rowIndex)==column){ return false; } if(rowIndex+solution.get(rowIndex)==row+column){ return false; } if(rowIndex-solution.get(rowIndex)==row-column){ return false; } } return true; }};
12.Min Stack:点击打开链接
public class MinStack { Stack<Integer> stack=new Stack<>(); Stack<Integer> minStack=new Stack<>(); public MinStack() { // do initialize if necessary } public void push(int number) { stack.push(number); if(minStack.isEmpty() || minStack.peek()>=number){ //如果栈是空的,可以直接放,如果栈里有就要比较与加入number的大小 minStack.push(number); //只有原来peek的比number的值大至少等于number,才可以加入number } //也就是说,如果要加入的一直比minStack.peek()的大,就一直不加入minStack里 } public int pop() { int x=stack.pop(); if(minStack.peek()==x){ //如果当初加入的时候加入的比minStack原有的大,则minStack不加入 minStack.pop(); //这时pop的时候minStack也不pop } return x; } public int min() { return minStack.peek(); }}
575.Expression Expand: 点击打开链接
public class Solution { /** * @param s an expression includes numbers, letters and brackets * @return a string */ public String expressionExpand(String s) { Stack<Object> stack=new Stack<>(); int num=0; for(char c : s.toCharArray()){ //c只有4种:数字, '[', ']'或者字符串 if(Character.isDigit(c)){ //如果是数字,就拿到数字 num=num*10+c-'0'; }else if(c=='['){ //如果是'[',就把数字入栈 stack.push(Integer.valueOf(num)); //数字入栈之后要归零,后面的数字还要在for循环里出现 num=0; }else if(c==']'){ //如果是']',就要拿出[]所包含的字符串,并让之前相应的数字出栈 String curString=popStack(stack); Integer count=(Integer)stack.pop(); for(int i=0;i<count;i++){ //有几个字符串,就以for循环的形式入栈几次 stack.push(curString); //解决了形如 3[abc]这样的问题 } }else{ //如果是字符串,就直接入栈 stack.push(String.valueOf(c)); } } return popStack(stack); //最后最大括号的整体也要当做字符串 } private String popStack(Stack<Object> stack){ //将stack里的字符串出栈,导入暂时栈temp,然后添加到sb里转化为String Stack<String> tempStack=new Stack<>(); String str=null; while(!stack.isEmpty() && stack.peek() instanceof String){ tempStack.push((String) stack.pop()); } StringBuilder sb=new StringBuilder(); while(!tempStack.isEmpty()){ sb.append(tempStack.pop()); } return sb.toString(); }}
433.Numbers of Islands: 点击打开链接
对于每一个
grid[i][j]点进行遍历
, 如果是小岛,即grid[i][j] == true
,则result+1,并对四个方向进行DFS查找(查找的时候要先判断有效点,也就是坐标加减后还在给定矩阵中的点),并将所有属于那坐岛屿的点标记为非岛屿。这样遍历过的地方全部会变成非岛屿,而岛屿的数量已被记录。(标记的意义在于:不会对同一块已经计数过的小岛反复计数)。
public class Solution { /** * @param grid a boolean 2D matrix * @return an integer */ public int numIslands(boolean[][] grid) { //写法一 if(grid==null || grid.length==0){ return 0; } int result=0; for(int i=0;i<grid.length;i++){ for(int j=0;j<grid[0].length;j++){ if(grid[i][j]==true){ result++; dfs(grid,i,j); } } } return result; } private void dfs(boolean[][] grid,int x,int y){ //找grid[i][j]四周为岛屿的点 int[] dx={0,0,-1,1}; //如果有就把它们标记为false,表示和grid[i][j]连接 int[] dy={-1,1,0,0}; if(isValid(grid,x,y) && grid[x][y]==true){ grid[x][y]=false; for(int k=0;k<4;k++){ dfs(grid,x+dx[k],y+dy[k]); } } } private boolean isValid(boolean[][] grid,int x,int y){ if(x<0 || x>=grid.length){ return false; } if(y<0 || y>=grid[0].length){ return false; } return true; }}
public class Solution { /** * @param grid a boolean 2D matrix * @return an integer */ public int numIslands(boolean[][] grid) { //写法二,思路是一样的 if(grid==null || grid.length==0){ return 0; } int result=0; for(int i=0;i<grid.length;i++){ for(int j=0;j<grid[0].length;j++){ if(grid[i][j]==true){ result++; dfs(grid,i,j); } } } return result; } private void dfs(boolean[][] grid, int i, int j){ if(i<0 || i>=grid.length || j<0 || j>=grid[0].length){ return; } if(grid[i][j]==true){ grid[i][j]=false; dfs(grid,i+1,j); dfs(grid,i-1,j); dfs(grid,i,j+1); dfs(grid,i,j-1); } }}
- [Algorithm]九章五.DFS
- Non-recursive Version of DFS Algorithm
- Algorithm
- Algorithm
- algorithm
- algorithm
- algorithm
- algorithm
- algorithm
- Algorithm
- Algorithm
- algorithm
- Algorithm
- Algorithm
- algorithm
- algorithm
- <algorithm>
- 2016 UESTC Training for Search Algorithm & String E - 吴队长征婚 dfs剪枝、好题
- HDU 1702 ACboy needs your help again!(栈和队列的试用)
- android webview native与JavaScript相互调用 java与JavaScript相互调用
- Java异常体系结构
- caffe SilenceLayer
- c语言环境下如何创建一个外部函数
- [Algorithm]九章五.DFS
- 一只小蜜蜂...
- 如何解决sublime text3中文出现乱码
- UUID跟UDID的区别
- lintcode(647)Substring Anagrams
- EOJ 3256拼音魔法(string+char[]的使用技巧)
- A. 拼音魔法(模拟)
- 如何将JSON的键转为键值-xyp-hf
- A == B ?