DFS 算法視頻QQ_1603159172
什么時候用dfs?
短, 小, 最問題
而90%DFS的題, 要么是排列, 要么是組合
組合搜索問題 Combination
問題模型:求出所有滿足條件的“組合”
判斷條件:組合中的元素是順序無關的
時間復雜度:與 2^n 相關
遞歸三要素
一般來說,如果面試官不特別要求的話,DFS都可以使用遞歸(Recursion)的方式來實現。
遞歸三要素是實現遞歸的重要步驟:
• 遞歸的定義
• 遞歸的拆解
• 遞歸的出口
Combination Sum
算法視頻QQ_1603159172
Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
為什么是正整數?
如果有0:
取一次是一種方案, 取兩次是一種方案, 最后有無數種方案.
新題和老題的關系:
看到新題要和老題產生關系, 哪兒像哪兒不像
這道題和subset的關系:
- 可以無限制的取
-
限制了一個和
-
去重: {1,2} == {2,1} 選代表
{2,2,3} = {2,3,2] = {3,2,2]
其中49行, [2’,2”,3]可能有三種:
[2’,2”,3]
[2’,2’,3]
ps: 也可以用hash set去重
去重
Given an array of integers, remove the duplicate numbers in it.
You should:
- Do it in place in the array.
-
Move the unique numbers to the front of the array.
-
Return the total number of the unique numbers.
class Solution {
public: /** * @param A: a list of integers * @return : return an integer */ int removeDuplicates(vector<int> &nums) { if (nums.size() == 0) { return 0; } int len = 0; for (int i = 1; i < nums.size(); i++) { if (nums[len] != nums[i]) { nums[++len] = nums[i]; } } return len + 1; } };
兩點需要注意:
- for 之后的i從1開始
-
return的不是index,二是數量,所以要加1
時間復雜度
算法視頻QQ_1603159172
答案個數不知道, 假設為S;
每個答案用的時間=target;
所以總的時間復雜度= O(S*target), 是個NP問題
Combination Sum II
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
Each number in C may only be used once in the combination.
其中:
if (i != startIndex && candidates[i] == candidates[i - 1]) { continue; }
去重的方式是相同的從第一個開始選, 不能跳過第一個選第二個.
Palindrome Partitioning
算法視頻QQ_1603159172
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
這道題的本質是組合問題:
aab怎么分割的問題, 就是要不要縫隙
三個字符兩個空隙, 每個空隙我可以選擇要或者不要, 所以有4個答案.
一邊切, 一邊驗證是不是回文串:
因為搜索是一種嘗試, 是把以這個方案開頭的所有都找到.
找完之后, 還要回到原來的狀態, 要記得remove
Permutation
算法視頻QQ_1603159172
Given a list of numbers, return all possible permutations.
排列搜索問題 Permutation
問題模型:求出所有滿足條件的“排列”。
判斷條件:組合中的元素是順序“相關”的。
時間復雜度:與 n! 相關。
此題的時間復雜度是: O(n! * n)
和subsets的關系是:
- permutation是湊齊再加到答案上; 而subsets是中間結果也存.
-
permutation是可以回頭取的, 但是不能重復取, 所以沒有startIndex.
Permutation II
算法視頻QQ_1603159172
Given a list of numbers with duplicate number in it. Find all unique permutations.
- 邊排列邊看有沒有斜線攻擊.
- 左上到右下的斜線上的點符合差相等:x1 – y1 = x2 – y2
- 右上到左下和相等.
- 每個function不超過三十行, 不容易出bug
Word Ladder
算法視頻QQ_1603159172
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:
Only one letter can be changed at a time
Each intermediate word must exist in the dictionary
搜索,動態規划,二叉樹的時間復雜度計算通用公式
搜索的時間復雜度:O(答案總數 * 構造每個答案的時間)
舉例:Subsets問題,求所有的子集。子集個數一共 2^n,每個集合的平均長度是 O(n) 的,所以時間復雜度為 O(n * 2^n),同理 Permutations 問題的時間復雜度為:O(n * n!)
動態規划的時間復雜度:O(狀態總數 * 計算每個狀態的時間復雜度)
舉例:triangle,數字三角形的最短路徑,狀態總數約 O(n^2) 個,計算每個狀態的時間復雜度為 O(1)——就是求一下 min。所以總的時間復雜度為 O(n^2)
用分治法解決二叉樹問題的時間復雜度:O(二叉樹節點個數 * 每個節點的計算時間)
舉例:二叉樹最大深度。二叉樹節點個數為 N,每個節點上的計算時間為 O(1)。總的時間復雜度為 O(N)
public class Solution { public int ladderLength(String start, String end, Set dict) { if (dict == null) { return 0; } if (start.equals(end)) { return 1; } dict.add(start); dict.add(end); HashSet hash = new HashSet(); Queue queue = new LinkedList(); queue.offer(start); hash.add(start); int length = 1; while(!queue.isEmpty()) { length++; int size = queue.size(); for (int i = 0; i < size; i++) { String word = queue.poll(); for (String nextWord: getNextWords(word, dict)) { if (hash.contains(nextWord)) { continue; } if (nextWord.equals(end)) { return length; } hash.add(nextWord); queue.offer(nextWord); } } } return 0; } // replace character of a string at given index to a given character // return a new string private String replace(String s, int index, char c) { char[] chars = s.toCharArray(); chars[index] = c; return new String(chars); } // get connections with given word. // for example, given word = 'hot', dict = {'hot', 'hit', 'hog'} // it will return ['hit', 'hog'] private ArrayList getNextWords(String word, Set dict) { ArrayList nextWords = new ArrayList(); for (char c = 'a'; c <= 'z'; c++) { for (int i = 0; i < word.length(); i++) { if (c == word.charAt(i)) { continue; } String nextWord = replace(word, i, c); if (dict.contains(nextWord)) { nextWords.add(nextWord); } } } return nextWords; } }
難點一: BFS
難點二:
L單詞長度遠小於N詞典里的單詞數, 所以
L: 10 N:10K
可以把時間從100k變成2.5k
ps: hash_map的時間是O(key.size())
因為key變成hash code即為index
Word Ladder II
算法視頻QQ_1603159172
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:
Only one letter can be changed at a time
Each intermediate word must exist in the dictionary
既有all又有shortest
BFS+DFS
- 小人往A走, 走的是回頭路;
往B走, 沒走的更近;
C才是正確的路線.
- start -> end BFS
end ->start DFS
再reverse
Subsets
非遞歸和其他組合題不一樣, 用位操作構造一個0~2^(n-1)的大循環
Permutation Next
算法視頻QQ_1603159172
Given a list of integers, which denote a permutation.
Find the next permutation in ascending order.
Notice
The list may contains duplicate integers.
1 5 2 4 3找這些數字組成的稍微大那么一點的數
從右往左找第一個降序的地方, 把它和右邊比他大的最小的換, 換完reverse回來
1 5 3 4 2
1 5 3 2 4