全排列-leetcode47
思路:
通过递归,每一层如果发现是相同的参数,则不再向下递归,因为这个位置上相同的数字会造成结果的重复
代码
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> usedIndex = new ArrayList<>();
permuteUnique(nums, usedIndex, result);
return result;
}
public void permuteUnique(int[] nums, List<Integer> usedIndex, List<List<Integer>> result) {
if (nums.length == usedIndex.size()) {
List<Integer> list = new ArrayList<>();
for (Integer index : usedIndex) {
list.add(nums[index]);
}
result.add(list);
return;
}
List<Integer> usedEle = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
if (usedIndex.contains(i) || usedEle.contains(nums[i])) {
continue;
}
usedIndex.add(i);
permuteUnique(nums, usedIndex, result);
usedIndex.remove(usedIndex.size() - 1);
usedEle.add(nums[i]);
}
}
}
时间复杂度空间复杂度分析
时间复杂度:n*n!
空间复杂度:O(n),递归深度为n,构建结果的时候集合长度为n
组合总数III-leetcode216
思路
思路一:通过深度搜索,一个数字可以有两个选择,添加到结果中,或者不添加到结果中,可以以大于目标,等于目标,或者加到9为结束的条件。
思路二:以二进制数作为集合的子集,如果某一位是1就表示该数添加到结果中。遍历所有的数字,并选择其中1的位数为k的数字,然后计算结果。时间复杂度为2^9 * k。空间复杂度为常量。
代码
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> re = new ArrayList<>();
combination(1, k , re, result, n);
return result;
}
public void combination(int index, int k, List<Integer> re, List<List<Integer>> result, int target) {
if (target == 0 && k == re.size()) {
result.add(new ArrayList<>(re));
return;
}
if (target <= 0 || k <= re.size() || index > 9) {
return;
}
re.add(index);
combination(index + 1, k, re, result, target - index);
re.remove(re.size() - 1);
combination(index + 1, k, re, result, target);
}
}
复杂度分析
时间复杂度 k * 2 ^ 9
空间复杂度:M(m)
分割回文串 -leetcode131
思路
通过深度优先搜索,每个字符都有分割和不分割两个选择,要分割就需要和之前未分割的组成一个字符串,同时需要判断这个字符串是否符合回文串.不分割则继续往下一个字符。结束条件是字符串不符合回文串的要求或者字符走到最后一个字符。
代码
class Solution {
public List<List<String>> partition(String s) {
List<List<String>> result = new ArrayList<>();
List<String> re = new ArrayList<>();
partition(result, re, 0, 1, s);
return result;
}
public void partition(List<List<String>> result, List<String> re, int start, int end, String s) {
if (start + 1 == end && start == s.length()) {
result.add(new ArrayList<>(re));
return;
}
if (end > s.length()) {
return;
}
if (check(s.substring(start, end))) {
re.add(s.substring(start, end));
partition(result, re, end, end + 1, s);
re.remove(re.size() - 1);
}
partition(result, re, start, end + 1, s);
}
public boolean check(String s) {
if (s.length() == 0) {
return false;
}
for (int i = 0; i < s.length() / 2; i++) {
if (s.charAt(i) != s.charAt(s.length() - 1 - i)) {
return false;
}
}
return true;
}
}
复杂度分析
时间复杂度:O(2 ^len * len)
空间复杂度:O(len)
复原ip地址-leetcode 93
思路:
分四层递归处理IP
复杂度
时间复杂度:O(4 * s)s是ip地址的长度
空间复杂度:四层的栈空间
电话号码的字母组合 - leetcode17
思路
采用回溯的方式
解数独-leetcode37
代码
class Solution {
private boolean finish = false;
public void solveSudoku(char[][] board) {
solveSudoku(board, 0, 0);
}
public void solveSudoku(char[][] board, int i, int j) {
if (finish) {
return;
}
if (i == 9) {
finish = true;
return;
}
if (board[i][j] != '.') {
int jIndex = j == 8 ? 0 : j + 1;
int iIndex = j == 8 ? i + 1 : i;
solveSudoku(board,iIndex, jIndex);
return;
}
for (char k = '1'; k <= '9'; k++) {
if (check(board, k, i, j)) {
board[i][j] = k;
solveSudoku(board, j == 8 ? i + 1 : i, j == 8 ? 0 : j + 1);
if (finish) {
return;
}
board[i][j] = '.';
}
}
}
public boolean check(char[][] board, char num, int iIndex, int jIndex) {
for (int i = 0; i < board.length; i++) {
if (num == board[i][jIndex]) {
return false;
}
}
for (int i = 0; i < board[0].length; i++) {
if (num == board[iIndex][i]) {
return false;
}
}
int iLevel = (iIndex / 3) * 3;
int jLevel = (jIndex / 3) * 3;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[iLevel + i][jLevel + j] == num) {
return false;
}
}
}
return true;
}
}
思路
递归+回溯:有点儿暴力搜索的意思,但是需要注意有填写数字的位置,往后循环的方式。
复杂度分析
时间复杂度:O(9 ^(9*9))
空间复杂度:(9 * 9)
我觉得还是看面经吧!刷题穿插着来