leetcode 算法題 Star

  • 一趟結(jié)束后能夠確定一個(gè)元素的最終位置的排序方法有: 簡(jiǎn)單選擇排序、快速排序、冒泡排序、堆排序

  • 穩(wěn)定性定義:排序前后兩個(gè)相等的數(shù)相對(duì)位置不變,則算法穩(wěn)定。

  • 數(shù)據(jù)結(jié)構(gòu) search insert delete
    數(shù)組 O(n),有序數(shù)組折半查找是O(lgn) O(n) O(n)
    雙向鏈表 O(n) O(1) O(1)
    排序二叉樹 O(lgn) O(lgn) O(lgn)
    哈希表(n與槽數(shù)m成正比)O(1) O(1) O(1)

  • 快速排序算法:

    • public static int[] qsort(int arr[],int start,int end) {        
          int pivot = arr[start];        
          int i = start;        
          int j = end;        
          while (i<j) {            
              while ((i<j)&&(arr[j]>pivot)) {                
                  j--;            
              }            
              while ((i<j)&&(arr[i]<pivot)) {                
                  i++;            
              }            
              if ((arr[i]==arr[j])&&(i<j)) {                
                  i++;            
              } else {                
                  int temp = arr[i];                
                  arr[i] = arr[j];                
                  arr[j] = temp;            
              }        
          }        
          if (i-1>start) arr=qsort(arr,start,i-1);        
          if (j+1<end) arr=qsort(arr,j+1,end);        
          return arr;    
      }    
      
  • 歸并排序(左右分治):

    •     /**
           * 歸并排序
           *
           * @param arr
           */
          public static void mergeSort(int[] arr) {
              process(arr, 0, arr.length - 1);
          }
      
          /**
           * 對(duì)lr范圍內(nèi)進(jìn)行左右分別排序,使中點(diǎn)左右兩邊都有序
           *
           * @param arr
           * @param l
           * @param r
           */
          public static void process(int[] arr, int l, int r) {
              if (l == r) return;
              int mid = (l + r) / 2;
      
              process(arr, l, mid);
              process(arr, mid + 1, r);
              merge(arr, l, r);
          }
      
          /**
           * 使用輔助數(shù)組對(duì)已經(jīng)左右拍好序的數(shù)組進(jìn)行整體排序
           *
           * @param arr
           * @param l
           * @param r
           */
          public static void merge(int[] arr, int l, int r) {
              int[] helpArr = new int[r - l + 1];
              int mid = (r + l) / 2;
              int p = l;
              int q = mid + 1;
              int index = 0;
              while (p <= mid && q <= r) {
                  helpArr[index++] = arr[p] < arr[q] ? arr[p++] : arr[q++];
              }
              //左右一定有一個(gè)越界
              while (p <= mid) {
                  helpArr[index++] = arr[p++];
              }
              while (q <= r) {
                  helpArr[index++] = arr[q++];
              }
              if (helpArr.length >= 0) System.arraycopy(helpArr, 0, arr, l, helpArr.length);
          }
      
    • 歸并排序的*Master公式=T(N)=a*T(N/b)+O(N^d)==T(N)=2T(N/2)+O(N) **

  • 大頂堆:(根節(jié)點(diǎn)的關(guān)鍵字既大于等于左子樹的關(guān)鍵字值,同時(shí)也大于等于右子樹的關(guān)鍵字值)

  • 小頂堆:(根結(jié)點(diǎn)的鍵值是所有堆結(jié)點(diǎn)鍵值中最小者)

