Java知识点
//Arrays.fill()
Arrays.fill(array, content);
//StringBuilder删除某个位置的字符
sb.deleteCharAt(index)
一 题目列表
其实就是在做深度优先搜索(遍历)遍历保存路径 然后随时检查当前路径是否符合条件 满足就加在结果中
1 组合
39 Combination Sum
40 Combination Sum II
216 Combination Sum III
78 Subsets
90 Subsets II
lt680. Split String
2 排列
46 Permutations
47 Permutations II
lt10 String Permutation II
51 N-Queens
52 N-Queens II
3 记忆化搜索
44 Wildcard Matching
10 Regular Expression Matching
140 Word Break II
二 组合
39. Combination Sum
元素可以重复使用 求和是target组合
class Solution {
public List> combinationSum(int[] candidates, int target) {
List> result = new ArrayList<>();
Arrays.sort(candidates);
helper(candidates, 0, new ArrayList(), result, target);
return result;
}
private void helper(int[] candidates, int index, List subset, List> result, int target){
//深度拷贝
if(target==0)
result.add(new ArrayList(subset));
if(index==candidates.length)
return;
for(int i=index; i0 && candidates[i]==candidates[i-1])
continue;
if(candidates[i]>target)
return;
subset.add(candidates[i]);
//可以重复使用 所以i不更新
helper(candidates, i, subset, result, target-candidates[i]);
subset.remove(subset.size()-1);
}
}
}
40. Combination Sum II
元素不可以重复使用 求和是target组合
class Solution {
public List> combinationSum2(int[] candidates, int target) {
List> result = new ArrayList<>();
if(candidates==null || candidates.length==0)
return result;
Arrays.sort(candidates);
helper(candidates, 0, new ArrayList(), result, target);
return result;
}
private void helper(int[] candidates, int index, List subset, List> result, int target){
if(target==0)
result.add(new ArrayList(subset));
if(index==candidates.length)
return;
for(int i=index; iindex && candidates[i]==candidates[i-1])
continue;
if(target
216. Combination Sum III
求k个1-9不同的数组合 和是n
class Solution {
public List> combinationSum3(int k, int n) {
List> result = new ArrayList<>();
if(n>45 || k>9 || k<=0)
return result;
helper(1, new ArrayList(), result, n, k);
return result;
}
private void helper(int index, List subset, List> result, int target, int k){
if(target==0 && k==0)
result.add(new ArrayList(subset));
if(index==10)
return;
for(int i=index; i<=9; i++){
if(target
78. Subsets
没有重复
class Solution {
public List> subsets(int[] nums) {
List> result = new ArrayList<>();
if(nums==null || nums.length==0)
return result;
helper(nums, 0, new ArrayList(), result);
return result;
}
private void helper(int[] nums, int index, ArrayList subset, List> result){
result.add(new ArrayList<>(subset));
if(index>=nums.length)
return;
for(int i=index; i
90. Subsets II
又重复
class Solution {
public List> subsetsWithDup(int[] nums) {
List> result = new ArrayList<>();
if(nums==null || nums.length==0)
return result;
Arrays.sort(nums);
helper(nums, 0, new ArrayList(), result);
return result;
}
private void helper(int[] nums, int index, List subset, List> result){
result.add(new ArrayList( subset));
if(index==nums.length)
return;
for(int i=index; iindex && nums[i]==nums[i-1])
continue;
subset.add(nums[i]);
helper(nums, i+1, subset, result);
subset.remove(subset.size()-1);
}
}
}
lt680. Split String
Given the string "123"
return [["1","2","3"],["12","3"],["1","23"]]
public class Solution {
/*
* @param : a string to be split
* @return: all possible split string array
*/
public List> splitString(String s) {
// write your code here
List> result = new ArrayList<>();
if(s==null )
return result;
helper(s, 0, new ArrayList(), result);
return result;
}
private void helper(String s, int index, ArrayList subset, List> result){
if(index==s.length()){
result.add(new ArrayList(subset));
return;
}
for(int i=index; i
组合
46. Permutations
无重复元素
class Solution {
public List> permute(int[] nums) {
List> result = new ArrayList<>();
if(nums==null || nums.length==0)
return result;
boolean[] visited = new boolean[nums.length];
helper(nums, visited, new ArrayList<>(), result);
return result;
}
private void helper(int[] nums, boolean[] visited, List subset, List> result){
if(subset.size()==nums.length){
result.add(new ArrayList(subset));
return;
}
for(int i=0; i
47. Permutations II
有重复元素
class Solution {
public List> permuteUnique(int[] nums) {
List> result = new ArrayList<>();
if(nums==null || nums.length==0)
return result;
Arrays.sort(nums);
boolean[] visited = new boolean[nums.length];
helper(nums, visited, new ArrayList<>(), result);
return result;
}
private void helper(int[] nums, boolean[] visited, List subset, List> result){
if(subset.size()==nums.length){
result.add(new ArrayList(subset));
return;
}
for(int i=0; i0 && nums[i]==nums[i-1] && !visited[i-1])
continue;
if(visited[i])
continue;
visited[i]=true;
subset.add(nums[i]);
helper(nums, visited, subset, result);
subset.remove(subset.size()-1);
visited[i]=false;
}
}
}
lt10. String Permutation II
public class Solution {
//Given "aabb", return ["aabb", "abab", "baba", "bbaa", "abba", "baab"].
/**
* @param str: A string
* @return: all permutations
*/
public List stringPermutation2(String str) {
public List stringPermutation2(String str) {
// write your code here
List results = new ArrayList<>();
str = sort(str);
boolean[] visited = new boolean[str.length()];
helper(str, visited, new StringBuilder(), results);
return results;
}
private String sort(String str){
char[] chars = str.toCharArray();
Arrays.sort(chars);
return new String(chars);
}
private void helper(String str, boolean[] visited, StringBuilder sb, List results){
if(sb.length()==str.length()){
results.add(new String(sb.toString()));
return;
}
for(int i=0; i0 && str.charAt(i)==str.charAt(i-1) && visited[i-1]==false)
continue;
sb.append(str.charAt(i));
visited[i] = true;
helper(str, visited, sb, results);
visited[i] = false;
sb.deleteCharAt(sb.length()-1);
}
}
}
51. N-Queens
返回所有棋盘布局
//先用0 - (n-1)的排列表示一个棋盘布局
//0 - (n-1)的排列 index代表row 值代表col
//优点在于 只用考虑斜线冲突 不会有同行或同列冲突
//相当于在找所有排列 只不过每次添加的时候考察是否存在冲突
//然后把这些排列转成棋盘布局
class Solution {
public List> solveNQueens(int n) {
List> numListLists = new ArrayList<>();
Set cols = new HashSet();
Set left = new HashSet();
Set right = new HashSet();
helper(n, cols, left, right, new ArrayList(), numListLists);
return toChessBoards(numListLists, n);
}
private void helper(int n, Set cols, Set left, Set right, List list, List> lists){
if(list.size() == n){
lists.add(new ArrayList(list));
return;
}
for(int i=1; i<=n; i++){
if(cols.contains(i))
continue;
if(left.contains(list.size()+i))
continue;
if(right.contains(list.size()-i))
continue;
left.add(list.size()+i);
right.add(list.size()-i);
cols.add(i);
list.add(i);
helper(n, cols, left, right, list, lists);
list.remove(list.size()-1);
left.remove(list.size()+i);
right.remove(list.size()-i);
cols.remove(i);
}
}
private List> toChessBoards(List> numListLists, int n){
List> results = new ArrayList<>();
char[] chars = new char[n];
Arrays.fill(chars, '.');
for(List numList: numListLists){
List result = new ArrayList<>();
for(Integer col: numList){
chars[col-1] = 'Q';
String temp = new String(chars);
result.add(temp);
chars[col-1] = '.';
}
results.add(result);
}
return results;
}
}
52. N-Queens II
求可能的布局个数
// \冲突 差相等 n*n 可能的值 -(n-1) - (n-1) 所以加n对应到2n长度的d1
// /冲突 和相等 n*n 可能的值 0-2(n-1) 直接对应长度2n的d2
public class Solution {
int count = 0;
public int totalNQueens(int n) {
Set cols = new HashSet();
Set left = new HashSet();
Set right = new HashSet();
helper(n, cols, left, right, new ArrayList());
return count;
}
private void helper(int n, Set cols, Set left, Set right, List list){
if(list.size() == n){
count++;
}
for(int i=1; i<=n; i++){
if(cols.contains(i) || left.contains(list.size()+i) || right.contains(list.size()-i))
continue;
left.add(list.size()+i);
right.add(list.size()-i);
cols.add(i);
list.add(i);
helper(n, cols, left, right, list);
list.remove(list.size()-1);
left.remove(list.size()+i);
right.remove(list.size()-i);
cols.remove(i);
}
}
}
记忆化搜索
44. Wildcard Matching
(0,0)->(1,1)(1,0)(0,1)
(1,0)->(2,1)(1,1)(2,0)
(0,1)->(1,2)(1,1)(0,2)
可以发现已经有重复 所以使用记忆化搜索避免重复
本质上是在搜索过程中会遇到已访问过的节点
'?' Matches any single character.
'' Matches any sequence of characters (including the empty sequence).
时间复杂度为O(s.length()p.length())
//时间复杂度为O(s.length()*p.length())
class Solution {
public boolean isMatch(String s, String p) {
if (s == null || p == null) {
return false;
}
boolean[][] memo = new boolean[s.length()][p.length()];
boolean[][] visited = new boolean[s.length()][p.length()];
return isMatchHelper(s, 0, p, 0, memo, visited);
}
private boolean isMatchHelper(String s, int sIndex,
String p, int pIndex,
boolean[][] memo,
boolean[][] visited) {
// 如果 p 从pIdex开始是空字符串了,那么 s 也必须从 sIndex 是空才能匹配上
if (pIndex == p.length()) {
return sIndex == s.length();
}
// 如果 s 从 sIndex 是空,那么p 必须全是 *
if (sIndex == s.length()) {
return allStar(p, pIndex);
}
if (visited[sIndex][pIndex]) {
return memo[sIndex][pIndex];
}
char sChar = s.charAt(sIndex);
char pChar = p.charAt(pIndex);
boolean match;
if (pChar == '*') {
match = isMatchHelper(s, sIndex, p, pIndex + 1, memo, visited) ||
isMatchHelper(s, sIndex + 1, p, pIndex, memo, visited);
} else {
match = charMatch(sChar, pChar) &&
isMatchHelper(s, sIndex + 1, p, pIndex + 1, memo, visited);
}
visited[sIndex][pIndex] = true;
memo[sIndex][pIndex] = match;
return match;
}
private boolean charMatch(char sChar, char pChar) {
return (sChar == pChar || pChar == '?');
}
private boolean allStar(String p, int pIndex) {
for (int i = pIndex; i < p.length(); i++) {
if (p.charAt(i) != '*') {
return false;
}
}
return true;
}
}
10. Regular Expression Matching
'.' Matches any single character.
'*' Matches zero or more of the preceding element.
class Solution {
public boolean isMatch(String s, String p) {
boolean[][] visited = new boolean[s.length()][p.length()];
boolean[][] memo = new boolean[s.length()][p.length()];
return helper(s, 0, p, 0, visited, memo);
}
public boolean helper(String s,
int indexS,
String p,
int indexP,
boolean[][] visited,
boolean[][] memo){
if(indexS==s.length()){
return checkEmpty(p, indexP);
}
if(indexP==p.length()){
return indexS==s.length();
}
if(visited[indexS][indexP]){
return memo[indexS][indexP];
}
boolean match = false;
if(indexP
131. Palindrome Partitioning
求把一个字符串切割成所有字串都是回文串的所有方式
Input: "aab"
Output:
[ ["aa","b"], ["a","a","b"] ]
abaxxxx
如果不用memo xxxx重复计算
如果用了memo 在第一次迭代xxxx的结果已经计算出来 下次遇到直接返回结果就可以
Time complexity: O(n(2^n))
For a string with length n, there will be (n - 1) intervals between chars.
For every interval, we can cut it or not cut it, so there will be 2^(n - 1) ways to partition the string.
For every partition way, we need to check if it is palindrome, which is O(n).
So the time complexity is O(n(2^n))
解的个数*构造一个解的时间
class Solution {
public List> partition(String s) {
// return withMemo(s);
return withoutMemo(s);
}
public List> withMemo(String s) {
List> result = new ArrayList<>();
if(s==null || s.length()==0)
return result;
Map>> map = new HashMap<>();
return help(s, 0, map);
}
private List> help(String s, int index, Map>> memo){
if(index==s.length()){
List> result = new ArrayList<>();
result.add(new ArrayList<>());
return result;
}
if(memo.containsKey(index)){
return memo.get(index);
}
List> results = new ArrayList<>();
for(int i=index; i> suffixs = help(s, i+1, memo);
for(List list: suffixs){
List result = new ArrayList<>(list);
result.add(0, prefix);
results.add(result);
}
}
memo.put(index, results);
return results;
}
public List> withoutMemo(String s) {
List> result = new ArrayList<>();
if(s==null || s.length()==0)
return result;
helper(s, 0, new ArrayList(), result);
return result;
}
private void helper(String s, int index, List subset, List> result){
if(index==s.length()){
result.add(new ArrayList(subset));
return;
}
for(int i=index; i
140. Word Break II
最坏情况 所有拆法都符合要求 一共2^(n-1)种拆法 所以最坏时间复杂度O(2^n)
记忆化的优点在于
"aaaaab", with wordDict = ["a", "aa", "aaa", "aaaa", "aaaaa", "aaaaa"],
map中 key
在第一次迭代之后 aaab的分割方案已经求过 在第二次迭代可以使用结果
class Solution {
public List wordBreak(String s, List wordDict) {
List result = new ArrayList<>();
if(s==null || wordDict==null)
return result;
//key是string value是所有这个string能够被拆分成的词组组合list
Map> memo = new HashMap<>();
return helper(s, wordDict, memo);
}
private List helper(String s, List wordDict, Map> memo){
if(memo.containsKey(s))
return memo.get(s);
List result = new ArrayList<>();
if(s.length()==0)
return result;
if(wordDict.contains(s))
result.add(s);
for (int len = 1; len < s.length(); ++len){
String word = s.substring(0, len);
if (!wordDict.contains(word)) {
continue;
}
String suffix = s.substring(len);
List segmentations = helper(suffix, wordDict, memo);
for (String segmentation: segmentations){
result.add(word + " " + segmentation);
}
}
memo.put(s, result);
return result;
}
}
139. Word Break
class Solution {
public boolean wordBreak(String s, List wordDict) {
Set set = new HashSet<>();
for(String string : wordDict)
set.add(string);
return bfsMethod(s, set);
// return dfsMethod(s, set);
}
public boolean dfsMethod(String s, Set dict) {
// DFS
Set set = new HashSet();
return dfs(s, 0, dict, set);
}
private boolean dfs(String s, int index, Set dict, Set set){
// base case
if(index == s.length()) return true;
// check memory
//原理是如果曾经访问过 这里再次访问 说明后面的结果肯定是false
if(set.contains(index)) return false;
// recursion
for(int i = index+1;i <= s.length();i++){
String t = s.substring(index, i);
if(dict.contains(t))
if(dfs(s, i, dict, set))
return true;
else
set.add(i);
}
set.add(index);
return false;
}
public boolean bfsMethod(String s, Set dict) {
if (dict.contains(s)) return true;
Queue queue = new LinkedList();
queue.offer(0);
// use a set to record checked index to avoid repeated work.
// This is the key to reduce the running time to O(N^2).
Set visited = new HashSet();
visited.add(0);
while (!queue.isEmpty()) {
int curIdx = queue.poll();
for (int i = curIdx+1; i <= s.length(); i++) {
if (visited.contains(i))
continue;
if (dict.contains(s.substring(curIdx, i))) {
if (i == s.length())
return true;
queue.offer(i);
visited.add(i);
}
}
}
return false;
}
}