2-27-lc40组合总和II+lc77组合+lc78子集+lc79单词搜索
40. 组合总和 II
class Solution {//对于【1(a)、1(b)、2】target=3情况,会出现两个(1、2) //所以,应排好序,则相同数必相邻,处理到相邻相同时跳过则可去重 List<List<Integer>> ans = new ArrayList<>(); List<Integer> tmp = new ArrayList<>(); public List<List<Integer>> combinationSum2(int[] candidates, int target) { Arrays.sort(candidates); dfs(candidates,target,0);//设置IDX,去除重复,每次从IDX+1开始做选择 return ans; } public void dfs(int[] candidates,int target,int idx){ if(target==0){ ans.add(new ArrayList<>(tmp));//由于是引用,后面tmp变化了,ans里面的tmp也会变,故new return; } for(int i=idx;i<candidates.length&&target-candidates[i]>=0;i++){//若新加入的太大,则剪枝跳过循环 if(i>idx&&candidates[i]==candidates[i-1])continue;//处理到相邻相同时跳过则可去重 tmp.add(candidates[i]); dfs(candidates,target-candidates[i],i+1); tmp.remove(tmp.size()-1); } } }
77. 组合
class Solution { List<List<Integer>> ans = new ArrayList<>(); List<Integer> tmp = new ArrayList<>(); public List<List<Integer>> combine(int n, int k) { dfs(n,k,1); return ans; } private void dfs(int n,int k,int idx){ if (tmp.size() + (n - idx + 1) < k) { return;//当前idx的位置后面都加起来,也填不满tmp,此时剪枝 } if(tmp.size()==k){ ans.add(new ArrayList<>(tmp)); return; } tmp.add(idx); dfs(n,k,idx+1); tmp.remove(tmp.size()-1); dfs(n,k,idx+1); } }
78. 子集
class Solution { List<List<Integer>> ans = new ArrayList<>(); List<Integer> tmp = new ArrayList<>(); public List<List<Integer>> subsets(int[] nums) { dfs(nums,0); return ans; } private void dfs(int[] nums,int idx){ if(idx==nums.length){ ans.add(new ArrayList<>(tmp)); return; } tmp.add(nums[idx]);//选他 dfs(nums,idx+1);//go on tmp.remove(tmp.size()-1);//不选他 dfs(nums,idx+1);//go on } }
79. 单词搜索
public class Solution { private static final int[][] DIRECTIONS = {{-1, 0}, {0, -1}, {0, 1}, {1, 0}}; private int rows; private int cols; private int len; private boolean[][] visited; private char[] charArray; private char[][] board; public boolean exist(char[][] board, String word) { rows = board.length; if (rows == 0) return false; cols = board[0].length; visited = new boolean[rows][cols]; this.len = word.length(); this.charArray = word.toCharArray(); this.board = board; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (dfs(i, j, 0)) return true; } } return false; } private boolean dfs(int x, int y, int begin) { if (begin == len - 1) return board[x][y] == charArray[begin]; if (board[x][y] == charArray[begin]) {//命中 visited[x][y] = true;//标记访问过 for (int[] direction : DIRECTIONS) {//xy上下左右移动 int newX = x + direction[0]; int newY = y + direction[1]; if (inArea(newX, newY) && !visited[newX][newY]) {//若新位置合规且未访问过 if (dfs(newX, newY, begin + 1)) return true;//新位置,新字母继续dfs } } visited[x][y] = false;//退回标记,因为是全局变量 } return false; } private boolean inArea(int x, int y) { return x >= 0 && x < rows && y >= 0 && y < cols; } }