典例

  • 4的冪:

    • 這個(gè)題和“2的冪”“3的冪”一樣,有不用循環(huán)和遞歸就能直接判斷的方法,同樣十分巧妙,屬于二進(jìn)制/位運(yùn)算的應(yīng)用。
      4的冪的數(shù),都是這樣的數(shù):100、10000、1000000……(4、16、64)
      觀察規(guī)律,可以發(fā)現(xiàn) 4的冪 需要滿足以下條件:
      最高位是 1,其余都為 0;
      最高位的 1 應(yīng)該在奇數(shù)位上,比如:100 的 1 在 第三位上;
      那么對(duì)應(yīng)的判斷方法為:
      用 num & (num-1) 可以判斷條件1,比如:100(4) & 011(3) == 0,結(jié)果為 0 說明符合條件1;
      是否在奇數(shù)位可以用 0xaaaaaaaa 判斷,16 進(jìn)制的 a 是 1010,比如:0100(4) & 1010(a) == 0,結(jié)果為 0 說明最高位 1 在奇數(shù)位上;
      
       public boolean isPowerOfFour(int n) {
              return n > 0 && (n & (n - 1)) == 0 && ((n & 0x55555555) == n);
              
              //        if (n<0) return false; 
              //        if ((n&(n-1))!=0) return false; 判斷是否位2的冪次方
              //        return (n & 0x55555555) == n;   判斷1是否在奇數(shù)位上
              
          }
      
  • 兩個(gè)數(shù)相乘:

    •     public static String multiply2(String num1, String num2) {
              int len1 = num1.length();
              int len2 = num2.length();
              int[] res = new int[len1 + len2];
              for (int i = len1 - 1; i >= 0; i--) {
                  for (int j = len2 - 1; j >= 0; j--) {
                      int LowPos = i + j + 1;
                      int highPos = i + j;
                      int temp = (num1.charAt(i) - '0') * (num2.charAt(j) - '0') + res[LowPos];
                      res[LowPos] = (temp) % 10;
                      res[highPos] += temp / 10; //這里高位不要取mod
                  }
              }
              StringBuilder sb = new StringBuilder();
              for (int i : res) {
                  if (!(sb.length() == 0) && i == 0) sb.append(i);
              }
              return sb.length() == 0 ? "0" : sb.toString();
          }
      
      
  • 二叉樹的公共祖先:

    • 最近公共祖先的定義為:“對(duì)于有根樹 T 的兩個(gè)結(jié)點(diǎn) p、q,最近公共祖先表示為一個(gè)結(jié)點(diǎn) x,滿足 x 是 p、q 的祖先且 x 的深度盡可能大(一個(gè)節(jié)點(diǎn)也可以是它自己的祖先)。”

      例如,給定如下二叉樹: root = [3,5,1,6,2,0,8,null,null,7,4]

      [圖片上傳失敗...(image-2faa57-1585194160478)]

  • class Solution {
        /*
        算法思想,當(dāng)遞歸到的節(jié)點(diǎn)為p1或p2時(shí)候,則將該節(jié)點(diǎn)向上傳遞,
        使其父節(jié)點(diǎn)變成其本身,如果一個(gè)節(jié)點(diǎn)下方?jīng)]有p1/p2,則向上傳遞null,使父節(jié)點(diǎn)為null,
        當(dāng)左右節(jié)點(diǎn)分別是p1,p2時(shí)則說明該節(jié)點(diǎn)是目標(biāo)節(jié)點(diǎn),向上傳遞,
        該目標(biāo)節(jié)點(diǎn)對(duì)應(yīng)的兄弟節(jié)點(diǎn)經(jīng)過遞歸后一定為null(因?yàn)樾值芄?jié)點(diǎn)的子節(jié)點(diǎn)中不存在p1/p2只能向上傳遞null),    最終目標(biāo)頂點(diǎn)傳遞至根節(jié)點(diǎn)。
        */
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p1, TreeNode p2) {
          if (root == null || root == p1 || root == p2) return root;
            TreeNode left = lowestCommonAncestor(root.left, p1, p2);
            TreeNode right = lowestCommonAncestor(root.right, p1, p2);
            if (left == null && right == null) return null;
            if (left == null || right == null) return left == null ? right : left;
            return root;
        }
    }
    
  • 括號(hào)生成

    • 給出 n 代表生成括號(hào)的對(duì)數(shù),請(qǐng)你寫出一個(gè)函數(shù),使其能夠生成所有可能的并且有效的括號(hào)組合。

      例如,給出 n = 3,生成結(jié)果為:

      [ "((()))",
      "(()())",
      "(())()",
      "()(())",
      "()()()"]

    •  public List<String> generateParenthesis(int n) {
              List<String> res = new ArrayList<>();
              generate(res, "", 0, 0, n);
              return res;
          }
        
          //count1統(tǒng)計(jì)“(”的個(gè)數(shù),count2統(tǒng)計(jì)“)”的個(gè)數(shù)
          public void generate(List<String> res, String ans, int count1, int count2, int n) {
              if (count1 > n || count2 > n) return;
              if (count1 == n && count2 == n) res.add(ans);
              /*核心點(diǎn): count1>=count2 ,
              從左往右添加,只有滿足左邊括號(hào)數(shù)量>=右邊括號(hào)時(shí)候,
              才能夠滿足題意,否則會(huì)出現(xiàn)括號(hào)不匹配的情況
              */
              if (count1 >= count2) {
                  generate(res, ans + "(", count1 + 1, count2, n);
                  generate(res, ans + ")", count1, count2 + 1, n);
              }
          }
      
  • BFS:

    • [圖片上傳失敗...(image-26fb97-1585194160478)]
    # 廣度遍歷
    graph = {
        "A": ["B", "C"],
        "B": ["A", "C", "D"],
        "C": ["A", "B", "D", "E"],
        "D": ["B", "C", "E", "F"],
        "E": ["C", "D"],
        "F": ["D"]
    }
    
    
    def BFS(graph, s):
        queue = []  # 使用動(dòng)態(tài)數(shù)組作隊(duì)列
        queue.append(s)
        seen = set()
        while (len(queue) > 0):
            vertex = queue.pop(0) # 每次取隊(duì)列中的第一個(gè)再進(jìn)行添加
            seen.add(s)
            nodes = graph[vertex]
            for w in nodes:
                if w not in seen:
                    queue.append(w)
                    seen.add(w)
            print(vertex)
    
    
    BFS(graph, "A")
    
    
  • DFS

    • # 深度遍歷
      graph = {
          "A": ["B", "C"],
          "B": ["A", "C", "D"],
          "C": ["A", "B", "D", "E"],
          "D": ["B", "C", "E", "F"],
          "E": ["C", "D"],
          "F": ["D"]
      }
      
      
      def DFS(graph, s):
          queue = []  # 使用動(dòng)態(tài)數(shù)組作棧
          queue.append(s)
          seen = set()
          seen.add(s)
          parent = {s: None} # <子節(jié)點(diǎn):父節(jié)點(diǎn)>
          while (len(queue) > 0):
              vertex = queue.pop()
              nodes = graph[vertex]
              for w in nodes:
                  if w not in seen:
                      parent[w] = vertex
                      queue.append(w)
                      seen.add(w)
              print(vertex)
          return parent
      
      if __name__ == "__main__":
          print (DFS(graph,"A"))
      
      
      
  • 使用BFS求最短路徑(Dijkstra):

    • [圖片上傳失敗...(image-a1078d-1585194160478)]

    • import heapq # 權(quán)限比隊(duì)列
      import math
      graph = {
          "A": {"B": 5, "C": 1},
          "B": {"A": 5, "C": 2},
          "C": {"A": 1, "B": 2, "D": 4},
          "D": {"B": 1, "C": 4, "E": 3, "F": 6},
          "E": {"C": 8, "D": 3},
          "F": {"D": 6}
      }
      
      
      def init_distance(graph, s):
          distance = {s: 0}
          for vertex in graph.keys():
              if vertex != s:
                  distance[vertex] = math.inf
          return distance
      
      
      def dijkstra(graph, s):
          pqueue = []  # prorityqueue 具有權(quán)重比的隊(duì)列,權(quán)重高的排前面
          heapq.heappush(pqueue, (0, s))
          seen = set()
          parent = {s: None}
          distance = init_distance(graph, s)
      
          while(len(pqueue) > 0):
              pair = heapq.heappop(pqueue)
              dist = pair[0]  # 取出來的點(diǎn)到s的距離
              vertex = pair[1]
              seen.add(vertex)
      
              nodes = graph[vertex].keys()
              for w in nodes:
                  if w not in seen:
                      if dist+graph[vertex][w] < distance[w]: 
                          distance[w] = dist+graph[vertex][w]
                          heapq.heappush(pqueue, (dist+graph[vertex][w], w))
                          parent[w] = vertex
          return parent, distance
      
      
      parent, distance = dijkstra(graph, "A")
      print(parent)
      print(distance)
      
      
    • 兩個(gè)數(shù)之間的所有數(shù)相與:

      • public static int rangeBitwiseAnd(int m, int n) {
                int count = 0;
                while (n != m) {
                    n >>= 1;
                    m >>= 1;
                    count++;
                }
                return n << count;
            }
        
    • 最大正方形

      • 在一個(gè)由 0 和 1 組成的二維矩陣內(nèi),找到只包含 1 的最大正方形,并返回其面積。

        示例:輸入:

        1 0 1 0 0
        1 0 1 1 1
        1 1 1 1 1
        1 0 0 1 0

        輸出: 4

      • //dp[i][j]為以[i][j]為右下角坐標(biāo)的最長(zhǎng)正方形邊長(zhǎng)
        class Solution {
            public int maximalSquare(char[][] matrix) {
                if (matrix==null||matrix.length==0) return 0;
                int m = matrix.length;
                int n = matrix[0].length;
                int[][] dp = new int[m][n];
                int res = 0;
                for (int i = 0; i < m; i++) {
                    for (int j = 0; j < n; j++) {
                        if (matrix[i][j] == '1' && (i == 0 || j == 0)) {
                            dp[i][j] = 1;
                        }else if (matrix[i][j] == '1') {
                            dp[i][j] = 1 + Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1]));
                        }
                        res = Math.max(dp[i][j] * dp[i][j], res);
                    }
                }
                return res;
            }
        }
        
  • LeetCode 395題:至少有K個(gè)重復(fù)字符的最長(zhǎng)子串

  • 找到給定字符串(由小寫字符組成)中的最長(zhǎng)子串 T , 要求 T 中的每一字符出現(xiàn)次數(shù)都不少于 k 。輸出 T 的長(zhǎng)度。
    示例 1:
    輸入:
    s = "aaabb", k = 3
    輸出:
    3
    最長(zhǎng)子串為 "aaa" ,其中 'a' 重復(fù)了 3 次。
    示例 2:
    輸入:
    s = "ababbc", k = 2
    輸出:
    5
    最長(zhǎng)子串為 "ababb" ,其中 'a' 重復(fù)了 2 次, 'b' 重復(fù)了 3 次。
    
  • 題解(遞歸+分治):

