Leetcode CookBook算法 算法集合的网站
https://leetcode.cn/leetbook/read/leetcode-cookbook
数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public int [] twoSum(int [] nums, int target) { int [] result = new int [2 ]; for (int i = 0 ; i < nums.length; i++) { boolean isHaveResult = false ; for (int j = 0 ; j < nums.length; j++) { if (i == j) { continue ; } if (nums[i] + nums[j] == target) { isHaveResult = true ; result[0 ] = i; result[1 ] = j; } } if (isHaveResult) { break ; } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public int [] twoSum(int [] nums, int target) { HashMap<Integer, Integer> map = new HashMap <>(); int [] result = new int [2 ]; for (int i = 0 ; i < nums.length; i++) { if (map.containsKey(target - nums[i])) { result[0 ] = i; result[1 ] = map.get(target - nums[i]); break ; } map.put(nums[i], i); } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public double findMedianSortedArrays (int [] nums1, int [] nums2) { int [] nums = new int [nums1.length + nums2.length]; int i = 0 , j = 0 , k = 0 ; while (i < nums1.length && j < nums2.length) { if (nums1[i] <= nums2[j]) { nums[k++] = nums1[i++]; } else { nums[k++] = nums2[j++]; } } while (i < nums1.length) { nums[k++] = nums1[i++]; } while (j < nums2.length) { nums[k++] = nums2[j++]; } if (nums.length % 2 == 0 ) { return ((double ) (nums[nums.length / 2 ] + nums[(nums.length - 1 ) / 2 ])) / 2 ; } else { return (double ) (nums[nums.length / 2 ]); } } }
优化写法,有空再看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public int maxArea (int [] height) { int l = 0 , r = height.length - 1 , result = 0 ; while (l < r) { result = Math.max(Math.min(height[l], height[r]) * (r - l), result); if (height[l] < height[r]) { l++; } else { r--; } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class Solution { public List<List<Integer>> threeSum (int [] nums) { Arrays.sort(nums); List<List<Integer>> result = new ArrayList <>(); for (int i = 0 ; i < nums.length; i++) { if (nums[i] > 0 ) { break ; } if (i != 0 && nums[i] == nums[i - 1 ]) { continue ; } int l = i + 1 , r = nums.length - 1 ; while (l < r) { int temp = nums[i] + nums[l] + nums[r]; if (temp < 0 ) { l++; } else if (temp > 0 ) { r--; } else { result.add(Arrays.asList(nums[i], nums[l], nums[r])); l++; while (l < r && nums[l] == nums[l - 1 ]) { l++; } r--; } } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution { public int threeSumClosest (int [] nums, int target) { int result = Integer.MAX_VALUE; int lastTemp = Math.abs(result - target); Arrays.sort(nums); for (int i = 0 ; i < nums.length; i++) { if (i > 0 && nums[i] == nums[i - 1 ]) { continue ; } int l = i + 1 , r = nums.length - 1 ; while (l < r) { int sum = nums[i] + nums[l] + nums[r]; if (sum == target) { return target; } int temp = Math.abs(sum - target); if (temp < lastTemp) { result = sum; lastTemp = temp; } if (sum > target) { r--; } else { l++; } } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 class Solution { public List<List<Integer>> fourSum (int [] nums, int target) { List<List<Integer>> result = new ArrayList <>(); Arrays.sort(nums); for (int i = 0 ; i < nums.length; i++) { if (nums[i] >= 0 && nums[i] > target) { break ; } if (i > 0 && nums[i] == nums[i - 1 ]) { continue ; } for (int j = i + 1 ; j < nums.length; j++) { if (nums[i] + nums[j] >= 0 && nums[i] + nums[j] > target) { break ; } if (j > i + 1 && nums[j] == nums[j - 1 ]) { continue ; } int left = j + 1 ; int right = nums.length - 1 ; while (left < right) { long sum = (long ) nums[i] + nums[j] + nums[left] + nums[right]; if (sum < target) { left++; } else if (sum > target) { right--; } else { result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right])); left++; right--; while (left < right && nums[left] == nums[left - 1 ]) { left++; } while (left < right && nums[right] == nums[right + 1 ]) { right--; } } } } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public int removeDuplicates (int [] nums) { int cur = 0 , i = 0 , len = nums.length; while (i < nums.length) { nums[cur++] = nums[i++]; while (i < len && nums[i] == nums[i - 1 ]) { i++; } } return cur; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public int removeElement (int [] nums, int val) { int cur = 0 , i = 0 , len = nums.length; while (i < len) { if (nums[i] == val) { i++; continue ; } nums[cur++] = nums[i++]; } return cur; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public int searchInsert (int [] nums, int target) { int left = 0 , right = nums.length - 1 ; while (left <= right) { int mid = (left + right) >> 1 ; if (nums[mid] > target) { right = mid - 1 ; } else if (nums[mid] < target) { left = mid + 1 ; } else { return mid; } } return left; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public List<List<Integer>> combinationSum (int [] candidates, int target) { Arrays.sort(candidates); List<List<Integer>> result = new ArrayList <>(); dfs(result, new ArrayList <>(), candidates, target, 0 ); return result; } public void dfs (List<List<Integer>> result, List<Integer> temp, int [] candidates, int balance, int index) { if (balance == 0 ) { result.add(new ArrayList <>(temp)); return ; } for (int i = index; i < candidates.length; i++) { if (candidates[i] > balance) { break ; } temp.add(candidates[i]); dfs(result, temp, candidates, balance - candidates[i], i); temp.remove(temp.size() - 1 ); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution { public List<List<Integer>> combinationSum2 (int [] candidates, int target) { Arrays.sort(candidates); List<List<Integer>> result = new ArrayList <>(); dfs(result, new ArrayList <>(), candidates, new boolean [candidates.length], 0 , target); return result; } public void dfs (List<List<Integer>> result, List<Integer> temp, int [] candidates, boolean [] isVisted, int index, int balance) { if (balance == 0 ) { result.add(new ArrayList <>(temp)); return ; } for (int i = index; i < candidates.length; i++) { if (candidates[i] > balance) { break ; } if (i > 0 && candidates[i - 1 ] == candidates[i] && !isVisted[i - 1 ]) { continue ; } temp.add(candidates[i]); isVisted[i] = true ; dfs(result, temp, candidates, isVisted, i + 1 , balance - candidates[i]); temp.remove(temp.size() - 1 ); isVisted[i] = false ; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public void rotate (int [][] matrix) { int n = matrix.length - 1 ; for (int i = 0 ; i < n; i++) { for (int j = i + 1 ; j <= n; j++) { int temp = matrix[i][j]; matrix[i][j] = matrix[j][i]; matrix[j][i] = temp; } } for (int i = 0 ; i <= n; i++) { for (int j = 0 ; j < (n + 1 ) / 2 ; j++) { int temp = matrix[i][j]; matrix[i][j] = matrix[i][n - j]; matrix[i][n - j] = temp; } } } }
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public int maxSubArray (int [] nums) { int result = nums[0 ], temp = nums[0 ]; for (int i = 1 ; i < nums.length; i++) { temp = Math.max(nums[i], temp + nums[i]); result = Math.max(result, temp); } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Solution { public List<Integer> spiralOrder (int [][] matrix) { List<Integer> result = new ArrayList <>(); int top = 0 , bottom = matrix.length - 1 , left = 0 , right = matrix[0 ].length - 1 ; while (top <= bottom && left <= right) { for (int j = left; j <= right; j++) { result.add(matrix[top][j]); } top++; for (int i = top; i <= bottom; i++) { result.add(matrix[i][right]); } right--; if (top <= bottom) { for (int j = right; j >= left; j--) { result.add(matrix[bottom][j]); } bottom--; } if (left <= right) { for (int i = bottom; i >= top; i--) { result.add(matrix[i][left]); } left++; } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public boolean canJump (int [] nums) { int balance = 0 ; for (int i = 0 ; i < nums.length; i++) { if (i <= balance) { balance = Math.max(balance, i + nums[i]); if (balance >= nums.length - 1 ) { return true ; } } } return false ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution { public int [][] generateMatrix(int n) { int [][] result = new int [n][n]; int temp = 1 , top = 0 , bottom = n - 1 , left = 0 , right = n - 1 ; while (top <= bottom && left <= right) { for (int j = left; j <= right; j++) { result[top][j] = temp; temp++; } top++; for (int i = top; i <= bottom; i++) { result[i][right] = temp; temp++; } right--; if (top <= bottom) { for (int j = right; j >= left; j--) { result[bottom][j] = temp; temp++; } bottom--; } if (left <= right) { for (int i = bottom; i >= top; i--) { result[i][left] = temp; temp++; } left++; } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public int uniquePaths (int m, int n) { int [] dp = new int [n]; Arrays.fill(dp, 1 ); for (int i = 1 ; i < m; i++) { for (int j = 1 ; j < n; j++) { dp[j] += dp[j - 1 ]; } } return dp[n - 1 ]; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public int uniquePathsWithObstacles (int [][] obstacleGrid) { int m = obstacleGrid.length, n = obstacleGrid[0 ].length; int [][] dp = new int [m][n]; dp[0 ][0 ] = obstacleGrid[0 ][0 ] == 1 ? 0 : 1 ; for (int j = 1 ; j < n; j++) { dp[0 ][j] = obstacleGrid[0 ][j] == 1 ? 0 : dp[0 ][j - 1 ]; } for (int i = 1 ; i < m; i++) { dp[i][0 ] = obstacleGrid[i][0 ] == 1 ? 0 : dp[i - 1 ][0 ]; } for (int i = 1 ; i < m; i++) { for (int j = 1 ; j < n; j++) { dp[i][j] = obstacleGrid[i][j] == 1 ? 0 : dp[i - 1 ][j] + dp[i][j - 1 ]; } } return dp[m - 1 ][n - 1 ]; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public int minPathSum (int [][] grid) { int [] dp = new int [grid[0 ].length]; dp[0 ] = grid[0 ][0 ]; for (int j = 1 ; j < grid[0 ].length; j++) { dp[j] = dp[j - 1 ] + grid[0 ][j]; } for (int i = 1 ; i < grid.length; i++) { for (int j = 0 ; j < grid[0 ].length; j++) { if (j != 0 ) { dp[j] = Math.min(dp[j], dp[j - 1 ]) + grid[i][j]; } else { dp[j] += grid[i][j]; } } } return dp[grid[0 ].length - 1 ]; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public int [] plusOne(int [] digits) { int carry = 1 ; int len = digits.length; for (int i = len - 1 ; i >= 0 ; i--) { digits[i] += carry; carry = digits[i] / 10 ; digits[i] = digits[i] % 10 ; } if (carry == 0 ) { return digits; } else { int [] result = new int [len + 1 ]; result[0 ] = carry; for (int i = 0 ; i < len; i++) { result[i + 1 ] = digits[i]; } return result; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public boolean searchMatrix (int [][] matrix, int target) { int m = matrix.length, n = matrix[0 ].length, len = m * n, left = 0 , right = len - 1 ; while (left <= right) { int mid = (left + right) >> 1 ; int i = mid / n, j = mid % n; if (matrix[i][j] > target) { right = mid - 1 ; } else if (matrix[i][j] < target) { left = mid + 1 ; } else { return true ; } } return false ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public List<List<Integer>> subsets (int [] nums) { List<List<Integer>> result = new ArrayList <>(); dfs(result, new ArrayList <>(), nums, 0 ); return result; } public void dfs (List<List<Integer>> result, List<Integer> temp, int [] nums, int index) { result.add(new ArrayList <>(temp)); for (int i = index; i < nums.length; i++) { temp.add(nums[i]); dfs(result, temp, nums, i + 1 ); temp.remove(temp.size() - 1 ); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class Solution { public boolean exist (char [][] board, String word) { if (board.length * board[0 ].length < word.length()) { return false ; } int [][] dirs = new int [][] { { 1 , 0 }, { -1 , 0 }, { 0 , -1 }, { 0 , 1 } }; StringBuilder builder = new StringBuilder (); boolean [][] isVisited = new boolean [board.length][board[0 ].length]; for (int i = 0 ; i < board.length; i++) { for (int j = 0 ; j < board[0 ].length; j++) { if (board[i][j] == word.charAt(0 )) { builder.append(board[i][j]); isVisited[i][j] = true ; if (dfs(board, word, dirs, builder, isVisited, i, j)) { return true ; } builder.deleteCharAt(builder.length() - 1 ); isVisited[i][j] = false ; } } } return false ; } public boolean dfs (char [][] board, String word, int [][] dirs, StringBuilder builder, boolean [][] isVisited, int i, int j) { if (builder.length() == word.length()) { return word.equals(builder.toString()); } boolean result = false ; for (int [] dir : dirs) { int newI = i + dir[0 ], newJ = j + dir[1 ]; if (newI >= 0 && newI < board.length && newJ >= 0 && newJ < board[0 ].length && !isVisited[newI][newJ] && board[newI][newJ] == word.charAt(builder.length())) { isVisited[newI][newJ] = true ; builder.append(board[newI][newJ]); result = result || dfs(board, word, dirs, builder, isVisited, newI, newJ); if (result) { return true ; } isVisited[newI][newJ] = false ; builder.deleteCharAt(builder.length() - 1 ); } } return result; } }
时间花费很高,后面看看怎么优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution { public static int [][] dirs = new int [][] { { -1 , 0 }, { 1 , 0 }, { 0 , -1 }, { 0 , 1 } }; public boolean exist (char [][] board, String word) { boolean [][] isVisited = new boolean [board.length][board[0 ].length]; for (int i = 0 ; i < board.length; i++) { for (int j = 0 ; j < board[0 ].length; j++) { if (dfs(board, word, isVisited, 0 , i, j)) { return true ; } } } return false ; } public boolean dfs (char [][] board, String word, boolean [][] isVisited, int index, int i, int j) { if (index == word.length() - 1 ) { return board[i][j] == word.charAt(word.length() - 1 ); } if (board[i][j] == word.charAt(index)) { isVisited[i][j] = true ; for (int [] dir : dirs) { int newI = i + dir[0 ], newJ = j + dir[1 ]; if (newI >= 0 && newI < board.length && newJ >= 0 && newJ < board[0 ].length && !isVisited[newI][newJ]) { if (dfs(board, word, isVisited, index + 1 , newI, newJ)) { return true ; } } } isVisited[i][j] = false ; } return false ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public int removeDuplicates (int [] nums) { int count = 1 , cur = 1 ; for (int i = 1 ; i < nums.length; i++) { if (nums[i] == nums[i - 1 ]) { count++; if (count <= 2 ) { nums[cur++] = nums[i]; } } else { count = 1 ; nums[cur++] = nums[i]; } } return cur; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public void merge (int [] nums1, int m, int [] nums2, int n) { int [] temp = new int [m + n]; int i = 0 , j = 0 , cur = 0 ; while (i < m && j < n) { if (nums1[i] <= nums2[j]) { temp[cur++] = nums1[i++]; } else { temp[cur++] = nums2[j++]; } } while (i < m) { temp[cur++] = nums1[i++]; } while (j < n) { temp[cur++] = nums2[j++]; } for (i = 0 ; i < m + n; i++) { nums1[i] = temp[i]; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public void merge (int [] nums1, int m, int [] nums2, int n) { int i = m - 1 , j = n - 1 , cur = m + n - 1 ; while (i >= 0 && j >= 0 ) { if (nums1[i] >= nums2[j]) { nums1[cur--] = nums1[i--]; } else { nums1[cur--] = nums2[j--]; } } while (i >= 0 ) { nums1[cur--] = nums1[i--]; } while (j >= 0 ) { nums1[cur--] = nums2[j--]; } } }
字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution { public int strStr (String haystack, String needle) { int len = needle.length(); int [] next = new int [len]; next[0 ] = 0 ; int j = 0 ; for (int i = 1 ; i < len; i++) { while (j > 0 && needle.charAt(i) != needle.charAt(j)) { j = next[j - 1 ]; } if (needle.charAt(i) == needle.charAt(j)) { j++; } next[i] = j; } int p = 0 ; for (int s = 0 ; s < haystack.length(); s++) { while (p > 0 && needle.charAt(p) != haystack.charAt(s)) { p = next[p - 1 ]; } if (needle.charAt(p) == haystack.charAt(s)) { p++; } if (p == len) { return s - len + 1 ; } } return -1 ; } }
暴力解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public boolean repeatedSubstringPattern (String s) { int len = s.length(); for (int i = 1 ; i * 2 <= len; i++) { if (len % i == 0 ) { boolean isCurrent = true ; for (int j = i; j < len; j++) { if (s.charAt(j) != s.charAt(j - i)) { isCurrent = false ; break ; } } if (isCurrent) { return true ; } } } return false ; } }
移动匹配(字符串匹配)
借助系统函数,不用系统函数就去掉头尾然后判断s是否在s+s中,因为不去掉搜索会搜到s+s最开始的s,没什么意义
1 2 3 4 5 6 class Solution { public boolean repeatedSubstringPattern (String s) { return (s + s).indexOf(s, 1 ) != s.length(); } }
KMP
前缀表:当出现两个位置的字符不相等的时候,需要找到当前不相等位置的前面的所有字符的后缀的相等前缀的后一个字符进行匹配,那么就要知道某个字符串的最长相等前后缀(前后缀可以有多个)
前缀:包含首字母,不包含尾字母的所有子串
后缀:包含尾字母,不包含首字母的所有子串
最长相等前后缀:aabaa,最长就是2呗,aa和aa相等(长度刚好就是下次匹配的下标,很巧妙),前缀表在最后个a位置记录2,从2位置继续匹配(这里前缀表不进行任何偏移)
next数组、prefix数组:其实存放的都是前缀表,但代码实现上可能有些区别罢了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public boolean repeatedSubstringPattern (String s) { int len = s.length(); int [] next = new int [len]; int j = 0 ; next[0 ] = 0 ; for (int i = 1 ; i < len; i++) { while (j > 0 && s.charAt(i) != s.charAt(j)) { j = next[j - 1 ]; } if (s.charAt(i) == s.charAt(j)) { j++; } next[i] = j; } if (next[len - 1 ] > 0 && len % (len - next[len - 1 ]) == 0 ) { return true ; } else { return false ; } } }
为什么需要减去,减的部分可以按下面这个理解
链表 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution { public ListNode addTwoNumbers (ListNode l1, ListNode l2) { int carry = 0 ; ListNode head = new ListNode (), cur = head; while (l1 != null && l2 != null ) { int now = l1.val + l2.val + carry; carry = now / 10 ; now %= 10 ; l1.val = now; cur.next = l1; cur = l1; l1 = l1.next; l2 = l2.next; } while (l1 != null ) { int now = l1.val + carry; carry = now / 10 ; now %= 10 ; l1.val = now; cur.next = l1; cur = l1; l1 = l1.next; } while (l2 != null ) { int now = l2.val + carry; carry = now / 10 ; now %= 10 ; l2.val = now; cur.next = l2; cur = l2; l2 = l2.next; } if (carry != 0 ) { ListNode node = new ListNode (carry); cur.next = node; } return head.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public ListNode removeNthFromEnd (ListNode head, int n) { ListNode newHead = new ListNode (0 , head); ListNode cur = newHead, delete = newHead; for (int i = 0 ; i <= n; i++) { cur = cur.next; } while (cur != null ) { cur = cur.next; delete = delete.next; } ListNode next = delete.next; delete.next = next.next; next.next = null ; return newHead.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public ListNode mergeTwoLists (ListNode list1, ListNode list2) { ListNode head = new ListNode (), result = head; while (list1 != null && list2 != null ) { if (list1.val <= list2.val) { head.next = list1; head = list1; list1 = list1.next; } else { head.next = list2; head = list2; list2 = list2.next; } } if (list1 != null ) { head.next = list1; } if (list2 != null ) { head.next = list2; } return result.next; } }
一开始暴力的时间复杂度很高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution { public ListNode mergeKLists (ListNode[] lists) { ListNode cur = new ListNode (), head = cur; while (true ) { int min = -1 ; for (int i = 0 ; i < lists.length; i++) { ListNode node = lists[i]; if (node == null ) { continue ; } if (min == -1 ) { min = i; } else { if (node.val < lists[min].val) { min = i; } } } if (min == -1 ) { cur.next = null ; break ; } cur.next = lists[min]; cur = lists[min]; lists[min] = lists[min].next; } return head.next; } }
优先队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public ListNode mergeKLists (ListNode[] lists) { PriorityQueue<Integer> queue = new PriorityQueue <>( (Integer node1, Integer node2) -> { return lists[node1].val - lists[node2].val; }); for (int i = 0 ; i < lists.length; i++) { if (lists[i] != null ) { queue.offer(i); } } ListNode cur = new ListNode (), head = cur; while (!queue.isEmpty()) { int min = queue.poll(); ListNode minNode = lists[min]; cur.next = minNode; cur = minNode; lists[min] = minNode.next; if (lists[min] != null ) { queue.offer(min); } } return head.next; } }
归并两两合并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution { public ListNode mergeKLists (ListNode[] lists) { return merge(lists, 0 , lists.length - 1 ); } public ListNode merge (ListNode[] lists, int l, int r) { if (l == r) { return lists[l]; } if (l > r) { return null ; } int mid = (l + r) >> 1 ; return mergeTwoLists( merge(lists, l, mid), merge(lists, mid + 1 , r)); } public ListNode mergeTwoLists (ListNode list1, ListNode list2) { ListNode head = new ListNode (), result = head; while (list1 != null && list2 != null ) { if (list1.val <= list2.val) { head.next = list1; head = list1; list1 = list1.next; } else { head.next = list2; head = list2; list2 = list2.next; } } if (list1 != null ) { head.next = list1; } if (list2 != null ) { head.next = list2; } return result.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public ListNode swapPairs (ListNode head) { ListNode cur = new ListNode (), result = cur; while (head != null ) { ListNode next = head.next; if (next != null ) { ListNode nextUp = next.next; cur.next = next; next.next = head; head.next = nextUp; cur = head; head = nextUp; } else { cur.next = head; head = null ; } } return result.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution { public ListNode rotateRight (ListNode head, int k) { if (head == null ) { return head; } ListNode newHead = new ListNode (-1 , head); int count = 0 ; ListNode node = head, tail = head; while (node != null ) { node = node.next; if (tail.next != null ) { tail = tail.next; } count++; } int n = k % count, t = count - n; if (n == 0 ) { return newHead.next; } node = head; count = 1 ; while (count < t) { node = node.next; count++; } newHead.next = node.next; node.next = null ; tail.next = head; return newHead.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution { public ListNode deleteDuplicates (ListNode head) { if (head == null || head.next == null ) { return head; } ListNode newHead = new ListNode (), first = head, second = head.next, result = newHead; while (first != null ) { if (second == null || second.val != first.val) { newHead.next = first; newHead = newHead.next; } else { while (second != null && second.val == first.val) { second = second.next; } } if (second == null ) { break ; } else { first = second; second = second.next; } } newHead.next = null ; return result.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public ListNode deleteDuplicates (ListNode head) { if (head == null || head.next == null ) { return head; } ListNode last = head, cur = head.next; while (cur != null ) { if (cur.val == last.val) { cur = cur.next; continue ; } last.next = cur; cur = cur.next; last = last.next; } last.next = cur; return head; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public ListNode partition (ListNode head, int x) { ListNode smallHead = new ListNode (), bigHead = new ListNode (), smallOriginHead = smallHead, bigOriginHead = bigHead; while (head != null ) { if (head.val < x) { smallHead.next = head; smallHead = smallHead.next; } else { bigHead.next = head; bigHead = bigHead.next; } ListNode next = head.next; head.next = null ; head = next; } if (smallOriginHead.next == null ) { return bigOriginHead.next; } else { smallHead.next = bigOriginHead.next; return smallOriginHead.next; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public ListNode reverseBetween (ListNode head, int left, int right) { ListNode newHead = new ListNode (-1 , head), cur = head, last = newHead; int index = 1 ; while (index < left) { last = cur; cur = cur.next; index++; } ListNode leftNode = cur, leftLast = last; while (index < right) { ListNode next = cur.next; cur.next = last; last = cur; cur = next; index++; } ListNode rightNext = cur.next; cur.next = last; leftLast.next = cur; leftNode.next = rightNext; return newHead.next; } }
不加头节点可以看下面的一题,一样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Solution { public boolean hasCycle (ListNode head) { ListNode newHead = new ListNode (-1 ), fast = newHead, slow = newHead; newHead.next = head; while (fast.next != null && fast.next.next != null ) { fast = fast.next.next; slow = slow.next; if (fast == slow) { return true ; } } return false ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class Solution { public ListNode detectCycle (ListNode head) { ListNode temp = isHaveCircleInLinkedList(head); if (temp == null ) { return null ; } temp = temp.next; ListNode cur = head; while (cur != temp) { cur = cur.next; temp = temp.next; } return cur; } public ListNode isHaveCircleInLinkedList (ListNode head) { if (head == null || head.next == null ) { return null ; } ListNode fast = head.next, slow = head; while (fast.next != null && fast.next.next != null ) { fast = fast.next.next; slow = slow.next; if (fast == slow) { return fast; } } return null ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 class Solution { public void reorderList (ListNode head) { int count = 0 ; ListNode cur = head; while (cur != null ) { count++; cur = cur.next; } if (count <= 2 ) { return ; } count = count >> 1 ; cur = head; while (count != 0 ) { count--; cur = cur.next; } ListNode reverseNode = cur.next; cur.next = null ; reverseNode = reverseList(reverseNode); cur = head; head = head.next; while (reverseNode != null ) { cur.next = reverseNode; ListNode next = reverseNode.next; reverseNode.next = head; cur = head; if (head != null ) { head = head.next; } reverseNode = next; } } public ListNode reverseList (ListNode head) { ListNode last = null ; while (head != null ) { ListNode next = head.next; head.next = last; last = head; head = next; } return last; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 class Solution { public ListNode sortList (ListNode head) { int count = 0 ; ListNode temp = head; while (temp != null ) { temp = temp.next; count++; } return mergeSort(head, 1 , count); } public ListNode mergeSort (ListNode node, int left, int right) { if (left < right) { int mid = (left + right) >> 1 ; ListNode leftNode = node; for (int i = left; i < mid; i++) { leftNode = leftNode.next; } ListNode rightNode = leftNode.next; leftNode.next = null ; leftNode = mergeSort(node, left, mid); rightNode = mergeSort(rightNode, mid + 1 , right); return merge(leftNode, rightNode); } return node; } public ListNode merge (ListNode left, ListNode right) { if (left == null ) { return right; } ListNode newHead = new ListNode (), cur = newHead; while (left != null && right != null ) { if (left.val < right.val) { cur.next = left; cur = left; ListNode next = left.next; left.next = null ; left = next; } else { cur.next = right; cur = right; ListNode next = right.next; right.next = null ; right = next; } } if (left != null ) { cur.next = left; } else { cur.next = right; } return newHead.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Solution { public ListNode getIntersectionNode (ListNode headA, ListNode headB) { ListNode node1 = headA, node2 = headB; while (node1 != null || node2 != null ) { if (node1 == node2) { return node1; } if (node1 == null ) { node1 = headB; } else { node1 = node1.next; } if (node2 == null ) { node2 = headA; } else { node2 = node2.next; } } return null ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution { public ListNode removeElements (ListNode head, int val) { ListNode newHead, cur = head; while (cur != null && cur.val == val) { ListNode next = cur.next; cur.next = null ; cur.next = next; cur = next; } if (cur != null ) { newHead = cur; } else { return null ; } while (cur.next != null ) { if (cur.next.val == val) { ListNode next = cur.next; cur.next = next.next; next.next = null ; } else { cur = cur.next; } } return newHead; } }
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public ListNode reverseList (ListNode head) { ListNode last = null ; while (head != null ) { ListNode next = head.next; head.next = last; last = head; head = next; } return last; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 class Solution { public boolean isPalindrome (ListNode head) { int count = 0 ; ListNode cur = head; while (cur != null ) { count++; cur = cur.next; } if (count <= 1 ) { return true ; } count = count >> 1 ; cur = head; int temp = 1 ; while (temp < count) { cur = cur.next; temp++; } ListNode next = cur.next; cur.next = null ; ListNode tail = reverse(next); while (head != null ) { if (head.val != tail.val) { return false ; } head = head.next; tail = tail.next; } return true ; } public ListNode reverse (ListNode head) { ListNode last = null ; while (head != null ) { ListNode next = head.next; head.next = last; last = head; head = next; } return last; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public void deleteNode (ListNode node) { ListNode last = null ; while (node.next != null ) { node.val = node.next.val; last = node; node = node.next; } if (last != null ) { last.next = null ; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public ListNode oddEvenList (ListNode head) { ListNode odd = new ListNode (), even = new ListNode (), curOdd = odd, curEven = even; int cur = 0 ; while (head != null ) { cur++; if (cur % 2 == 0 ) { curEven.next = head; curEven = head; } else { curOdd.next = head; curOdd = head; } ListNode next = head.next; head.next = null ; head = next; } if (odd.next == null ) { return odd.next; } else { curOdd.next = even.next; return odd.next; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class Solution { public ListNode addTwoNumbers (ListNode l1, ListNode l2) { ListNode head1 = reverse(l1), head2 = reverse(l2); int last = 0 ; ListNode cur1 = head1, cur2 = head2, lastNode = head1; while (cur1 != null ) { if (cur2 == null ) { cur1.val += last; } else { cur1.val = cur1.val + last + cur2.val; cur2 = cur2.next; } last = cur1.val / 10 ; cur1.val %= 10 ; lastNode = cur1; cur1 = cur1.next; } while (cur2 != null ) { cur2.val += last; last = cur2.val / 10 ; cur2.val %= 10 ; lastNode.next = cur2; lastNode = cur2; cur2 = cur2.next; } if (last != 0 ) { lastNode.next = new ListNode (last); } return reverse(head1); } public ListNode reverse (ListNode head) { ListNode last = null ; while (head != null ) { ListNode next = head.next; head.next = last; last = head; head = next; } return last; } }
不翻转链表进阶版本,递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 class Solution { public ListNode addTwoNumbers (ListNode l1, ListNode l2) { int len1 = getLinkedListLength(l1), len2 = getLinkedListLength(l2); ListNode longNode, sortNode; if (len1 >= len2) { longNode = l1; sortNode = l2; } else { longNode = l2; sortNode = l1; } int balance = Math.abs(len1 - len2); if (balance == 0 ) { int last = dfs(longNode, sortNode); if (last == 0 ) { return longNode; } else { ListNode node = new ListNode (last); node.next = longNode; return node; } } else { int curLen = 1 ; ListNode longCur = longNode; while (curLen < balance) { longCur = longCur.next; curLen++; } ListNode next = longCur.next; int last = dfs(next, sortNode); if (last == 0 ) { return longNode; } else { ListNode node = new ListNode (last); longCur.next = null ; ListNode result; if (len1 >= len2) { result = addTwoNumbers(l1, node); } else { result = addTwoNumbers(l2, node); } longCur.next = next; return result; } } } public int dfs (ListNode node1, ListNode node2) { if (node1 == null && node2 == null ) { return 0 ; } int last = dfs(node1.next, node2.next); int sum = last + node1.val + node2.val; node1.val = sum % 10 ; return sum / 10 ; } public int getLinkedListLength (ListNode head) { int length = 0 ; while (head != null ) { length++; head = head.next; } return length; } }
注意边界条件
看了一些别人简洁的版本,确实保留一个虚拟头节点代码会简洁很多,很多判断都省了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 class MyLinkedList { private int len; private Node head; private Node tail; private class Node { public int val; public Node next; } public MyLinkedList () { len = 0 ; head = null ; tail = null ; } public int get (int index) { if (index < 0 || index >= len) { return -1 ; } int cur = 0 ; Node node = head; while (cur < index) { cur++; node = node.next; } return node.val; } public void addAtHead (int val) { Node node = new Node (); node.val = val; len++; if (len == 1 ) { head = node; tail = node; } else { node.next = head; head = node; } } public void addAtTail (int val) { Node node = new Node (); node.val = val; len++; if (len == 1 ) { head = node; tail = node; } else { tail.next = node; tail = node; } } public void addAtIndex (int index, int val) { if (index < 0 || index > len) { return ; } if (index == 0 ) { addAtHead(val); } else if (index == len) { addAtTail(val); } else { Node cur = head, last = head; int curIndex = 0 ; while (curIndex < index) { curIndex++; last = cur; cur = cur.next; } Node node = new Node (); node.val = val; last.next = node; node.next = cur; len++; } } public void deleteAtIndex (int index) { if (index < 0 || index >= len) { return ; } len--; if (index == 0 ) { head = head.next; if (len == 0 ) { tail = null ; } } else { Node last = head, cur = head; int curIndex = 0 ; while (curIndex < index) { curIndex++; last = cur; cur = cur.next; } if (cur == tail) { tail = last; } last.next = cur.next; cur.next = null ; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 class Solution { public ListNode[] splitListToParts(ListNode head, int k) { int len = getLinkedListLength(head); int averge = len / k; int more = len % k; ListNode[] result = new ListNode [k]; ListNode cur = head; for (int i = 0 ; i < k; i++) { int count; if (i + 1 <= more) { count = averge + 1 ; } else { count = averge; } if (count == 0 ) { result[i] = null ; } else { ListNode temp = cur; for (int t = 1 ; t < count; t++) { cur = cur.next; } ListNode next = cur.next; cur.next = null ; cur = next; result[i] = temp; } } return result; } public int getLinkedListLength (ListNode head) { int len = 0 ; while (head != null ) { len++; head = head.next; } return len; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public int numComponents (ListNode head, int [] nums) { HashSet<Integer> hash = new HashSet <>(); for (int i : nums) { hash.add(i); } int result = 0 ; boolean isInSet = false ; while (head != null ) { if (hash.contains(head.val)) { if (!isInSet) { isInSet = true ; result++; } } else { isInSet = false ; } head = head.next; } return result; } }
题目说了一半要最后一个,手动模拟一些可以发现快慢指针合适,快指针如果不能到next的next,next为null,就说明出结果了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public ListNode middleNode (ListNode head) { ListNode fast = head, slow = head; while (fast != null ) { if (fast.next == null ) { break ; } fast = fast.next.next; slow = slow.next; } return slow; } }
暂时只想到O(n^2)的解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution { public int [] nextLargerNodes(ListNode head) { List<Integer> list = new ArrayList <>(); while (head != null ) { list.add(findNextLarger(head)); head = head.next; } int [] result = new int [list.size()]; for (int i = 0 ; i < list.size(); i++) { result[i] = list.get(i); } return result; } public int findNextLarger (ListNode head) { if (head == null ) { return 0 ; } ListNode cur = head.next; while (cur != null ) { if (cur.val > head.val) { return cur.val; } cur = cur.next; } return 0 ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public int getDecimalValue (ListNode head) { int result = 0 , cur = 1 ; ListNode node = reverse(head); while (node != null ) { result += (cur * node.val); node = node.next; cur *= 2 ; } return result; } public ListNode reverse (ListNode head) { ListNode last = null ; while (head != null ) { ListNode next = head.next; head.next = last; last = head; head = next; } return last; } }
栈和队列 可以if else优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution { public boolean isValid (String s) { LinkedList<Character> stack = new LinkedList <>(); for (int i = 0 ; i < s.length(); i++) { char c = s.charAt(i); switch (c) { case '(' : stack.push(c); break ; case '[' : stack.push(c); break ; case '{' : stack.push(c); break ; case ')' : if (stack.isEmpty() || stack.pop() != '(' ) { return false ; } break ; case ']' : if (stack.isEmpty() || stack.pop() != '[' ) { return false ; } break ; case '}' : if (stack.isEmpty() || stack.pop() != '{' ) { return false ; } break ; default : return false ; } } return stack.isEmpty(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class Solution { public String simplifyPath (String path) { ArrayDeque<String> deque = new ArrayDeque <>(); int len = path.length(); int i = 0 ; while (i < len) { if (path.charAt(i) == '/' ) { int j = i + 1 ; while (j < len && path.charAt(j) == '/' ) { j++; } i = j; while (j < len && path.charAt(j) != '/' ) { j++; } int contentLen = j - i; if (contentLen != 0 ) { String content = path.substring(i, j); if (content.equals("." )) { } else if (content.equals(".." )) { if (!deque.isEmpty()) { deque.pollLast(); } } else { deque.offerLast(content); } } i = j; } } StringBuilder builder = new StringBuilder (); builder.append("/" ); while (!deque.isEmpty()) { builder.append(deque.pollFirst()); if (!deque.isEmpty()) { builder.append("/" ); } } return builder.toString(); } }
可以优化的,去重部分复杂了,加了循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class Solution { public String simplifyPath (String path) { ArrayDeque<String> deque = new ArrayDeque <>(); int len = path.length(); int i = 0 ; while (i < len) { if (path.charAt(i) != '/' ) { int j = i + 1 ; while (j < len && path.charAt(j) != '/' ) { j++; } String content = path.substring(i, j); if (content.equals("." )) { } else if (content.equals(".." )) { if (!deque.isEmpty()) { deque.pollLast(); } } else { deque.offerLast(content); } i = j; } else { i++; } } StringBuilder builder = new StringBuilder (); builder.append("/" ); while (!deque.isEmpty()) { builder.append(deque.pollFirst()); if (!deque.isEmpty()) { builder.append("/" ); } } return builder.toString(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public int evalRPN (String[] tokens) { Deque<Integer> deque = new ArrayDeque <>(); for (String s : tokens) { if (s.equals("+" ) || s.equals("-" ) || s.equals("*" ) || s.equals("/" )) { int second = deque.pollLast(), first = deque.pollLast(); if (s.equals("+" )) { deque.offerLast(first + second); } else if (s.equals("-" )) { deque.offerLast(first - second); } else if (s.equals("*" )) { deque.offerLast(first * second); } else { deque.offerLast(first / second); } } else { deque.offerLast(Integer.valueOf(s)); } } return deque.pollLast(); } }
下面是官方的优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution { public int evalRPN (String[] tokens) { int n = tokens.length; int [] stack = new int [(n + 1 ) / 2 ]; int index = -1 ; for (int i = 0 ; i < n; i++) { String token = tokens[i]; switch (token) { case "+" : index--; stack[index] += stack[index + 1 ]; break ; case "-" : index--; stack[index] -= stack[index + 1 ]; break ; case "*" : index--; stack[index] *= stack[index + 1 ]; break ; case "/" : index--; stack[index] /= stack[index + 1 ]; break ; default : index++; stack[index] = Integer.parseInt(token); } } return stack[index]; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class MinStack { Deque<Integer> deque; Deque<Integer> minDeque; public MinStack () { deque = new ArrayDeque <>(); minDeque = new ArrayDeque <>(); } public void push (int val) { deque.offerLast(val); if (minDeque.isEmpty() || val <= minDeque.peekLast()) { minDeque.offerLast(val); } } public void pop () { int val = deque.pollLast(); if (val == minDeque.peekLast()) { minDeque.pollLast(); } } public int top () { return deque.peekLast(); } public int getMin () { return minDeque.peekLast(); } }
官方思路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class MinStack { Deque<Integer> stack; Deque<Integer> minStack; public MinStack () { stack = new LinkedList <>(); minStack = new LinkedList <>(); minStack.push(Integer.MAX_VALUE); } public void push (int val) { stack.push(val); minStack.push(Math.min(minStack.peek(), val)); } public void pop () { stack.pop(); minStack.pop(); } public int top () { return stack.peek(); } public int getMin () { return minStack.peek(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class MyStack { Queue<Integer> queue1; Queue<Integer> queue2; public MyStack () { queue1 = new ArrayDeque <>(); queue2 = new ArrayDeque <>(); } public void push (int x) { queue2.offer(x); while (!queue1.isEmpty()) { queue2.offer(queue1.poll()); } Queue temp = queue1; queue1 = queue2; queue2 = temp; } public int pop () { return queue1.poll(); } public int top () { return queue1.peek(); } public boolean empty () { return queue1.isEmpty(); } }
一个实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class MyStack { Queue<Integer> queue; public MyStack () { queue = new ArrayDeque <>(); } public void push (int x) { int n = queue.size(); queue.offer(x); while ((n--) != 0 ) { queue.offer(queue.poll()); } } public int pop () { return queue.poll(); } public int top () { return queue.peek(); } public boolean empty () { return queue.isEmpty(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class MyQueue { Deque<Integer> stack1; Deque<Integer> stack2; public MyQueue () { stack1 = new ArrayDeque <>(); stack2 = new ArrayDeque <>(); } public void push (int x) { stack1.push(x); } public int pop () { if (stack2.isEmpty()) { while (!stack1.isEmpty()) { stack2.push(stack1.pop()); } } return stack2.pop(); } public int peek () { if (stack2.isEmpty()) { while (!stack1.isEmpty()) { stack2.push(stack1.pop()); } } return stack2.peek(); } public boolean empty () { return stack1.isEmpty() && stack2.isEmpty(); } }
树 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public List<Integer> inorderTraversal (TreeNode root) { List<Integer> result = new ArrayList <>(); LinkedList<TreeNode> stack = new LinkedList <>(); while (root != null || !stack.isEmpty()) { if (root != null ) { stack.push(root); root = root.left; } else { root = stack.poll(); result.add(root.val); root = root.right; } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { TreeNode last = null ; public boolean isValidBST (TreeNode root) { if (root == null ) { return true ; } boolean isLeftLegal = isValidBST(root.left); if (!isLeftLegal) { return false ; } if (last != null && root.val <= last.val) { return false ; } last = root; return isValidBST(root.right); } }
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public boolean isSameTree (TreeNode p, TreeNode q) { if (p == null && q == null ) { return true ; } else if ((p == null && q != null ) || (p != null && q == null )) { return false ; } else { return p.val == q.val && isSameTree(p.left, q.left) && isSameTree(p.right, q.right); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public boolean isSymmetric (TreeNode root) { return root == null || isLegal(root.left, root.right); } public boolean isLegal (TreeNode node1, TreeNode node2) { if (node1 == null && node2 == null ) { return true ; } else if ((node1 == null && node2 != null ) || (node1 != null && node2 == null )) { return false ; } else { return node1.val == node2.val && isLegal(node1.left, node2.right) && isLegal(node1.right, node2.left); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public List<List<Integer>> levelOrder (TreeNode root) { List<List<Integer>> result = new ArrayList <>(); Queue<TreeNode> queue = new LinkedList <>(); if (root != null ) { queue.offer(root); } while (!queue.isEmpty()) { int size = queue.size(); List<Integer>list = new ArrayList <>(); while (size != 0 ) { size--; root = queue.poll(); list.add(root.val); if (root.left != null ) { queue.offer(root.left); } if (root.right != null ) { queue.offer(root.right); } } result.add(list); } return result; } }
1 2 3 4 5 6 7 8 class Solution { public int maxDepth (TreeNode root) { if (root == null ) { return 0 ; } return Math.max((maxDepth(root.left)), maxDepth(root.right)) + 1 ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public List<List<Integer>> levelOrderBottom (TreeNode root) { List<List<Integer>> result = new ArrayList <>(); Queue<TreeNode> queue = new LinkedList <>(); if (root != null ) { queue.offer(root); while (!queue.isEmpty()) { int size = queue.size(); List<Integer> list = new ArrayList <>(); while (size != 0 ) { size--; root = queue.poll(); list.add(root.val); if (root.left != null ) { queue.offer(root.left); } if (root.right != null ) { queue.offer(root.right); } } result.add(0 , list); } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public TreeNode sortedArrayToBST (int [] nums) { return build(nums, 0 , nums.length - 1 ); } public TreeNode build (int [] nums, int left, int right) { if (left > right) { return null ; } int mid = (left + right) >> 1 ; TreeNode node = new TreeNode (nums[mid]); node.left = build(nums, left, mid - 1 ); node.right = build(nums, mid + 1 , right); return node; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution { ListNode cur; public TreeNode sortedListToBST (ListNode head) { cur = head; int len = getLen(head); return build(0 , len - 1 ); } private TreeNode build (int left, int right) { if (left > right) { return null ; } int mid = (left + right) >> 1 ; TreeNode leftNode = build(left, mid - 1 ); TreeNode node = new TreeNode (cur.val); cur = cur.next; node.left = leftNode; node.right = build(mid + 1 , right); return node; } public int getLen (ListNode head) { int len = 0 ; while (head != null ) { head = head.next; len++; } return len; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public boolean isBalanced (TreeNode root) { return getDeep(root) != -1 ; } public int getDeep (TreeNode root) { if (root == null ) { return 0 ; } int left = getDeep(root.left); if (left == -1 ) { return -1 ; } int right = getDeep(root.right); if (right == -1 ) { return -1 ; } if (Math.abs(left - right) > 1 ) { return -1 ; } return Math.max(left, right) + 1 ; } }
当然也可以getDeep就是获取高度,在isBalanced分别获取left和right的高度,发现高度差直接返回了,不然就再递归isBalanced左右
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public boolean isBalanced (TreeNode root) { if (root == null ) { return true ; } if (Math.abs(getDeep(root.left) - getDeep(root.right)) > 1 ) { return false ; } else { return isBalanced(root.left) && isBalanced(root.right); } } public int getDeep (TreeNode root) { if (root == null ) { return 0 ; } return Math.max(getDeep(root.left), getDeep(root.right)) + 1 ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution { public int minDepth (TreeNode root) { if (root == null ) { return 0 ; } Queue<TreeNode> queue = new LinkedList <>(); queue.offer(root); int minDeep = 0 ; while (!queue.isEmpty()) { minDeep++; int size = queue.size(); while ((size--) != 0 ) { TreeNode node = queue.poll(); if (node.left == null && node.right == null ) { return minDeep; } else { if (node.left != null ) { queue.offer(node.left); } if (node.right != null ) { queue.offer(node.right); } } } } return minDeep; } }
也可以递归,效率低了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public int minDepth (TreeNode root) { if (root == null ) { return 0 ; } if (root.left == null ) { return minDepth(root.right) + 1 ; } if (root.right == null ) { return minDepth(root.left) + 1 ; } return Math.min(minDepth(root.left), minDepth(root.right)) + 1 ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public boolean hasPathSum (TreeNode root, int targetSum) { return hasPath(targetSum, root, 0 ); } public boolean hasPath (int targetSum, TreeNode root, int temp) { if (root == null ) { return false ; } temp += root.val; if (root.left == null && root.right == null ) { return temp == targetSum; } return hasPath(targetSum, root.left, temp) || hasPath(targetSum, root.right, temp); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public List<List<Integer>> pathSum (TreeNode root, int targetSum) { List<List<Integer>> result = new ArrayList <>(); dfs(result, new ArrayList <>(), root, targetSum, 0 ); return result; } public void dfs (List<List<Integer>> result, List<Integer> temp, TreeNode root, int targetSum, int tempSum) { if (root == null ) { return ; } tempSum += root.val; temp.add(root.val); if (root.left == null && root.right == null ) { if (tempSum == targetSum) { result.add(new ArrayList <>(temp)); temp.remove(temp.size() - 1 ); return ; } } dfs(result, temp, root.left, targetSum, tempSum); dfs(result, temp, root.right, targetSum, tempSum); temp.remove(temp.size() - 1 ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { TreeNode newTreeNode = new TreeNode (), last = newTreeNode; public void flatten (TreeNode root) { preOrder(root); } public void preOrder (TreeNode root) { if (root == null ) { return ; } TreeNode left = root.left, right = root.right; last.left = null ; last.right = root; last = root; preOrder(left); preOrder(right); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution { public int sumNumbers (TreeNode root) { return dfs(root, 0 ); } public int dfs (TreeNode node, int last) { if (node == null ) { return 0 ; } last *= 10 ; last += node.val; if (node.left == null && node.right == null ) { return last; } return dfs(node.left, last) + dfs(node.right, last); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public List<Integer> preorderTraversal (TreeNode root) { LinkedList<TreeNode> stack = new LinkedList <>(); List<Integer> result = new ArrayList <>(); if (root == null ) { return result; } stack.add(root); while (!stack.isEmpty()) { root = stack.poll(); result.add(root.val); if (root.right != null ) { stack.push(root.right); } if (root.left != null ) { stack.push(root.left); } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public List<Integer> postorderTraversal (TreeNode root) { LinkedList<TreeNode> stack = new LinkedList <>(); List<Integer> result = new ArrayList <>(); TreeNode last = null ; while (root != null || !stack.isEmpty()) { while (root != null ) { stack.push(root); root = root.left; } root = stack.peek(); if (root.right == null || root.right == last) { result.add(root.val); last = stack.poll(); root = null ; } else { root = root.right; } } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class BSTIterator { LinkedList<TreeNode> stack; public BSTIterator (TreeNode root) { stack = new LinkedList <>(); pushLeft(root); } public int next () { TreeNode node = stack.poll(); pushLeft(node.right); return node.val; } public boolean hasNext () { return !stack.isEmpty(); } private void pushLeft (TreeNode node) { while (node != null ) { stack.push(node); node = node.left; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public List<Integer> rightSideView (TreeNode root) { List<Integer> result = new ArrayList <>(); Queue<TreeNode> queue = new LinkedList <>(); if (root == null ) { return result; } queue.offer(root); while (!queue.isEmpty()) { int size = queue.size(); TreeNode cur = null ; while ((size--) != 0 ) { cur = queue.poll(); if (cur.left != null ) { queue.offer(cur.left); } if (cur.right != null ) { queue.offer(cur.right); } } result.add(cur.val); } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 class Solution { public TreeNode invertTree (TreeNode root) { if (root == null ) { return null ; } TreeNode left = root.left, right = root.right; root.right = invertTree(left); root.left = invertTree(right); return root; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class Solution { public List<String> binaryTreePaths (TreeNode root) { List<String> result = new ArrayList <>(); dfs(root, result, new StringBuilder ()); return result; } public void dfs (TreeNode root, List<String> result, StringBuilder builder) { if (root == null ) { return ; } String s = String.valueOf(root.val); builder.append(s); builder.append("->" ); if (root.left == null && root.right == null ) { builder.delete(builder.length() - 2 , builder.length()); result.add(builder.toString()); builder.delete(builder.length() - s.length(), builder.length()); return ; } dfs(root.left, result, builder); dfs(root.right, result, builder); builder.delete(builder.length() - s.length() - 2 , builder.length()); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public int sumOfLeftLeaves (TreeNode root) { int [] value = new int [] { 0 }; dfs(root, value); return value[0 ]; } public void dfs (TreeNode root, int [] value) { if (root == null ) { return ; } if (root.left != null && root.left.left == null && root.left.right == null ) { value[0 ] += root.left.val; } dfs(root.left, value); dfs(root.right, value); } }
long类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public int pathSum (TreeNode root, long targetSum) { if (root == null ) { return 0 ; } int [] value = new int [] { 0 }; dfs(root, targetSum, 0 , value); return value[0 ] + pathSum(root.left, targetSum) + pathSum(root.right, targetSum); } public void dfs (TreeNode root, long targetSum, long temp, int [] value) { if (root == null ) { return ; } temp += root.val; if (temp == targetSum) { value[0 ]++; } dfs(root.left, targetSum, temp, value); dfs(root.right, targetSum, temp, value); } }
同样也是要注意Long类型,这里是前缀和,然后要看前面有多少个符合要求的,就需要HashMap,还要注意开始的0的处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public int pathSum (TreeNode root, int targetSum) { HashMap<Long, Integer> preSum = new HashMap <>(); preSum.put(0L , 1 ); return getPreSum(root, targetSum, preSum, 0L ); } public int getPreSum (TreeNode root, int targetSum, HashMap<Long, Integer> preSum, long cur) { if (root == null ) { return 0 ; } int result = 0 ; cur += root.val; result += preSum.getOrDefault(cur - targetSum, 0 ); preSum.put(cur, preSum.getOrDefault(cur, 0 ) + 1 ); result += getPreSum(root.left, targetSum, preSum, cur); result += getPreSum(root.right, targetSum, preSum, cur); preSum.put(cur, preSum.get(cur) - 1 ); return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public int findBottomLeftValue (TreeNode root) { int result = 0 ; LinkedList<TreeNode> queue = new LinkedList <>(); queue.offer(root); while (!queue.isEmpty()) { int size = queue.size(), cur = size; while (cur != 0 ) { TreeNode node = queue.poll(); if (cur == size) { result = node.val; } if (node.left != null ) { queue.offer(node.left); } if (node.right != null ) { queue.offer(node.right); } cur--; } } return result; } }
递归优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { int deep = 0 , result = 0 ; public int findBottomLeftValue (TreeNode root) { getResult(root, 1 ); return result; } public void getResult (TreeNode root, int curDeep) { if (curDeep > deep) { deep = curDeep; result = root.val; } if (root.left != null ) { getResult(root.left, curDeep + 1 ); } if (root.right != null ) { getResult(root.right, curDeep + 1 ); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution { public List<Integer> largestValues (TreeNode root) { List<Integer> result = new ArrayList <>(); if (root == null ) { return result; } LinkedList<TreeNode> queue = new LinkedList <>(); queue.offer(root); while (!queue.isEmpty()) { int size = queue.size() - 1 ; TreeNode largest = queue.poll(); if (largest.left != null ) { queue.offer(largest.left); } if (largest.right != null ) { queue.offer(largest.right); } while ((size--) != 0 ) { TreeNode node = queue.poll(); if (largest.val < node.val) { largest = node; } if (node.left != null ) { queue.offer(node.left); } if (node.right != null ) { queue.offer(node.right); } } result.add(largest.val); } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { int result = 0 ; public int findTilt (TreeNode root) { dfs(root); return result; } public int dfs (TreeNode root) { if (root == null ) { return 0 ; } int left = dfs(root.left), right = dfs(root.right); result += Math.abs(left - right); return left + right + root.val; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public boolean isSubtree (TreeNode root, TreeNode subRoot) { boolean result = isSame(root, subRoot); if (root == null || subRoot == null ) { return result; } return result || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); } public boolean isSame (TreeNode root, TreeNode subRoot) { if (root == null && subRoot == null ) { return true ; } if (root != null && subRoot != null ) { return root.val == subRoot.val && isSame(root.left, subRoot.left) && isSame(root.right, subRoot.right); } return false ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public List<Double> averageOfLevels (TreeNode root) { List<Double> result = new ArrayList <>(); LinkedList<TreeNode> queue = new LinkedList <>(); queue.offer(root); while (!queue.isEmpty()) { int size = queue.size(), curSize = size; double temp = 0 ; while ((curSize--) != 0 ) { TreeNode node = queue.poll(); if (node.left != null ) { queue.offer(node.left); } if (node.right != null ) { queue.offer(node.right); } temp += node.val; } result.add(temp / size); } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public boolean findTarget (TreeNode root, int k) { List<Integer> temp = new ArrayList <>(); midOrder(root, temp); int left = 0 , right = temp.size() - 1 ; while (left < right) { if (temp.get(left) + temp.get(right) > k) { right--; } else if (temp.get(left) + temp.get(right) < k) { left++; } else { break ; } } return left < right; } public void midOrder (TreeNode root, List<Integer> temp) { if (root == null ) { return ; } midOrder(root.left, temp); temp.add(root.val); midOrder(root.right, temp); } }
网上另一种思路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public boolean findTarget (TreeNode root, int k) { return find(root, k, new HashSet <Integer>()); } public boolean find (TreeNode root, int k, HashSet<Integer> set) { if (root == null ) { return false ; } if (set.contains(k - root.val)) { return true ; } set.add(root.val); return find(root.left, k, set) || find(root.right, k, set); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public boolean leafSimilar (TreeNode root1, TreeNode root2) { List<Integer> list1 = new ArrayList <>(), list2 = new ArrayList <>(); dfs(root1, list1); dfs(root2, list2); return list1.equals(list2); } public void dfs (TreeNode root, List<Integer> list) { if (root == null ) { return ; } if (root.left == null && root.right == null ) { list.add(root.val); } dfs(root.left, list); dfs(root.right, list); } }
注意最后将left和right都置为null
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { TreeNode newRoot = new TreeNode (), last = newRoot; public TreeNode increasingBST (TreeNode root) { midOrder(root); last.left = null ; last.right = null ; return newRoot.right; } public void midOrder (TreeNode root) { if (root == null ) { return ; } midOrder(root.left); last.left = null ; last.right = root; last = root; midOrder(root.right); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public int deepestLeavesSum (TreeNode root) { int result = 0 ; LinkedList<TreeNode> queue = new LinkedList <>(); queue.offer(root); while (!queue.isEmpty()) { int size = queue.size(), temp = 0 ; while ((size--) != 0 ) { TreeNode node = queue.poll(); temp += node.val; if (node.left != null ) { queue.offer(node.left); } if (node.right != null ) { queue.offer(node.right); } } result = temp; } return result; } }
递归避免了频繁抛出和加入队列,更快了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { int maxDeep = 0 , sum = 0 ; public int deepestLeavesSum (TreeNode root) { if (root != null ) { dfs(root, 1 ); } return sum; } public void dfs (TreeNode root, int deep) { if (root == null ) { return ; } if (deep > maxDeep) { sum = root.val; maxDeep = deep; } else if (deep == maxDeep) { sum += root.val; } dfs(root.left, deep + 1 ); dfs(root.right, deep + 1 ); } }
动态规划 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public int climbStairs (int n) { if (n <= 2 ) { return n; } int first = 1 , second = 2 ; for (int i = 3 ; i <= n; i++) { int temp = first + second; first = second; second = temp; } return second; } }
1 2 3 4 5 6 7 8 9 10 11 class Solution { public int climbStairs (int n) { int [] dp = new int [n + 1 ]; dp[0 ] = 1 ; dp[1 ] = 1 ; for (int i = 2 ; i <= n; i++) { dp[i] = dp[i - 1 ] + dp[i - 2 ]; } return dp[n]; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution { public int rob (int [] nums) { int [] dp = new int [nums.length + 1 ]; dp[0 ] = 0 ; dp[1 ] = nums[0 ]; for (int i = 2 ; i <= nums.length; i++) { dp[i] = Math.max(dp[i - 1 ], dp[i - 2 ] + nums[i - 1 ]); } return dp[nums.length]; } }
1 2 3 4 5 6 7 8 9 10 11 class Solution { public int rob (int [] nums) { int first = 0 , second = nums[0 ]; for (int i = 1 ; i < nums.length; i++) { int temp = Math.max(second, first + nums[i]); first = second; second = temp; } return second; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public int maxProfit (int [] prices) { int [][] dp = new int [prices.length][3 ]; dp[0 ][0 ] = -prices[0 ]; for (int i = 1 ; i < prices.length; i++) { dp[i][0 ] = Math.max(dp[i - 1 ][0 ], dp[i - 1 ][2 ] - prices[i]); dp[i][1 ] = dp[i - 1 ][0 ] + prices[i]; dp[i][2 ] = Math.max(dp[i - 1 ][2 ], dp[i - 1 ][1 ]); } return Math.max(dp[prices.length - 1 ][1 ], dp[prices.length - 1 ][2 ]); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution { public int maxProfit (int [] prices) { int [] dp = new int [3 ]; dp[0 ] = -prices[0 ]; for (int i = 1 ; i < prices.length; i++) { int old = dp[0 ]; dp[0 ] = Math.max(dp[0 ], dp[2 ] - prices[i]); dp[2 ] = Math.max(dp[1 ], dp[2 ]); dp[1 ] = old + prices[i]; } return Math.max(dp[1 ], dp[2 ]); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public int coinChange (int [] coins, int amount) { int [] dp = new int [amount + 1 ]; Arrays.fill(dp, amount + 1 ); dp[0 ] = 0 ; for (int coin : coins) { for (int j = coin; j <= amount; j++) { dp[j] = Math.min(dp[j], dp[j - coin] + 1 ); } } return dp[amount] == amount + 1 ? -1 : dp[amount]; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public int integerBreak (int n) { int [] dp = new int [n + 1 ]; dp[2 ] = 1 ; for (int i = 3 ; i <= n; i++) { for (int j = 1 ; j <= i / 2 ; j++) { dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j])); } } return dp[n]; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public boolean canPartition (int [] nums) { int sum = 0 ; for (int num : nums) { sum += num; } if (sum % 2 != 0 ) { return false ; } sum /= 2 ; int [] dp = new int [sum + 1 ]; for (int i : nums) { for (int j = sum; j >= i; j--) { dp[j] = Math.max(dp[j], dp[j - i] + i); if (dp[j] == sum) { return true ; } } } return dp[sum] == sum; } }
DFS和BFS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution { public List<String> letterCombinations (String digits) { HashMap<Character, String> map = new HashMap <>(); map.put('2' , "abc" ); map.put('3' , "def" ); map.put('4' , "ghi" ); map.put('5' , "jkl" ); map.put('6' , "mno" ); map.put('7' , "pqrs" ); map.put('8' , "tuv" ); map.put('9' , "wxyz" ); List<String> result = new ArrayList <>(); if (digits.length() != 0 ) { backTracking(map, result, new char [digits.length()], 0 , digits); } return result; } public void backTracking (HashMap<Character, String> map, List<String> result, char [] temp, int len, String digits) { if (len == digits.length()) { result.add(new String (temp)); return ; } char c = digits.charAt(len); String s = map.get(c); for (int i = 0 ; i < s.length(); i++) { temp[len] = s.charAt(i); backTracking(map, result, temp, len + 1 , digits); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution { public List<String> generateParenthesis (int n) { List<String> result = new ArrayList <>(); backTracking(0 , 0 , n, new char [n * 2 ], result); return result; } public void backTracking (int left, int right, int n, char [] temp, List<String> result) { if (left == n && right == n) { result.add(new String (temp)); return ; } int cur = left + right; if (left < n) { if (left == right) { temp[cur] = '(' ; backTracking(left + 1 , right, n, temp, result); } else { temp[cur] = '(' ; backTracking(left + 1 , right, n, temp, result); temp[cur] = ')' ; backTracking(left, right + 1 , n, temp, result); } } else { temp[cur] = ')' ; backTracking(left, right + 1 , n, temp, result); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 class Solution { public void solveSudoku (char [][] board) { for (int i = 0 ; i < 9 ; i++) { for (int j = 0 ; j < 9 ; j++) { if (board[i][j] == '.' ) { for (char k = '1' ; k <= '9' ; k++) { if (isLegal(board, i, j, k)) { board[i][j] = k; solveSudoku(board); if (isFill(board)) { return ; } board[i][j] = '.' ; } } return ; } } } } public boolean isFill (char [][] board) { for (int i = 0 ; i < 9 ; i++) { for (int j = 0 ; j < 9 ; j++) { if (board[i][j] == '.' ) { return false ; } } } return true ; } public boolean isLegal (char [][] board, int row, int column, char num) { for (int i = 0 ; i < 9 ; i++) { if (board[i][column] == num) { return false ; } } for (int j = 0 ; j < 9 ; j++) { if (board[row][j] == num) { return false ; } } int left = row / 3 * 3 , right = column / 3 * 3 ; for (int i = left; i < left + 3 ; i++) { for (int j = right; j < right + 3 ; j++) { if (board[i][j] == num) { return false ; } } } return true ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public List<List<Integer>> permute (int [] nums) { boolean [] isSelected = new boolean [nums.length]; List<List<Integer>> result = new ArrayList <>(); List<Integer> temp = new ArrayList <>(); backTracking(result, nums, isSelected, temp); return result; } public void backTracking (List<List<Integer>> result, int [] nums, boolean [] isSelected, List<Integer> temp) { if (temp.size() == nums.length) { result.add(new ArrayList <>(temp)); return ; } for (int i = 0 ; i < nums.length; i++) { if (!isSelected[i]) { temp.add(nums[i]); isSelected[i] = true ; backTracking(result, nums, isSelected, temp); isSelected[i] = false ; temp.remove(temp.size() - 1 ); } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 class Solution { List<List<String>> result = new ArrayList <>(); char [][] board; public List<List<String>> solveNQueens (int n) { board = new char [n][n]; for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < n; j++) { board[i][j] = '.' ; } } backTracking(n, 0 ); return result; } public void backTracking (int n, int deep) { if (deep == n) { List<String> temp = new ArrayList <>(); for (char [] chars : board) { temp.add(new String (chars)); } result.add(temp); return ; } for (int j = 0 ; j < n; j++) { if (isLegal(n, deep, j)) { board[deep][j] = 'Q' ; backTracking(n, deep + 1 ); board[deep][j] = '.' ; } } } public boolean isLegal (int n, int x, int y) { for (int i = 0 ; i < n; i++) { if (board[i][y] != '.' ) { return false ; } } for (int i = x - 1 , j = y - 1 ; i >= 0 && j >= 0 ; i--, j--) { if (board[i][j] != '.' ) { return false ; } } for (int i = x + 1 , j = y - 1 ; i < n && j >= 0 ; i++, j--) { if (board[i][j] != '.' ) { return false ; } } for (int i = x - 1 , j = y + 1 ; i >= 0 && j < n; i--, j++) { if (board[i][j] != '.' ) { return false ; } } for (int i = x + 1 , j = y + 1 ; i < n && j < n; i++, j++) { if (board[i][j] != '.' ) { return false ; } } return true ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 class Solution { int result = 0 ; char [][] board; public int totalNQueens (int n) { board = new char [n][n]; for (int i = 0 ; i < n; i++) { for (int j = 0 ; j < n; j++) { board[i][j] = '.' ; } } backTracking(n, 0 ); return result; } public void backTracking (int n, int deep) { if (deep == n) { result++; return ; } for (int j = 0 ; j < n; j++) { if (isLegal(n, deep, j)) { board[deep][j] = 'Q' ; backTracking(n, deep + 1 ); board[deep][j] = '.' ; } } } public boolean isLegal (int n, int x, int y) { for (int i = 0 ; i < n; i++) { if (board[i][y] != '.' ) { return false ; } } for (int i = x - 1 , j = y - 1 ; i >= 0 && j >= 0 ; i--, j--) { if (board[i][j] != '.' ) { return false ; } } for (int i = x + 1 , j = y - 1 ; i < n && j >= 0 ; i++, j--) { if (board[i][j] != '.' ) { return false ; } } for (int i = x - 1 , j = y + 1 ; i >= 0 && j < n; i--, j++) { if (board[i][j] != '.' ) { return false ; } } for (int i = x + 1 , j = y + 1 ; i < n && j < n; i++, j++) { if (board[i][j] != '.' ) { return false ; } } return true ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution { String result = "" ; int cur = 0 ; public String getPermutation (int n, int k) { backTracking(n, k, new boolean [n], new char [n], 0 ); return result; } public void backTracking (int n, int k, boolean [] isSelect, char [] temp, int deep) { if (deep == n) { cur++; if (cur == k) { result = new String (temp); } return ; } if (cur >= k) { return ; } for (int i = 0 ; i < isSelect.length; i++) { if (cur >= k) { return ; } if (!isSelect[i]) { isSelect[i] = true ; temp[deep] = (char ) ('0' + i + 1 ); backTracking(n, k, isSelect, temp, deep + 1 ); isSelect[i] = false ; } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { List<List<Integer>> result = new ArrayList <>(); public List<List<Integer>> combine (int n, int k) { backTracking(n, k, new ArrayList <>(), 1 ); return result; } public void backTracking (int n, int k, List<Integer> temp, int cur) { if (temp.size() == k) { result.add(new ArrayList <>(temp)); return ; } if (temp.size() + n - cur + 1 < k) { return ; } for (int i = cur; i <= n; i++) { temp.add(i); backTracking(n, k, temp, i + 1 ); temp.remove(temp.size() - 1 ); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 class Solution { List<String> result = new ArrayList <>(); public List<String> restoreIpAddresses (String s) { backTracking(s, new StringBuilder (), 0 , 0 ); return result; } public void backTracking (String s, StringBuilder builder, int cur, int pointCount) { if (pointCount == 4 && cur == s.length()) { builder.deleteCharAt(builder.length() - 1 ); result.add(builder.toString()); builder.append("." ); return ; } if (pointCount == 4 ) { return ; } int curMaxLen = cur + 3 > s.length() ? s.length() : cur + 3 ; for (int i = cur + 1 ; i <= curMaxLen; i++) { String temp = s.substring(cur, i); if (temp.charAt(0 ) == '0' && temp.length() > 1 ) { return ; } if (Integer.valueOf(temp) > 255 ) { return ; } builder.append(temp); builder.append("." ); backTracking(s, builder, i, pointCount + 1 ); builder.delete(builder.length() - temp.length() - 1 , builder.length()); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 class Solution { List<List<String>> result = new ArrayList <>(); public List<List<String>> partition (String s) { backTracking(s, new ArrayList <>(), 0 ); return result; } public void backTracking (String s, List<String> temp, int cur) { if (cur == s.length()) { result.add(new ArrayList <>(temp)); return ; } for (int i = cur + 1 ; i <= s.length(); i++) { if (isLegal(s, cur, i - 1 )) { temp.add(s.substring(cur, i)); backTracking(s, temp, i); temp.remove(temp.size() - 1 ); } } } public boolean isLegal (String s, int left, int right) { while (left < right) { if (s.charAt(left++) != s.charAt(right--)) { return false ; } } return true ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class WordDictionary { HashSet<String> dic; public WordDictionary () { dic = new HashSet <>(); } public void addWord (String word) { dic.add(word); } public boolean search (String word) { return isInDic(word.toCharArray(), 0 ); } public boolean isInDic (char [] word, int cur) { if (cur == word.length) { return dic.contains(new String (word)); } for (int i = cur; i < word.length; i++) { if (word[i] == '.' ) { for (char c = 'a' ; c <= 'z' ; c++) { word[i] = c; boolean result = isInDic(word, i + 1 ); word[i] = '.' ; if (result) { return true ; } } return false ; } } return isInDic(word, word.length); } }
TODO 前缀树优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 class Solution { public List<String> findWords (char [][] board, String[] words) { boolean [] isHeadHas = new boolean [26 ]; int maxLen = 0 ; HashSet<String> dic = new HashSet <>(); for (String word : words) { dic.add(word); isHeadHas[word.charAt(0 ) - 'a' ] = true ; maxLen = Math.max(maxLen, word.length()); } StringBuilder temp = new StringBuilder (); boolean [][] isVisited = new boolean [board.length][board[0 ].length]; int [][] dirs = new int [][] { { 1 , 0 }, { -1 , 0 }, { 0 , 1 }, { 0 , -1 } }; HashSet<String> result = new HashSet <>(); for (int i = 0 ; i < board.length; i++) { for (int j = 0 ; j < board[0 ].length; j++) { if (isHeadHas[board[i][j] - 'a' ]) { temp.append(board[i][j]); isVisited[i][j] = true ; dfs(temp, 1 , isVisited, board, dic, i, j, dirs, result, maxLen); temp.deleteCharAt(temp.length() - 1 ); isVisited[i][j] = false ; } } } return new ArrayList <>(result); } public void dfs (StringBuilder temp, int deep, boolean [][] isVisited, char [][] board, HashSet<String> dic, int i, int j, int [][] dirs, HashSet<String> result, int maxLen) { String s = temp.toString(); if (dic.contains(s) && !result.contains(s)) { result.add(s); } if (deep == maxLen) { return ; } for (int [] dir : dirs) { int nextI = i + dir[0 ], nextJ = j + dir[1 ]; if (nextI >= 0 && nextI < isVisited.length && nextJ >= 0 && nextJ < isVisited[0 ].length && !isVisited[nextI][nextJ]) { isVisited[nextI][nextJ] = true ; temp.append(board[nextI][nextJ]); dfs(temp, deep + 1 , isVisited, board, dic, nextI, nextJ, dirs, result, maxLen); isVisited[nextI][nextJ] = false ; temp.deleteCharAt(temp.length() - 1 ); } } } }
TODO 优化
二分搜索 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public double myPow (double x, int n) { return n >= 0 ? quickPow(x, (long ) n) : 1.0 / quickPow(x, -(long ) n); } public double quickPow (double x, long n) { if (n == 0 ) { return 1.0 ; } double y = quickPow(x, n / 2 ); return n % 2 == 0 ? y * y : y * y * x; } }
迭代
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public double myPow (double x, int n) { return n >= 0 ? quickPow(x, (long ) n) : 1.0 / quickPow(x, -(long ) n); } public double quickPow (double x, long n) { double result = 1.0 ; double temp = x; while (n > 0 ) { if (n % 2 == 1 ) { result *= temp; } temp *= temp; n /= 2 ; } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public int mySqrt (int x) { int left = 0 , right = x; while (left <= right) { int mid = left + ((right - left) >> 1 ); long square = (long )mid * mid; if (square > x) { right = mid - 1 ; } else if (square < x) { left = mid + 1 ; } else { return mid; } } return right; } }
个人感觉没什么二分思想
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public int countNodes (TreeNode root) { if (root == null ) { return 0 ; } TreeNode left = root.left; TreeNode right = root.right; int l = 0 , r = 0 ; while (left != null ) { left = left.left; l++; } while (right != null ) { right = right.right; r++; } if (l == r) { return (2 << l) - 1 ; } return 1 + countNodes(root.left) + countNodes(root.right); } }
个人写的,感觉没什么二分思想
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public int kthSmallest (TreeNode root, int k) { int [] temp = new int [] { k, -1 }; dfs(root, temp); return temp[1 ]; } public void dfs (TreeNode root, int [] temp) { if (root == null ) { return ; } dfs(root.left, temp); if (temp[0 ] == 1 ) { temp[0 ]--; temp[1 ] = root.val; return ; } temp[0 ]--; dfs(root.right, temp); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public boolean searchMatrix (int [][] matrix, int target) { for (int [] m : matrix) { if (binarySearch(m, target)) { return true ; } } return false ; } public boolean binarySearch (int [] matrix, int target) { int l = 0 , r = matrix.length - 1 ; while (l <= r) { int mid = (l + r) >> 1 ; if (matrix[mid] < target) { l = mid + 1 ; } else if (matrix[mid] > target) { r = mid - 1 ; } else { return true ; } } return false ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public boolean searchMatrix (int [][] matrix, int target) { int i = matrix.length - 1 , j = 0 ; while (i >= 0 && j <= matrix[0 ].length - 1 ) { if (matrix[i][j] < target) { j++; } else if (matrix[i][j] > target) { i--; } else { return true ; } } return false ; } }
275. H 指数 II - 力扣(LeetCode)
后续看看,这里看的网上的讲解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public int hIndex (int [] citations) { int l = 1 , r = citations.length, len = citations.length; while (l <= r) { int mid = (l + r) >> 1 ; if (citations[len - mid] >= mid) { l = mid + 1 ; } else { r = mid - 1 ; } } return r; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public int hIndex (int [] citations) { int l = 0 , r = citations.length - 1 , len = citations.length; while (l <= r) { int mid = (l + r) >> 1 ; if (len - mid > citations[mid]) { l = mid + 1 ; } else { r = mid - 1 ; } } return len - l; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public int search (int [] nums, int target) { int left = 0 , right = nums.length - 1 ; while (left <= right) { int mid = left + ((right - left) >> 1 ); if (nums[mid] < target) { left = mid + 1 ; } else if (nums[mid] > target) { right = mid - 1 ; } else { return mid; } } return -1 ; } }
哈希表 正常模拟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution { public boolean isValidSudoku (char [][] board) { for (int i = 0 ; i < 9 ; i++) { for (int j = 0 ; j < 9 ; j++) { if (board[i][j] != '.' ) { for (int k = 0 ; k < 9 ; k++) { if (k != j && board[i][j] == board[i][k]) { return false ; } } for (int k = 0 ; k < 9 ; k++) { if (k != i && board[i][j] == board[k][j]) { return false ; } } int top = i / 3 * 3 , start = j / 3 * 3 ; for (int k = top; k < top + 3 ; k++) { for (int l = start; l < start + 3 ; l++) { if (k != i && l != j && board[k][l] == board[i][j]) { return false ; } } } } } } return true ; } }
哈希
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution { public boolean isValidSudoku (char [][] board) { for (int i = 0 ; i < 9 ; i++) { int [] hash = new int [9 ]; for (int j = 0 ; j < 9 ; j++) { if (board[i][j] != '.' && (hash[board[i][j] - '1' ]++) != 0 ) { return false ; } } } for (int j = 0 ; j < 9 ; j++) { int [] hash = new int [9 ]; for (int i = 0 ; i < 9 ; i++) { if (board[i][j] != '.' && (hash[board[i][j] - '1' ]++) != 0 ) { return false ; } } } for (int i = 0 ; i < 9 ; i += 3 ) { for (int j = 0 ; j < 9 ; j += 3 ) { int [] hash = new int [9 ]; for (int k = i; k < i + 3 ; k++) { for (int l = j; l < j + 3 ; l++) { if (board[k][l] != '.' && (hash[board[k][l] - '1' ]++) != 0 ) { return false ; } } } } } return true ; } }
再优化,都是哈希,代码更优雅
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public boolean isValidSudoku (char [][] board) { int [][] rows = new int [9 ][9 ]; int [][] columns = new int [9 ][9 ]; int [][][] grids = new int [3 ][3 ][9 ]; for (int i = 0 ; i < 9 ; i++) { for (int j = 0 ; j < 9 ; j++) { char c = board[i][j]; if (c != '.' ) { int index = c - '1' ; rows[i][index]++; columns[j][index]++; grids[i / 3 ][j / 3 ][index]++; if (rows[i][index] > 1 || columns[j][index] > 1 || grids[i / 3 ][j / 3 ][index] > 1 ) { return false ; } } } } return true ; } }
哈希+排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public List<List<String>> groupAnagrams (String[] strs) { HashMap<String, List<String>> map = new HashMap <>(); for (String str : strs) { char [] charArray = str.toCharArray(); Arrays.sort(charArray); String sortedStr = new String (charArray); if (!map.containsKey(sortedStr)) { map.put(sortedStr, new ArrayList <String>()); } map.get(sortedStr).add(str); } return new ArrayList <>(map.values()); } }
哈希+哈希计数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public List<List<String>> groupAnagrams (String[] strs) { HashMap<String, List<String>> map = new HashMap <>(); for (String str : strs) { int [] hash = new int [26 ]; for (int i = 0 ; i < str.length(); i++) { hash[str.charAt(i) - 'a' ]++; } StringBuilder builder = new StringBuilder (); for (int i = 0 ; i < 26 ; i++) { builder.append((char ) ('a' + i)); builder.append(hash[i]); } String key = builder.toString(); List<String> list = map.getOrDefault(key, new ArrayList <String>()); list.add(str); map.put(key, list); } return new ArrayList <List<String>>(map.values()); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution { public boolean wordPattern (String pattern, String s) { HashMap<Character, String> map = new HashMap <>(); HashSet<String> set = new HashSet <>(); String[] strs = s.split(" " ); if (strs.length != pattern.length()) { return false ; } for (int i = 0 ; i < pattern.length(); i++) { Character c = pattern.charAt(i); String str = strs[i]; if (map.containsKey(c)) { if (!map.get(c).equals(str)) { return false ; } } else { if (set.contains(str)) { return false ; } } map.put(c, str); set.add(str); } return true ; } }
排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public int [][] merge(int [][] intervals) { Arrays.sort(intervals, (int [] ints1, int [] ints2) -> { return ints1[0 ] - ints2[0 ]; }); List<int []> list = new ArrayList <>(); list.add(intervals[0 ]); int [] last = intervals[0 ]; for (int i = 1 ; i < intervals.length; i++) { int [] cur = intervals[i]; if (cur[0 ] >= last[0 ] && cur[0 ] <= last[1 ]) { last[1 ] = Math.max(last[1 ], cur[1 ]); } else { list.add(cur); last = cur; } } int [][] result = new int [list.size()][2 ]; for (int i = 0 ; i < list.size(); i++) { result[i] = list.get(i); } return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public ListNode insertionSortList (ListNode head) { ListNode newHead = new ListNode (-5001 , head), cur = head, curLast = newHead; while (cur != null ) { ListNode curNext = cur.next; if (cur.val >= curLast.val) { curLast = cur; } else { curLast.next = cur.next; ListNode node = newHead; while (node.next != null && node.next.val < cur.val) { node = node.next; } ListNode next = node.next; node.next = cur; cur.next = next; } cur = curNext; } return newHead.next; } }
归并排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution { public int maximumGap (int [] nums) { if (nums.length < 2 ) { return 0 ; } mergeSort(nums, new int [nums.length], 0 , nums.length - 1 ); int result = Math.abs(nums[0 ] - nums[1 ]); for (int i = 2 ; i < nums.length; i++) { int temp = Math.abs(nums[i] - nums[i - 1 ]); result = Math.max(temp, result); } return result; } public void mergeSort (int [] nums, int [] temp, int start, int end) { if (start < end) { int mid = (start + end) >> 1 ; mergeSort(nums, temp, start, mid); mergeSort(nums, temp, mid + 1 , end); merge(nums, temp, start, mid, end); } } public void merge (int [] nums, int [] temp, int start, int mid, int end) { int left = start, right = mid + 1 , cur = start; while (left <= mid && right <= end) { if (nums[left] < nums[right]) { temp[cur++] = nums[left++]; } else { temp[cur++] = nums[right++]; } } while (left <= mid) { temp[cur++] = nums[left++]; } while (right <= end) { temp[cur++] = nums[right++]; } for (int i = start; i <= end; i++) { nums[i] = temp[i]; } } }
快排,自己写的会超时,系统Api不会
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class Solution { public int maximumGap (int [] nums) { if (nums.length < 2 ) { return 0 ; } quickSort(nums, 0 , nums.length - 1 ); int result = Math.abs(nums[0 ] - nums[1 ]); for (int i = 2 ; i < nums.length; i++) { result = Math.max(Math.abs(nums[i] - nums[i - 1 ]), result); } return result; } public void quickSort (int [] nums, int start, int end) { if (start < end) { int position = partition(nums, start, end); quickSort(nums, start, position - 1 ); quickSort(nums, position + 1 , end); } } public int partition (int [] nums, int start, int end) { int base = nums[start], left = start + 1 , right = end; while (left <= right) { while (left <= right && nums[left] <= base) { left++; } while (left <= right && nums[right] > base) { right--; } if (left < right) { swap(nums, left, right); } } swap(nums, start, right); return right; } public void swap (int [] nums, int left, int right) { int temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution { public int maximumGap (int [] nums) { if (nums.length < 2 ) { return 0 ; } Arrays.sort(nums); int result = Math.abs(nums[0 ] - nums[1 ]); for (int i = 2 ; i < nums.length; i++) { result = Math.max(Math.abs(nums[i] - nums[i - 1 ]), result); } return result; } }
基数排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 class Solution { public int maximumGap (int [] nums) { if (nums.length < 2 ) { return 0 ; } lSDRadixSort(nums); int max = Math.abs(nums[0 ] - nums[1 ]); for (int i = 2 ; i < nums.length; i++) { max = Math.max(max, Math.abs(nums[i] - nums[i - 1 ])); } return max; } public void lSDRadixSort (int [] nums) { int max = -1 ; for (int i : nums) { max = Math.max(max, i); } int len = String.valueOf(max).length(); int last = 1 , cur = 10 ; int [][] bucket = new int [nums.length][10 ]; int [] bucketNum = new int [10 ]; for (int i = 0 ; i < len; i++) { for (int num : nums) { int curIndex = num % cur / last; bucket[bucketNum[curIndex]++][curIndex] = num; } int index = 0 ; for (int j = 0 ; j < 10 ; j++) { for (int k = 0 ; k < bucketNum[j]; k++) { nums[index++] = bucket[k][j]; } bucketNum[j] = 0 ; } last *= 10 ; cur *= 10 ; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution { int quickselect (int [] nums, int start, int end, int k) { int base = nums[start], left = start, right = end; while (left <= right) { while (left <= right && nums[right] > base) { right--; } while (left <= right && nums[left] <= base) { left++; } if (left < right) { int tmp = nums[left]; nums[left] = nums[right]; nums[right] = tmp; } } nums[start] = nums[right]; nums[right] = base; if (right == k) { return nums[right]; } else if (right < k) { return quickselect(nums, right + 1 , end, k); } else { return quickselect(nums, start, right - 1 , k); } } public int findKthLargest (int [] _nums, int k) { int n = _nums.length; return quickselect(_nums, 0 , n - 1 , n - k); } }
冒泡->快排
插入->希尔
计数->桶排
选择
归并
基数
堆排
1. 冒泡排序 时间复杂度:均为O(n^2),可以优化最好到O(n),本来有序就优化到一次遍历结束,空间O(1),稳定排序
两两比较,将最大的复位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public int [] sortArray(int [] nums) { bubbleSort(nums); return nums; } public void bubbleSort (int [] nums) { for (int i = 1 ; i < nums.length; i++) { boolean flag = false ; for (int j = 0 ; j < nums.length - i; j++) { if (nums[j + 1 ] < nums[j]) { int temp = nums[j + 1 ]; nums[j + 1 ] = nums[j]; nums[j] = temp; flag = true ; } } if (!flag) { return ; } } } }
2. 选择排序 超时
时间复杂度均为On^2,空间复杂度O1,5 8 5 2 9例子,第一个5会换到2的位置,两个相同的顺序变了,不是稳定排序
记住是保存下标就行,每轮选择剩下最小的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public int [] sortArray(int [] nums) { selectSort(nums); return nums; } public void selectSort (int [] nums) { for (int i = 0 ; i < nums.length - 1 ; i++) { int min = i; for (int j = i + 1 ; j < nums.length; j++) { if (nums[j] < nums[min]) { min = j; } } if (min != i) { int temp = nums[min]; nums[min] = nums[i]; nums[i] = temp; } } } }
3. 插入排序 超时
时间复杂度:最坏全逆序,O(n^2);最好有序,O(n);平均O(n^2)
空间复杂度:O(1)
稳定排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public int [] sortArray(int [] nums) { insertSort(nums); return nums; } public void insertSort (int [] nums) { for (int i = 1 ; i < nums.length; i++) { int cur = nums[i], j = i; while (j > 0 && nums[j - 1 ] > cur) { nums[j] = nums[j - 1 ]; j--; } nums[j] = cur; } } }
4. 希尔排序 插入排序的进阶版
这个居然ac了,而且效率在这题表现跟归并排序差不多,但空间复杂度是O1
时间复杂度在nlogn到n^2之间,不稳定排序
初始状态:
列表:[8, 3, 1, 2, 7, 5, 6, 4]。
初始增量:4(列表长度 8 的一半)。
第一轮(增量为 4):
将列表分成 4 个子列表:
子列表 1:[8, 7]。
子列表 2:[3, 5]。
子列表 3:[1, 6]。
子列表 4:[2, 4]。
对每个子列表进行插入排序:
子列表 1:[7, 8]。
子列表 2:[3, 5]。
子列表 3:[1, 6]。
子列表 4:[2, 4]。
排序后的列表:[7, 3, 1, 2, 8, 5, 6, 4]。
第二轮(增量为 2):
将列表分成 2 个子列表:
子列表 1:[7, 1, 8, 6]。
子列表 2:[3, 2, 5, 4]。
对每个子列表进行插入排序:
子列表 1:[1, 6, 7, 8]。
子列表 2:[2, 3, 4, 5]。
排序后的列表:[1, 2, 6, 3, 7, 4, 8, 5]。
第三轮(增量为 1):
将整个列表视为一个子列表,进行插入排序。
排序后
的列表:[1, 2, 3, 4, 5, 6, 7, 8]。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public int [] sortArray(int [] nums) { shellSort(nums); return nums; } public void shellSort (int [] nums) { int len = nums.length; for (int step = len / 2 ; step >= 1 ; step /= 2 ) { for (int i = step; i < len; i++) { int j = i, cur = nums[i]; while (j - step >= 0 && nums[j - step] > cur) { nums[j] = nums[j - step]; j -= step; } nums[j] = cur; } } } }
5. 归并排序 时间复杂度:最好最坏平均都是O(nlogn)
空间复杂度:O(n)
稳定排序,每次对比的两个序列不会破坏相等的先后顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution { public int [] sortArray(int [] nums) { mergeSort(nums, new int [nums.length], 0 , nums.length - 1 ); return nums; } public void mergeSort (int [] nums, int [] temp, int start, int end) { if (start < end) { int mid = (start + end) >> 1 ; mergeSort(nums, temp, start, mid); mergeSort(nums, temp, mid + 1 , end); merge(nums, temp, start, mid, end); } } public void merge (int [] nums, int [] temp, int start, int mid, int end) { int left = start, right = mid + 1 , cur = start; while (left <= mid && right <= end) { if (nums[left] <= nums[right]) { temp[cur++] = nums[left++]; } else { temp[cur++] = nums[right++]; } } while (left <= mid) temp[cur++] = nums[left++]; while (right <= end) temp[cur++] = nums[right++]; while (start <= end) { nums[start] = temp[start]; start++; } } }
6. 快速排序 时间复杂度,最好O(nlogn),平均O(nlogn),最坏O(n^2),空间复杂度,O(1),不稳定排序
结合代码看7 7 6 3 8 12,发现两个7的先后顺序变了,不稳定
最坏的触发的话就刚好每次选的第一个元素就是极值,有序就是最好的例子,就为最坏情况了
快排在比较乱序的时候由于nlogn的常数比较小就比归并快并且不用额外空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution { public int [] sortArray(int [] nums) { quickSort(nums, 0 , nums.length - 1 ); return nums; } public void quickSort (int [] nums, int start, int end) { if (start < end) { int left = start, right = end, base = nums[start]; while (left < right) { while (left < right && nums[right] >= base) right--; while (left < right && nums[left] <= base) left++; if (left < right) { nums[left] ^= nums[right]; nums[right] ^= nums[left]; nums[left] ^= nums[right]; } } nums[start] = nums[left]; nums[left] = base; quickSort(nums, start, left - 1 ); quickSort(nums, left + 1 , end); } } }
不随机选取过不了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import java.util.Random;class Solution { public int [] sortArray(int [] nums) { quickSort(nums, 0 , nums.length - 1 ); return nums; } public void quickSort (int [] nums, int start, int end) { if (start < end) { int left = start, right = end; int baseIndex = new Random ().nextInt(right - left + 1 ) + left; int base = nums[baseIndex]; nums[baseIndex] = nums[start]; nums[start] = base; while (left < right) { while (left < right && nums[right] >= base) { right--; } while (left < right && nums[left] <= base) { left++; } if (left < right) { int temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; } } nums[start] = nums[left]; nums[left] = base; quickSort(nums, start, left - 1 ); quickSort(nums, left + 1 , end); } } }
7. 堆排序 时间复杂度O(nlogn),空间复杂度O(1),不稳定排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution { public int [] sortArray(int [] nums) { heapSort(nums); return nums; } public void heapSort (int [] nums) { for (int i = nums.length / 2 - 1 ; i >= 0 ; i--) { heapify(nums, nums.length, i); } for (int i = nums.length - 1 ; i >= 0 ; i--) { swap(nums, i, 0 ); heapify(nums, i, 0 ); } } public void heapify (int [] nums, int len, int index) { int largest = index, lson = index * 2 + 1 , rson = index * 2 + 2 ; if (lson < len && nums[lson] > nums[largest]) { largest = lson; } if (rson < len && nums[rson] > nums[largest]) { largest = rson; } if (largest != index) { swap(nums, largest, index); heapify(nums, len, largest); } } public void swap (int [] nums, int first, int second) { int temp = nums[first]; nums[first] = nums[second]; nums[second] = temp; } }
8. 计数排序 时间复杂度是O(n+k),计数排序不是比较排序,排序的速度快于任何比较排序算法。由于用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),这使得计数排序对于数据范围很大的数组,需要大量时间和内存。
空间复杂度O(n+k),页可以说O(k)其实,稳定排序
经典版本,没有负数哈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution { public int [] sortArray(int [] nums) { countingSort(nums); return nums; } public void countingSort (int [] nums) { int max = Integer.MIN_VALUE; for (int i : nums) { max = Math.max(max, i); } int [] count = new int [max + 1 ]; for (int i : nums) { count[i]++; } int t = 0 ; for (int i = 0 ; i <= max; i++) { while (count[i] > 0 ) { nums[t++] = i; count[i]--; } } } }
常数级别,在数字相差不大就是快,就是需要额外空间,下面这个ac了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public int [] sortArray(int [] nums) { countingSort(nums); return nums; } public void countingSort (int [] nums) { int [] count = new int [100001 ]; for (int i : nums) { count[i + 50000 ]++; } int t = 0 ; for (int i = 0 ; i <= 100000 ; i++) { int j = i - 50000 ; while (count[i] > 0 ) { nums[t++] = j; count[i]--; } } } }
9. 桶排序 1.9 桶排序 | 菜鸟教程
这里不写了,有个思路就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 public class BucketSort { public static void main (String[] args) { int [] ints = new int []{2343 , 234 , 765 , 1 , 23 , 5 , 3 , 2 , 0 , 3 }; bucketSort(ints); for (int i : ints) { System.out.print(i + "\t" ); } } public static void bucketSort (int [] ints) { if (ints == null || ints.length == 1 ) { return ; } int min = ints[0 ]; int max = ints[0 ]; for (int i = 1 ; i < ints.length; i++) { if (ints[i] > max) { max = ints[i]; } if (ints[i] < min) { min = ints[i]; } } int buketNum = (max - min) / ints.length + 1 ; ArrayList<ArrayList<Integer>> bucketList = new ArrayList <>(buketNum); for (int i = 0 ; i < buketNum; i++) { bucketList.add(new ArrayList <>()); } for (int i : ints) { bucketList.get((i - min) / ints.length).add(i); } for (int i = 0 ; i < buketNum; i++) { Collections.sort(bucketList.get(i)); } int t = 0 ; for (int i = 0 ; i < buketNum; i++) { ArrayList<Integer> list = bucketList.get(i); for (Integer integer : list) { ints[t++] = integer; } } } }
10. 基数排序 对于每位,每个数字的这个位放入对应位的桶内,按顺序放,然后每位的大小先后放回原数组,继续对下一位进行处理,从低位到高位,注意负数情况
空间复杂度O(n+k),时间复杂度度O(n*k),稳定排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 class Solution { public int [] sortArray(int [] nums) { radixSort(nums); return nums; } public void radixSort (int [] nums) { int maxDigit = getMaxDigit(nums); int [] digitCount = new int [19 ]; int [][] bucket = new int [19 ][nums.length]; int mod = 10 , dev = 1 ; for (int i = 0 ; i < maxDigit; i++, mod *= 10 , dev *= 10 ) { for (int num : nums) { int bucketPosition = num % mod / dev + 9 ; bucket[bucketPosition][digitCount[bucketPosition]++] = num; } int t = 0 ; for (int j = 0 ; j < 19 ; j++) { for (int k = 0 ; k < digitCount[j]; k++) { nums[t++] = bucket[j][k]; } } Arrays.fill(digitCount, 0 ); } } public int getMaxDigit (int [] nums) { int max = 0 ; for (int i : nums) { max = Math.max(max, Math.abs(i)); } int digit = 0 ; do { digit++; max /= 10 ; } while (max != 0 ); return digit; } }