一、逆序想到 stack ; 好比 445. 兩數相加 II,固然,能夠用 stack 也是能夠用 List,list 有序,所以也是能夠看成 stack 用;html
二、要求達到 O(n \log n)O(nlogn) 的時間複雜度和 O(1)O(1) 的空間複雜度,時間複雜度是 O(n \log n)O(nlogn) 的排序算法包括歸併排序、堆排序和快速排序(快速排序的最差時間複雜度是 O(n^2)O(n2)),其中最適合鏈表的排序算法是歸併排序。算法
三、對於鏈表,有時候須要把頭結點加入循環,能夠在頭結點前面在家一個節點,這樣就能夠用於判斷了;數組
四、鏈表經常使用的操做邏輯,用 stack, 數組保存節點組成新的隊列;用一個新節點來鏈接原來的節點,這樣,即便對原有節點改變了,仍是能夠返回頭結點。熟悉鏈表的反轉,合併等邏輯。ide
五、關於二叉樹,二叉樹通常採用遞歸,通常是遞歸到最後一個的時候,在不斷往前,所以你要作好最好一個判斷究竟是返回什麼,好比深度的求解等等。spa
class Solution { public int maxDepth(TreeNode root) { if (root == null) { return 0; } else { int leftHeight = maxDepth(root.left); int rightHeight = maxDepth(root.right); return Math.max(leftHeight, rightHeight) + 1; // 這裏加1,不斷遞歸,數值就變大了 } } }
六、二叉樹的遞歸調用其實就是存在一個隱藏的stack。只是你們平時熟悉了遞歸,沒有去細想內部的邏輯。因此若是不採用遞歸方式來實現,就是得采用 stack 來維護這個順序,可是要注意先入後出這個點。指針
七、若是給你一個數組 num1 足夠空間,前部分已經存在值了,讓你把另外一個 num2 的值填到 num1 中。這種要麼新建一個數組,填完後再挪到 num1 中,另外一種是從合併後的長度開始填,這樣確保不會覆蓋 num1 前面已有的值。可參考 88. 合併兩個有序數組code
八、兩個字符串找不一樣,對於字符串能夠採用求和,位運算,以及一個數組來記錄各個字母出現的個數,以此來找到不一樣。參考:389. 找不一樣htm
1 // 求和 2 class Solution { 3 public char findTheDifference(String s, String t) { 4 int as = 0, at = 0; 5 for (int i = 0; i < s.length(); ++i) { 6 as += s.charAt(i); 7 } 8 for (int i = 0; i < t.length(); ++i) { 9 at += t.charAt(i); 10 } 11 return (char) (at - as); 12 } 13 } 14 15 // 計數 16 class Solution { 17 public char findTheDifference(String s, String t) { 18 int[] cnt = new int[26]; 19 for (int i = 0; i < s.length(); ++i) { 20 char ch = s.charAt(i); 21 cnt[ch - 'a']++; 22 } 23 for (int i = 0; i < t.length(); ++i) { 24 char ch = t.charAt(i); 25 cnt[ch - 'a']--; 26 if (cnt[ch - 'a'] < 0) { 27 return ch; 28 } 29 } 30 return ' '; 31 } 32 } 33 34 // 位運算 35 class Solution { 36 public char findTheDifference(String s, String t) { 37 int ret = 0; 38 for (int i = 0; i < s.length(); ++i) { 39 ret ^= s.charAt(i); 40 } 41 for (int i = 0; i < t.length(); ++i) { 42 ret ^= t.charAt(i); 43 } 44 return (char) ret; 45 } 46 }
九、翻轉二叉樹,這道題目遇到過好幾遍,雖然知道翻轉,可是就不知道如何寫比較好:226. 翻轉二叉樹blog
class Solution { public TreeNode invertTree(TreeNode root) { if (root == null) { return null; } // 若是此時左右節點已經爲 null 了,那麼就會執行後面的交換邏輯,而後遞歸就會回到父節點那一層 TreeNode left = invertTree(root.left); TreeNode right = invertTree(root.right); root.left = right; root.right = left; return root; } }
十、關於遞歸。我感受本身對遞歸仍是沒有理解透徹。排序
對於509. 斐波那契數,我能夠很輕鬆寫下 以下代碼,並不會以爲有啥問題。
class Solution { public int fib(int n) { if (n==1 || n==2) return 1; return fib(n-1)+ fib(n-2); } }
一樣的,對於129. 求根節點到葉節點數字之和,也是遞歸,可是對於二叉樹的遞歸我確實很忐忑,老是以爲本身寫的代碼會有啥問題,具體代碼以下:
class Solution { public int sumNumbers(TreeNode root) { return dfs(root, 0); } public int dfs(TreeNode root, int prevSum) { if (root == null) { return 0; } int sum = prevSum * 10 + root.val; if (root.left == null && root.right == null) { return sum; } else { // 既然你知道是遞歸,同時你也把遞歸的分支搞清楚了,只有左右兩個分支,所以你就寫下就是了 return dfs(root.left, sum) + dfs(root.right, sum); } } }
還有就是我在想,是否是應該按照第一題同樣,先把遞歸的狀態搞清楚,也就是當前狀態和前面幾個狀態是啥關係,有幾個分支。都理清楚了可能就好寫了。而後把遞歸的結束條件分析清楚就好,結束條件放在前面,遞歸邏輯放在後面,只有沒有結束纔是能夠進入遞歸的。
十、對於二分法要時刻關注只有兩個元素的狀況,好比:[1,2],[2,1]。這時候 middle = left。這時候注意 left 和 right 之間的關係。
十一、在作加法和乘法的點時候要考慮會不會存在溢出的狀況,一旦溢出,結果就不同了。能夠考慮乘法變成除法,加法變成減法,以此逃過溢出。