class Solution {
      public int longestSubstring(String s, int k) {
          if (s.length() < k) return 0;
          return countLongestSubstring(s.toCharArray(), 0, s.length() - 1, k);
      }
      private int countLongestSubstring(char[] chars, int l, int r, int k) {
          int[] count = new int[26];
          for (int i = l; i <= r; i++) {
              count[chars[i] - 'a']++;
          }
          //使得左右指針?biāo)谖恢玫淖址麧M足條件(兩指針之間仍然可能存在不滿足條件的字符)
          while (r - l + 1 >= k && count[chars[l] - 'a'] < k) l++;
          while (r - l + 1 >= k && count[chars[r] - 'a'] < k) r--;
            //當(dāng)篩選完畢后如果長(zhǎng)度不滿足K則返回0
          if (r - l + 1 < k) return 0;
         
          //對(duì)初篩滿足條件的子串進(jìn)行遍歷,出現(xiàn)不滿足條件的字符,以字符為分割,左右繼續(xù)遞歸查詢,直到滿足所有的count[chars[i] - 'a']都>=K則 返回  r - l + 1
          for (int i = l; i < r; i++) {
              if (count[chars[i] - 'a'] < k) {
                  return Math.max(countLongestSubstring(chars, l, i - 1, k), countLongestSubstring(chars, i + 1, r, k));
              }
          }
          return r - l + 1;
      }
  }
 

