1.组合总和问题
原题:力扣39.
元素可以重复拿取,且题目的测试用例保证了组合数少于 150 个。
class CombinationSum {List<List<Integer>> res = new ArrayList<>();List<Integer> path = new ArrayList<>();public List<List<Integer>> combinationSum(int[] candidates, int target) {dfs(candidates, 0, target);return res;}// u 是开始遍历的索引public void dfs(int[] c, int u, int target) {if (target < 0) {return;}if (target == 0) {res.add(new ArrayList(path));return;}// 由于元素可以重复,所以 i 从传入的 i 开始继续遍历for (int i = u; i < c.length; i++) {if (c[i] <= target) {path.add(c[i]);dfs(c, i, target - c[i]);path.remove(path.size() - 1);}}}
}
2.分割回文串
原题:力扣131.
先取第一个数与后边分开,再取前两个数与后边分开,以此类推…
class Pritition {List<List<String>> lists = new ArrayList<>();Deque<String> deque = new LinkedList<>();public List<List<String>> partition(String s) {backTracking(s, 0);return lists;}// 回溯算法private void backTracking(String s, int startIndex) {// 已经遍历完成,可以作为一组方案添加到 lists 里面if (startIndex >= s.length()) {lists.add(new ArrayList(deque));return;}for (int i = startIndex; i < s.length(); i++) {if (isPalindrome(s, startIndex, i)) {String str = s.substring(startIndex, i + 1);deque.addLast(str);} else {continue;}backTracking(s, i + 1);deque.removeLast();}}// 判断回文串private boolean isPalindrome(String s, int startIndex, int end) {for (int i = startIndex, j = end; i < j; i++, j--) {if (s.charAt(i) != s.charAt(j)) {return false;}}return true;}
}
3.子集问题
原题:力扣78.
子集问题往往是要取得所有结果,所以不需要找到满足条件的结果或者剪枝。
class Subsets {List<List<Integer>> result = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();public List<List<Integer>> subsets(int[] nums) {// 空集合if (nums.length == 0) {result.add(new ArrayList<>());return result;}subsetsHelper(nums, 0);return result;}private void subsetsHelper(int[] nums, int startIndex) {// 之前的可以作为一个子集result.add(new ArrayList<>(path));if (startIndex >= nums.length) {return;}for (int i = startIndex; i < nums.length; i++) {path.add(nums[i]);subsetsHelper(nums, i + 1);path.removeLast();}}
}
4.排列问题
原题:力扣46.
class Permute {List<List<Integer>> result = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();boolean[] used;public List<List<Integer>> permute(int[] nums) {if (nums.length == 0) {return result;}used = new boolean[nums.length];permuteHelper(nums);return result;}private void permuteHelper(int [] nums) {// 排列完了,加入结果if (path.size() == nums.length) {result.add(new ArrayList<>(path));return;}for (int i = 0; i < nums.length; i++) {if (used[i]) {continue;}used[i] = true;path.add(nums[i]);permuteHelper(nums);path.removeLast();used[i] = false;}}
}
5.字母大小写全排列
原题:力扣784.
数字是干扰项,排除就好。字母的大小写转换用异或 32 来操作。
class LetterCasePermutation {public List<String> letterCasePermutation(String s) {List<String> ans = new ArrayList<String>();dfs(s.toCharArray(), 0, ans);return ans;}public void dfs(char[] arr, int pos, List<String> res) {while (pos < arr.length && Character.isDigit(arr[pos])) {pos++;}if (pos == arr.length) {res.add(new String(arr));return;}arr[pos] ^= 32;dfs(arr, pos + 1, res);arr[pos] ^= 32;dfs(arr, pos + 1, res);}
}
6.单词搜索
原题:力扣79.
class Exist {public boolean exist(char[][] board, String word) {char[] words = word.toCharArray();for (int i = 0; i < board.length; i++) {for (int j = 0; j < board[0].length; j++) {// 这里不要简写if (dfs(board, words, i, j, 0)) {return true;}}}return false;}// k 代表了 word 取到了第几个字符boolean dfs(char[][] board, char[] words, int i, int j, int k) {if (i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != words[k]) {return false;}// 终止条件if (k == words.length - 1) {return true;}// 改成终止符,不允许再次访问board[i][j] = '\0';boolean res = dfs(board, words, i + 1, j, k + 1) || dfs(board, words, i - 1, j, k + 1) ||dfs(board, words, i, j + 1, k + 1) || dfs(board, words, i, j - 1, k + 1);// 使用后再改回来,即前面题目的 remove 操作board[i][j] = words[k];return res;}
}
如果对您有帮助,请点赞关注支持我,谢谢!
如有错误或者不足之处,敬请指正!
个人主页:星不易
算法通关村专栏:不易|算法通关村