?

  • 計(jì)算完全二叉樹的節(jié)點(diǎn)個(gè)數(shù)并且且時(shí)間復(fù)雜度小于O(N)

  • [圖片上傳失敗...(image-86a6b8-1585194160478)]

  • lcs 最長(zhǎng)公共子串:

    • [圖片上傳失敗...(image-9fb531-1585194160478)]

    • //lrc 最長(zhǎng)公共子串
          public int longestCommonSubsequence(String text1, String text2) {
              int[][] dp = new int[text1.length()][text2.length()];
              for (int i = 0; i < text1.length(); i++) {
                  for (int j = 0; j < text2.length(); j++) {
                      boolean b = text1.charAt(i) == text2.charAt(j);
                      if (i != 0 && j != 0) {
                          if (b) dp[i][j] = dp[i - 1][j - 1] + 1;
                          else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                      } else {
                          if (b) dp[i][j] = 1;
                          else {
                              if (i == 0 && j == 0) continue;
                              if (i == 0) dp[i][j] = dp[i][j - 1];
                              else dp[i][j] = dp[i - 1][j];
                          }
                      }
                  }
              }
              return dp[text1.length() - 1][text2.length() - 1];
          }
      
      

      更優(yōu)解法:

    •  public int longestCommonSubsequence(String text1, String text2) {
              int n1 = text1.length(), n2 = text2.length();
              int[][] dp = new int[n1 + 1][n2 + 1];
              for (int i = 1; i <= n1; i++) {
                  for (int j = 1; j <= n2; j++) {
                      if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
                          dp[i][j] = dp[i - 1][j - 1] + 1;
                      } else {
                          dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                      }
                  }
              }
              return dp[n1][n2];
          }
        
      
    • LIS 最長(zhǎng)上升子序列:

    •  //給定一個(gè)無序的整數(shù)數(shù)組,找到其中最長(zhǎng)上升子序列的長(zhǎng)度。
       
       class Solution {
          public int lengthOfLIS(int[] nums) {
               if (nums.length == 0) return 0;
               int[] dp = new int[nums.length];
               dp[0] = 1;
               for (int i = 1; i < nums.length; i++) {
                   int tempMax = 0;
                   for (int j = i - 1; j >= 0; j--) {
                       if (nums[i] > nums[j]) {
                           tempMax = Math.max(tempMax, dp[j]);
                       }
                   }
                   dp[i] = tempMax + 1;
               }
               int res = 0;
               for (int i : dp) {
                   if (i > res) res = i;
               }
               return res;
           }
       }
      
  • lcs 712 兩個(gè)字符串的最小ascll刪除和:

  •  //最大公共子串 且 要求這些公共子串的 ascii 值最大。    
     public int minimumDeleteSum(String s1, String s2) {
             int sum = 0;
             for (int i = 0; i < s1.length(); i++) sum += s1.charAt(i);
             for (int i = 0; i < s2.length(); i++) sum += s2.charAt(i);
             if (s1.length() == 0 || s2.length() == 0) return sum;
             int[][] dp = new int[s1.length() + 1][s2.length() + 1];
             int max_lcs_sum = 0;
             for (int i = 1; i <= s1.length(); i++) {
                 for (int j = 1; j <= s2.length(); j++) {
                     if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                         dp[i][j] = dp[i - 1][j - 1] + s1.charAt(i - 1);
                     } else {
                         dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                     }
                     max_lcs_sum = Math.max(dp[i][j], max_lcs_sum);
                 }
             }
             return sum - 2 * max_lcs_sum;
         }
    
  • 279 完全平方數(shù):

    • 給定正整數(shù) n,找到若干個(gè)完全平方數(shù)(比如 1, 4, 9, 16, ...)使得它們的和等于 n。你需要讓組成和的完全平方數(shù)的個(gè)數(shù)最少。
      示例 1:
      輸入: n = 12
      輸出: 3 
      解釋: 12 = 4 + 4 + 4.
      
    •         //最小值公式f(n)=常數(shù)i+j*j (需要滿足條件i-j*j>=0,不能越界)
          //而f(j*j)=1
          //所以f(n)=f(i)+f(j*j)=f(i)+1
          //bfs遍歷所有可能的i j組合
          //取每次遍歷的最小值情況
          //dp[i]=Math.min(dp[i],dp[i-j*j]+dp[j*j]);
          
          public int numSquares(int n) {
              int[] dp = new int[n + 1];
              for (int i = 0; i <= n; i++) {
                  //默認(rèn)的每個(gè)數(shù)都是由全部1組成
                  dp[i] = i;
                  //bfs操作
                  for (int j = 0; i - j * j >= 0; j++) {
                      dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
                  }
              }
              return dp[n];
          }
      
  • 376,擺動(dòng)序列(線性DP)

    •     
      public int wiggleMaxLength(int[] nums) {
              if(nums.length<2) return nums.length;
              int low = 1;
              int high = 1;
              for (int i = 1; i < nums.length; i++) {
                  //起始位高低位都為1.
                  //保證了在連續(xù)上升/下降的情況下 high/low 不會(huì)重復(fù)遞增,
                  //在上升情況中,只要沒有發(fā)生坡度中斷,則high對(duì)應(yīng)的low不會(huì)發(fā)生改變。那么high位就不會(huì)發(fā)生改變。
                  if (nums[i] > nums[i - 1]) high = low+1;
                  if (nums[i] < nums[i - 1]) low  = high+1;
              }
              return Math.max(low, high);
          }
      
  • 漢諾塔問題(每次移動(dòng)頂部的,并且不能大壓小)

    • public void hanoti(int N,String from,String to,String help){
          if(N==1) System.out.println("Move 1 from" + from + "to" +to );
          else{
              hanoti(N-1,from,help,to);
              System.out.println("Move"+N+"from" + from + "to" +to );
              hanoti(N-1,help,to,from);
          }
      }
      
  • 502題IPO

    • public int findMaximizedCapital(int k, int W, int[] Profits, int[] Capital) {
              IpoNode[] ipoNodes = new IpoNode[Profits.length];
              PriorityQueue<IpoNode> MinCostHeap = new PriorityQueue<>(comparingInt(o -> o.cost));
              PriorityQueue<IpoNode> MaxProfitHeap = new PriorityQueue<>(comparingInt(o -> -o.profit));
              for (int i = 0; i < ipoNodes.length; i++) {
                  ipoNodes[i] = new IpoNode(Capital[i], Profits[i]);
                  MinCostHeap.add(ipoNodes[i]);
              }
              for (int i = 0; i < k; i++) {
                  while (MinCostHeap.size() > 0 && MinCostHeap.peek().cost <= W) MaxProfitHeap.add(MinCostHeap.poll());
                  if (MaxProfitHeap.size() > 0) W += MaxProfitHeap.poll().profit;
              }
              return W;
          }
      
      class IpoNode {
          public int cost;
          public int profit;
      
          public IpoNode(int cost, int profit) {
              this.cost = cost;
              this.profit = profit;
          }
      }
      
  • 1277 統(tǒng)計(jì)全為1的正方形子矩陣:

    • 核心在于加上每次的邊長(zhǎng)
      因?yàn)楫?dāng)出現(xiàn)長(zhǎng)的邊長(zhǎng),說明以該右下角為正方形幾個(gè)新的小正方形也同時(shí)出現(xiàn)了,
      比如3, res+3意味著加了邊長(zhǎng)為3和邊長(zhǎng)為2和邊長(zhǎng)為1這三個(gè)正方形。
      
      class Solution {
          public int countSquares(int[][] matrix) {
              if (matrix == null || matrix.length == 0) return 0;
              int m = matrix.length;
              int n = matrix[0].length;
              int[][] dp = new int[m][n];
              int res = 0;
              for (int i = 0; i < m; i++) {
                  for (int j = 0; j < n; j++) {
                      if (matrix[i][j] == 1 && (i == 0 || j == 0)) {
                          dp[i][j] = 1;
                      } else if (matrix[i][j] == 1) {
                          dp[i][j] = 1 + Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1]));
                      }
                      //直接將每一個(gè)正方形的邊長(zhǎng)加上來
                      res += dp[i][j];
                  }
              }
              return res;
          }
      }
      
  • 894,所有可能的滿二叉樹

    •     public List<TreeNode> allPossibleFBT(int N) {
              List<TreeNode> res = new ArrayList<TreeNode>();
              if(N % 2 == 0){
                  return res;
              }
              if(N == 1){
                  res.add(new TreeNode(0));
                  return res;
              }
              //對(duì)每個(gè)奇數(shù)
              //一個(gè)奇數(shù)拆成兩個(gè)奇數(shù)+1
              for(int i = 1; i < N; i += 2){
                  List<TreeNode> lt = allPossibleFBT(i);
                  List<TreeNode> rt = allPossibleFBT(N - 1 - i);
                  //每種可能性都加進(jìn)來
                  for(TreeNode l : lt){
                      for(TreeNode r : rt){
                          TreeNode root = new TreeNode(0);
                          root.left = l;
                          root.right = r;
                          res.add(root);
                      }
                  }
              }
              return res;
          }
      
  • 1079 活字印刷:

    • 你有一套活字字模 tiles,其中每個(gè)字模上都刻有一個(gè)字母 tiles[i]。返回你可以印出的非空字母序列的數(shù)目。
      示例 1:
      輸入:"AAB"
      輸出:8
      解釋:可能的序列為 "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA"。
      

分而治之

  • 23 合并K個(gè)排序鏈表

    • 合并 k 個(gè)排序鏈表,返回合并后的排序鏈表。請(qǐng)分析和描述算法的復(fù)雜度。
      示例:
      輸入:
      [
        1->4->5,
        1->3->4,
        2->6
      ]
      輸出: 1->1->2->3->4->4->5->6
      
    •  public ListNode mergeKLists(ListNode[] lists) {
              if (lists == null || lists.length == 0) return null;
              if (lists.length == 1) return lists[0];
              if (lists.length == 2) return mergeTwoListNode(lists[0], lists[1]);
              int mid = lists.length / 2;
              ListNode[] leftArr = new ListNode[mid];
              ListNode[] rightArr = new ListNode[lists.length - mid];
              for (int i = 0; i < lists.length; i++) {
                  if (i < mid) {
                      leftArr[i] = lists[i];
                  } else {
                      rightArr[i - mid] = lists[i];
                  }
              }
              //左右分治,最終變成兩個(gè)listNode合并
              return mergeTwoListNode(mergeKLists(leftArr), mergeKLists(rightArr));
          }
          //遞歸合并兩個(gè)ListNode
          public ListNode mergeTwoListNode(ListNode l1, ListNode l2) {
              if (l1 == null) return l2;
              if (l2 == null) return l1;
              ListNode cur;
              if (l1.val < l2.val) {
                  cur = l1;
                  cur.next = mergeTwoListNode(l1.next, l2);
              } else {
                  cur = l2;
                  cur.next = mergeTwoListNode(l1, l2.next);
              }
              return cur;
          }
      
    • 不用加減乘除做加法:

      • a+b==> (a&b)<<1+a^b

      • (異或就相當(dāng)于沒有進(jìn)位的加法,而&就是尋找進(jìn)位,<<1左移動(dòng)1是表明與的值為進(jìn)位在二進(jìn)制加法中向前一位)

      •   //當(dāng)a==0的時(shí)候說明沒有進(jìn)位
         public int add(int a, int b) {
                 if(a==0) return b;
                 return add((a&b)<<1,b^a);
             }
        

動(dòng)態(tài)規(guī)劃

  • lc 264 丑數(shù) 三指針:

    •     public int nthUglyNumber(int n) {
              if (n == 0) return 1;
              int[] dp = new int[n];
              dp[0] = 1;
              int l_2 = 0, l_3 = 0, l_5 = 0;
              for (int i = 1; i < n; i++) {
                  dp[i] = Math.min(dp[l_2] * 2, Math.min(dp[l_3] * 3, dp[l_5] * 5));
                  if (dp[i] == dp[l_2] * 2) l_2++;
                  if (dp[i] == dp[l_3] * 3) l_3++;
                  if (dp[i] == dp[l_5] * 5) l_5++;
              }
              return dp[n - 1];
          }
      
  • lc 309 最佳買賣股票世紀(jì)含冷凍期:

    • # sold rest hold 分別表示在該price 所持有的收益
      class Solution:
          def maxProfit(self, prices: List[int]) -> int:
              sold=0
              rest=0
              hold=-2147383648
              for price in prices:
                  pre_sold=sold
                  # 今天賣出的的收益
                  sold=hold+price
                  # 當(dāng)天是否買入,前一天的持有與之前的冷凍期收益減掉price
                  hold = max(hold, rest - price);
                  #當(dāng)天冷凍,取之前的冷凍的那天值和前一天pre_sold的比較值,保證了冷凍一定是在上次銷售之后
                  rest = max(rest, pre_sold);
              
              return max(sold,rest)
      
  • lc123 最佳買賣股票,次數(shù)限制:

       public int maxProfit(int[] prices) {
         if (prices == null || prices.length < 2) return 0;
         int[][][] dp = new int[prices.length+1][3][2];
         //base case
         for (int i = 0; i < 3; i++) {
             dp[0][i][0] = 0;
             dp[0][i][1] = Integer.MIN_VALUE;
         }
         for (int i = 1; i <= prices.length; i++) {
             for (int j = 1; j < 3; j++) {
                 dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i - 1][j][1] + prices[i-1]);
                 dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i - 1][j-1][0] - prices[i-1]);
             }
         }
         return dp[prices.length][2][0];
     }
    
  • lc309 股票買賣,含冷凍期:

        public int maxProfit(int[] prices) {
          if(prices==null||prices.length==0) return 0;
          int[][] dp = new int[prices.length][2];
          dp[0][0] = 0;
          dp[0][1] = -prices[0];
          for (int i = 1; i < prices.length; i++) {
              if (i == 1) dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
                                                                                //-2表示相鄰那天不能交易
              else dp[i][1] = Math.max(dp[i - 1][1], dp[i - 2][0] - prices[i]);
              dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
          }
          return dp[prices.length - 1][0];
      }
    
  • 迭代實(shí)現(xiàn)中序遍歷:

    • public List<Integer> inorderTraversal(TreeNode root) {
          List<Integer> res = new ArrayList<>();
          Stack<TreeNode> stack = new Stack<>();
          while (root != null || !stack.isEmpty()) {
              if (root != null) {
                  stack.push(root);
                  root = root.left;
              } else {
                  root = stack.pop();
                  res.add(root.val);
                  root = root.right;
              }
          }
          return res;
      }
      
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,185評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,446評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,951評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,189評(píng)論 0 287
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,718評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,800評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,420評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,755評(píng)論 2 371

推薦閱讀更多精彩內(nèi)容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,041評(píng)論 0 2
  • 回溯算法 回溯法:也稱為試探法,它并不考慮問題規(guī)模的大小,而是從問題的最明顯的最小規(guī)模開始逐步求解出可能的答案,并...
    fredal閱讀 13,703評(píng)論 0 89
  • 在C語言中,五種基本數(shù)據(jù)類型存儲(chǔ)空間長(zhǎng)度的排列順序是: A)char B)char=int<=float C)ch...
    夏天再來閱讀 3,371評(píng)論 0 2
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,715評(píng)論 0 3
  • 六的哥哥被騙子騙了7w元。 把他接到杭州后,還在和我們說你們不懂,我這是投資理財(cái)。 怒其不爭(zhēng)的同時(shí),痛恨和詛咒可惡...
    天田西西閱讀 211評(píng)論 0 0