├── src ├── 哈希表 │ ├── KeyboardRow_500.java │ ├── DistributeCandies_575.java │ ├── UncommonWordsfromTwoSentences_884.java │ └── NumJewelsInStones_771.java ├── 动态规划 │ ├── SequenceDP │ │ ├── JumpGame_55.java │ │ ├── ClimbStairs_70.java │ │ └── LongestIncreasingSubsequence_300.java │ ├── MatrixDP │ │ ├── Triangle_120.java │ │ ├── UniquePaths_62.java │ │ ├── MinimumPathSum_64.java │ │ └── UniquePathsII_63.java │ ├── TwoSequencesDP │ │ ├── MaximumSubarray_53.java │ │ ├── LongestCommonSubsequence_77.java │ │ └── EditDistance_72.java │ ├── GameDP │ │ ├── PredicttheWinner_486.java │ │ └── HouseRobber_198.java │ └── 背包问题 │ │ ├── CoinChange_322.java │ │ └── PartitionEqualSubsetSum_416.java ├── 数组 │ ├── Transpose_867.java │ ├── FlipAndInvertImage_832.java │ ├── PlusOne_66.java │ ├── ToeplitzMatrix_766.java │ ├── SortArrayByParity_905.java │ ├── TwoSum_1.java │ ├── BitAnd2bitCharacters_717.java │ ├── IntersectionTwoArrays_349.java │ ├── FizzBuzz_412.java │ ├── SortArrayByParityII_922.java │ └── IntersectionTwoArraysII_350.java ├── 排序 │ ├── 八大排序 │ │ ├── Base.java │ │ ├── Insertion.java │ │ ├── Selection.java │ │ ├── Bubble.java │ │ ├── Shell.java │ │ ├── QuickSort.java │ │ └── MergeSort.java │ ├── KthLargestElementinanArray_215.java │ └── SortColors_75.java ├── 数学 │ ├── HammingDistance_461.java │ ├── ReverseInteger_7.java │ ├── NumberComplement_476.java │ ├── BinaryGap_868.java │ ├── CountPrimes_204.java │ ├── PalindromeNumber_9.java │ ├── DiStringMatch_942.java │ ├── AddBinary_67.java │ └── SelfDividingNumbers_728.java ├── 二分查找 │ ├── PeakIndexInMountainArray_852.java │ ├── FirstBadVersion_278.java │ ├── SingleNonDuplicate_540.java │ ├── SearchInsertPosition_35.java │ ├── FindSmallestLetterGreaterThan_744.java │ ├── MySqrt_69.java │ ├── FindPeakElement_162.java │ ├── BinarySearch_704.java │ ├── Sum4_454.java │ ├── GuessNumberHigherorLower_374.java │ ├── ArrangeCoins_441.java │ ├── SearchinRotatedSortedArrayII_81.java │ ├── SearchRotatedSortedArray_33.java │ └── CountCompleteTreeNodes_222.java ├── 链表 │ ├── 删除 │ │ ├── DeleteNodeInLinkedList_237.java │ │ ├── RemoveDuplicatesfromSortedList_83.java │ │ └── RemoveNthNodeFromEndofList_19.java │ ├── 反转 │ │ ├── SwapNodesinPairs_24.java │ │ ├── ReverseList_77.java │ │ └── RotateRight_61.java │ ├── 合并 │ │ ├── GetIntersectionNode_160.java │ │ ├── MergeTwoLists_21.java │ │ └── AddTwoNumbers_2.java │ └── 双向 │ │ └── MyLinkedList_707.java ├── 字符串 │ ├── ToLowerCase_709.java │ ├── LongestCommonPrefix_14.java │ ├── ShortestToChar_821.java │ ├── LongestSubstringWithoutRepeatingCharacters_3.java │ ├── UniqueMorseRepresentations_804.java │ ├── GenerateParentheses_22.java │ ├── RomanToInt_13.java │ └── NumUniqueEmails_929.java ├── 贪心 │ ├── FindContentChildren_455.java │ ├── IsSubsequence_392.java │ ├── MinimumNumberofArrowstoBurstBalloons_452.java │ ├── ReconstructQueue_406.java │ └── NonOverlappingIntervals_435.java ├── 双指针 │ ├── JudgeSquareSum_633.java │ ├── MergeSortedArray_88.java │ ├── RemoveDuplicatesfromSortedArray_26.java │ ├── RemoveElement_27.java │ └── ContainerWithMostWater_11.java ├── 深度优先搜索 │ ├── MaximumDepthofBinaryTree_104.java │ ├── LeafSimilar_872.java │ ├── TreePostorderTraversal_590.java │ ├── TreePreorderTraversal_589.java │ ├── IncreasingOrderSearchTree_897.java │ ├── EmployeeImportance_690.java │ ├── Matrix_542.java │ └── Permutations_46.java ├── 回溯 │ ├── BinaryWatch_401.java │ └── LetterCasePermutation_784.java ├── 并查集 │ ├── PathSum_112.java │ ├── BinaryTreeLevelOrderTraversal_107.java │ ├── WordSearch_79.java │ ├── FindRedundantConnection_684.java │ └── SerializeDeserializeBinary_297.java ├── 二叉树 │ ├── 搜索 │ │ ├── SearchBST_700.java │ │ ├── LowestCommonAncestorofBinaryTree_236.java │ │ ├── MinimumAbsoluteDifferenceinBST_530.java │ │ ├── FindBottomLeftTreeValue_513.java │ │ ├── MergeTrees_617.java │ │ ├── BinaryTreeRightSideView_199.java │ │ ├── FindLargestValueinEachTreeRow_515.java │ │ ├── PopulatingNextRightPointersinEachNode_116.java │ │ ├── AverageofLevelsinBinaryTree_637.java │ │ └── AddOneRowtoTree_623.java │ ├── 性质 │ │ ├── BalanceTree_110.java │ │ └── TrimBinarySearchTree_669.java │ ├── 构造 │ │ └── ConvertSortedArrayBinarySearchTree_108.java │ ├── 遍历 │ │ ├── BinaryTreePreorderTraversal_144.java │ │ ├── BinaryTreeInorderTraversal_94.java │ │ └── BinaryTreePostorderTraversal_145.java │ ├── 路径 │ │ └── BinaryTreeMaximumPathSum_124.java │ └── 层序遍历 │ │ ├── NaryTreeLevelOrderTraversal_429.java │ │ ├── BinaryTreeLevelOrderTraversal_102.java │ │ ├── BinaryTreeLevelOrderTraversalII_107.java │ │ └── BinaryTreeZigzagLevelOrderTraversal_103.java ├── 栈 │ ├── ValidParentheses_20.java │ ├── SimplifyPath_71.java │ ├── NextGreaterElementI_496.java │ ├── ImplementStackusingQueues_225.java │ ├── MinStack_155.java │ ├── BackspaceStringCompare_844.java │ ├── EvaluateReversePolishNotation_150.java │ ├── BaseballGame_682.java │ ├── LongestValidParentheses_32.java │ ├── ImplementQueueusingStacks_232.java │ └── BasicCalculator_224.java ├── kSum │ ├── TwoSum_1.java │ ├── ThreeSumClosest_16.java │ └── ThreeSum_15.java ├── 尺取法 │ └── MinSubArrayLen_209.java ├── other │ └── 链表 │ │ └── RemoveLastKthNode.java ├── 分治 │ └── DiffWaysToCompute_241.java └── 字典树 │ ├── AddSearchWord_211.java │ └── Trie_208.java └── README.md /src/哈希表/KeyboardRow_500.java: -------------------------------------------------------------------------------- 1 | package 哈希表; 2 | 3 | 4 | import java.util.stream.Stream; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/23 下午12:36 9 | * 10 | * 键盘行 11 | */ 12 | public class KeyboardRow_500 { 13 | public String[] findWords(String[] words) { 14 | return Stream.of(words).filter(s -> s.toLowerCase().matches("[qwertyuiop]*|[asdfghjkl]*|[zxcvbnm]*")).toArray(String[]::new); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/动态规划/SequenceDP/JumpGame_55.java: -------------------------------------------------------------------------------- 1 | package 动态规划.SequenceDP; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/5 下午12:37 6 | * 7 | * 跳跃游戏 8 | */ 9 | public class JumpGame_55 { 10 | public boolean canJump(int[] nums) { 11 | int max = 0; 12 | for(int i=0;imax) {return false;} 14 | max = Math.max(nums[i]+i,max); 15 | } 16 | return true; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/数组/Transpose_867.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/22 下午6:04 6 | * 7 | * 转置矩阵 8 | */ 9 | public class Transpose_867 { 10 | public int[][] transpose(int[][] A) { 11 | int M = A.length, N = A[0].length; 12 | int[][] B = new int[N][M]; 13 | for (int j = 0; j < N; j++) 14 | for (int i = 0; i < M; i++) 15 | B[j][i] = A[i][j]; 16 | return B; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/排序/八大排序/Base.java: -------------------------------------------------------------------------------- 1 | package 排序.八大排序; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/4 14:16 6 | * @Description: 7 | */ 8 | public class Base { 9 | 10 | /** 11 | * 比较 12 | */ 13 | public static boolean compare(int s, int m) { 14 | return s < m; 15 | } 16 | 17 | /** 18 | * 交换 19 | */ 20 | public static void swap(int[] a, int i, int j) { 21 | int t = a[i]; 22 | a[i] = a[j]; 23 | a[j] = t; 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/数学/HammingDistance_461.java: -------------------------------------------------------------------------------- 1 | package 数学; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/22 下午12:23 6 | * 7 | * 汉明距离 8 | */ 9 | public class HammingDistance_461 { 10 | 11 | public int hammingDistance(int x, int y) { 12 | int n = x ^ y; 13 | int count = 0; 14 | 15 | while (n > 0) { 16 | if ((n & 1) == 1) { 17 | count++; 18 | } 19 | n = n >> 1; 20 | } 21 | 22 | return count; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/哈希表/DistributeCandies_575.java: -------------------------------------------------------------------------------- 1 | package 哈希表; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/29 下午9:42 9 | * 10 | * 分糖果 11 | */ 12 | public class DistributeCandies_575 { 13 | public int distributeCandies(int[] candies) { 14 | Set set = new HashSet(); 15 | for (int i=0;i A[i + 1]) { 14 | result = i; 15 | break; 16 | } 17 | } 18 | return result; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/动态规划/SequenceDP/ClimbStairs_70.java: -------------------------------------------------------------------------------- 1 | package 动态规划.SequenceDP; 2 | 3 | /** 4 | * Created by jiangyunxiong on 2018/5/2. 5 | *

6 | * 有 N 阶楼梯,每次可以上一阶或者两阶,求有多少种上楼梯的方法 7 | */ 8 | public class ClimbStairs_70 { 9 | 10 | public int climbStairs(int n) { 11 | if (n <= 2) 12 | return n; 13 | int p = 1, q = 2; 14 | for (int i = 2; i < n; i++) { 15 | int cur = p + q; 16 | p = q; 17 | q = cur; 18 | } 19 | return q; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/链表/删除/DeleteNodeInLinkedList_237.java: -------------------------------------------------------------------------------- 1 | package 链表.删除; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/27 下午8:54 6 | * 7 | * 删除链表中的节点 8 | */ 9 | public class DeleteNodeInLinkedList_237 { 10 | 11 | public void deleteNode(ListNode node) { 12 | node.val = node.next.val; 13 | node.next = node.next.next; 14 | } 15 | 16 | class ListNode { 17 | int val; 18 | ListNode next; 19 | 20 | ListNode(int x) { 21 | val = x; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/字符串/ToLowerCase_709.java: -------------------------------------------------------------------------------- 1 | package 字符串; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/22 上午10:18 6 | * 7 | * 转换成小写字母 8 | */ 9 | public class ToLowerCase_709 { 10 | public String toLowerCase(String str) { 11 | char[] chars = str.toCharArray(); 12 | for (int i=0;i 2147483647 / 10 || ret < -2147483647 / 10) 16 | return 0; 17 | ret = ret * 10 + x % 10; 18 | x = x / 10; 19 | } 20 | return ret; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/贪心/FindContentChildren_455.java: -------------------------------------------------------------------------------- 1 | package 贪心; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by jiangyunxiong on 2018/5/2. 7 | * 8 | * 分发饼干 9 | */ 10 | public class FindContentChildren_455 { 11 | 12 | public int findContentChildren(int[] g, int[] s) { 13 | Arrays.sort(g); 14 | Arrays.sort(s); 15 | int i = 0, j = 0; 16 | while (i < g.length && j < s.length) { 17 | if (s[j] >= g[i]) 18 | i++; 19 | j++; 20 | } 21 | return i; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/数组/PlusOne_66.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/4/5 9:45 AM 6 | */ 7 | public class PlusOne_66 { 8 | public int[] plusOne(int[] digits) { 9 | int size = digits.length; 10 | for (int i = size - 1; i >= 0; i--) { 11 | if (digits[i] < 9) { 12 | digits[i]++; 13 | return digits; 14 | } 15 | digits[i] = 0; 16 | } 17 | int[] arr = new int[size + 1]; 18 | arr[0] = 1; 19 | return arr; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/数学/NumberComplement_476.java: -------------------------------------------------------------------------------- 1 | package 数学; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/22 下午6:11 6 | * 7 | * 给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。 8 | */ 9 | public class NumberComplement_476 { 10 | 11 | public static void main(String[] args) { 12 | NumberComplement_476 num = new NumberComplement_476(); 13 | System.out.println(num.findComplement(12)); 14 | } 15 | 16 | public int findComplement(int num) { 17 | int mask = (Integer.highestOneBit(num) << 1) - 1; 18 | num = ~num; 19 | return num & mask; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/贪心/IsSubsequence_392.java: -------------------------------------------------------------------------------- 1 | package 贪心; 2 | 3 | /** 4 | * Created by jiangyunxiong on 2018/5/2. 5 | * 判断子序列 6 | * 给定字符串 s 和 t ,判断 s 是否为 t 的子序列 7 | */ 8 | public class IsSubsequence_392 { 9 | 10 | public boolean isSubsequence(String s, String t) { 11 | char[] ch1 = s.toCharArray(); 12 | char[] ch2 = t.toCharArray(); 13 | int i = 0, j = 0; 14 | while (i < ch1.length && j < ch2.length) { 15 | if (ch1[i] == ch2[j]) 16 | i++; 17 | j++; 18 | } 19 | return i == ch1.length - 1; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/双指针/JudgeSquareSum_633.java: -------------------------------------------------------------------------------- 1 | package 双指针; 2 | 3 | /** 4 | * Created by jiangyunxiong on 2018/5/2. 5 | * 6 | * 平方数之和 7 | * 8 | * 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c 9 | */ 10 | public class JudgeSquareSum_633 { 11 | 12 | public boolean judgeSquareSum(int c) { 13 | int i = 0, j = (int) Math.sqrt(c); 14 | while (i <= j){ 15 | int num = i*i + j*j; 16 | if(num == c) 17 | return true; 18 | if(num < c) 19 | i++; 20 | else 21 | j--; 22 | } 23 | return false; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/深度优先搜索/MaximumDepthofBinaryTree_104.java: -------------------------------------------------------------------------------- 1 | package 深度优先搜索; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/23 下午8:10 6 | * 7 | * 二叉树的最大深度 8 | */ 9 | public class MaximumDepthofBinaryTree_104 { 10 | public int maxDepth(TreeNode root) { 11 | if (root == null){ 12 | return 0; 13 | } 14 | return Math.max(maxDepth(root.left) + 1, maxDepth(root.right) + 1); 15 | } 16 | 17 | class TreeNode { 18 | int val; 19 | TreeNode left; 20 | TreeNode right; 21 | 22 | TreeNode(int x) { 23 | val = x; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/二分查找/FirstBadVersion_278.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/30 下午3:01 6 | * 7 | * 第一个错误的版本 8 | */ 9 | public class FirstBadVersion_278 { 10 | 11 | public int firstBadVersion(int n) { 12 | int start = 1, end = n; 13 | while (start < end){ 14 | int mid = start + (end - start)/2; 15 | if (!isBadVersion(mid)) 16 | start = mid + 1; 17 | else 18 | end = mid; 19 | } 20 | return start; 21 | } 22 | 23 | boolean isBadVersion(int version){ 24 | return false; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/数组/ToeplitzMatrix_766.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/23 下午1:08 6 | * 7 | * 如果一个矩阵的每一方向由左上到右下的对角线上具有相同元素,那么这个矩阵是托普利茨矩阵。 8 | */ 9 | public class ToeplitzMatrix_766 { 10 | 11 | public boolean isToeplitzMatrix(int[][] matrix) { 12 | int m = matrix.length; 13 | int n = matrix[0].length; 14 | 15 | for (int i = 1; i != m; i++) { 16 | for (int j = 1; j != n; j++) { 17 | if (matrix[i][j] != matrix[i - 1][j - 1]) { 18 | return false; 19 | } 20 | } 21 | } 22 | return true; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/链表/删除/RemoveDuplicatesfromSortedList_83.java: -------------------------------------------------------------------------------- 1 | package 链表.删除; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/29 下午10:16 6 | * 删除排序链表中的重复元素 7 | * 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。 8 | */ 9 | public class RemoveDuplicatesfromSortedList_83 { 10 | class ListNode { 11 | int val; 12 | ListNode next; 13 | 14 | ListNode(int x) { 15 | val = x; 16 | } 17 | } 18 | 19 | public ListNode deleteDuplicates(ListNode head) { 20 | if(head == null || head.next == null) return head; 21 | head.next = deleteDuplicates(head.next); 22 | return head.val == head.next.val ? head.next : head; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/双指针/MergeSortedArray_88.java: -------------------------------------------------------------------------------- 1 | package 双指针; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/4/4 11:13 PM 6 | * 7 | * 合并两个有序数组 8 | * 9 | * 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。 10 | */ 11 | public class MergeSortedArray_88 { 12 | public void merge(int[] nums1, int m, int[] nums2, int n) { 13 | int i = m - 1; 14 | int j = n - 1; 15 | int k = m + n - 1; 16 | 17 | while (k >= 0) { 18 | if (j < 0 || i >= 0 && nums1[i] > nums2[j]) { 19 | nums1[k--] = nums1[i--]; 20 | } else { 21 | nums1[k--] = nums2[j--]; 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/数学/BinaryGap_868.java: -------------------------------------------------------------------------------- 1 | package 数学; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/23 下午7:35 6 | * 7 | * 二进制间距 8 | * 9 | * 不需要将整数转二进制,直接用整数不断除以2 10 | */ 11 | public class BinaryGap_868 { 12 | 13 | public static void main(String[] args) { 14 | BinaryGap_868 b = new BinaryGap_868(); 15 | System.out.println(b.binaryGap(22)); 16 | } 17 | 18 | public int binaryGap(int N) { 19 | int res = 0; 20 | for (int d = -1; N > 0; N /= 2, d++) { 21 | if (N % 2 == 1) { 22 | res = Math.max(res, d); 23 | d = 0; 24 | } 25 | } 26 | return res; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/链表/反转/SwapNodesinPairs_24.java: -------------------------------------------------------------------------------- 1 | package 链表.反转; 2 | 3 | 4 | /** 5 | * @Author jiangyunxiong 6 | * @Date 2018/12/30 下午8:06 7 | */ 8 | public class SwapNodesinPairs_24 { 9 | public ListNode swapPairs(ListNode head) { 10 | if (head == null || head.next == null) { 11 | return head; 12 | } 13 | ListNode temp = head.next; 14 | head.next = swapPairs(temp.next); 15 | temp.next = head; 16 | return temp; 17 | } 18 | 19 | class ListNode { 20 | public int val; 21 | public ListNode next; 22 | 23 | public ListNode(int x) { 24 | val = x; 25 | next = null; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/二分查找/SingleNonDuplicate_540.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * Created by jiangyunxiong on 2018/5/2. 5 | * 6 | * 有序数组中的单一元素 7 | * 8 | * 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数 9 | */ 10 | public class SingleNonDuplicate_540 { 11 | int singleNonDuplicate(int[] nums) { 12 | int l = 0, r = nums.length - 1; 13 | while (l < r) { 14 | int m = l + (r - l) / 2; 15 | if (m % 2 == 1) 16 | m--; // 保证 l/h/m 都在偶数位,使得查找区间大小一直都是奇数 17 | if (nums[m] == nums[m + 1]) { 18 | l = m + 2; 19 | } else { 20 | r = m; 21 | } 22 | } 23 | return nums[l]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/回溯/BinaryWatch_401.java: -------------------------------------------------------------------------------- 1 | package 回溯; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/29 下午11:23 9 | * 10 | * 二进制手表 11 | */ 12 | public class BinaryWatch_401 { 13 | public List readBinaryWatch(int num) { 14 | List times = new ArrayList<>(); 15 | for (int h = 0; h < 12; h++) { 16 | for (int m = 0; m < 60; m++) { 17 | // 技术整型i二进制表示中1的个数。 18 | if (Integer.bitCount(h * 64 + m) == num) { 19 | times.add(String.format("%d:%02d", h, m)); 20 | } 21 | } 22 | } 23 | return times; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/动态规划/MatrixDP/Triangle_120.java: -------------------------------------------------------------------------------- 1 | package 动态规划.MatrixDP; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/5 上午9:51 8 | *

9 | * 三角形最小路径和 10 | *

11 | * 给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。 12 | */ 13 | public class Triangle_120 { 14 | 15 | public int minimumTotal(List> triangle) { 16 | int[] A = new int[triangle.size() + 1]; 17 | //自底向上 18 | for (int i = triangle.size() - 1; i >= 0; i--) { 19 | for (int j = 0; j < triangle.get(i).size(); j++) { 20 | A[j] = Math.min(A[j], A[j + 1]) + triangle.get(i).get(j); 21 | } 22 | } 23 | return A[0]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/并查集/PathSum_112.java: -------------------------------------------------------------------------------- 1 | package 并查集; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/31 上午9:53 6 | * 7 | * 路径总和 8 | */ 9 | public class PathSum_112 { 10 | class TreeNode { 11 | int val; 12 | TreeNode left; 13 | TreeNode right; 14 | 15 | TreeNode(int x) { 16 | val = x; 17 | } 18 | } 19 | 20 | public boolean hasPathSum(TreeNode root, int sum) { 21 | if (root == null)return false; 22 | if (root.left==null &&root.right==null){ 23 | return sum-root.val==0; 24 | } 25 | 26 | return hasPathSum(root.left, sum-root.val)|| 27 | hasPathSum(root.right, sum-root.val); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/二叉树/搜索/SearchBST_700.java: -------------------------------------------------------------------------------- 1 | package 二叉树.搜索; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/22 下午5:42 6 | *

7 | * 二叉搜索树中的搜索 8 | *

9 | * 给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。 10 | */ 11 | public class SearchBST_700 { 12 | 13 | class TreeNode { 14 | int val; 15 | TreeNode left; 16 | TreeNode right; 17 | 18 | TreeNode(int x) { 19 | val = x; 20 | } 21 | } 22 | 23 | public TreeNode searchBST(TreeNode root, int val) { 24 | while (root != null && root.val != val) { 25 | root = root.val > val ? root.right : root.left; 26 | } 27 | return root; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/动态规划/TwoSequencesDP/MaximumSubarray_53.java: -------------------------------------------------------------------------------- 1 | package 动态规划.TwoSequencesDP; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/4/5 9:52 AM 6 | * 7 | * 最大子序和 8 | * 9 | * 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 10 | */ 11 | public class MaximumSubarray_53 { 12 | public int maxSubArray(int[] nums) { 13 | int len = nums.length; 14 | if (len == 0) { 15 | return 0; 16 | } 17 | int segmentSum = nums[0]; 18 | int res = nums[0]; 19 | for (int i = 1; i < nums.length; i++) { 20 | segmentSum = Math.max(nums[i], segmentSum + nums[i]); 21 | res = Math.max(segmentSum, res); 22 | } 23 | return res; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/二分查找/SearchInsertPosition_35.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/26 下午7:55 6 | * 7 | * 搜索插入位置 8 | */ 9 | public class SearchInsertPosition_35 { 10 | 11 | 12 | public int searchInsert(int[] nums, int target) { 13 | int left = 0; 14 | int right = nums.length - 1; 15 | int mid = 0; 16 | while (left < right) { 17 | mid = left + (right - left) / 2; 18 | if (nums[mid] > target) { 19 | right = mid; 20 | } else if (nums[mid] < target) { 21 | left = mid + 1; 22 | } else { 23 | return mid; 24 | } 25 | } 26 | return left; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/哈希表/UncommonWordsfromTwoSentences_884.java: -------------------------------------------------------------------------------- 1 | package 哈希表; 2 | 3 | 4 | import java.util.*; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/23 下午1:41 9 | * 10 | * 两个数组中只出现过一次的数 11 | */ 12 | public class UncommonWordsfromTwoSentences_884 { 13 | 14 | public String[] uncommonFromSentences(String A, String B) { 15 | Map count = new HashMap<>(); 16 | for (String w : (A + " " + B).split(" ")) 17 | count.put(w, count.getOrDefault(w, 0) + 1); 18 | ArrayList res = new ArrayList<>(); 19 | for (String w : count.keySet()) 20 | if (count.get(w) == 1) 21 | res.add(w); 22 | return res.toArray(new String[0]); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/二分查找/FindSmallestLetterGreaterThan_744.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/24 下午11:56 6 | * 7 | * 寻找比目标字母大的最小字母 8 | */ 9 | public class FindSmallestLetterGreaterThan_744 { 10 | 11 | public char nextGreatestLetter(char[] letters, char target) { 12 | int left = 0; 13 | int right = letters.length - 1; 14 | 15 | while (left <= right) { 16 | int mid = left + (right - left) / 2; 17 | int num = letters[mid]; 18 | if (num <= target) { 19 | left = mid + 1; 20 | } else { 21 | right = mid - 1; 22 | } 23 | } 24 | return letters[left%(letters.length)]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/哈希表/NumJewelsInStones_771.java: -------------------------------------------------------------------------------- 1 | package 哈希表; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/22 上午1:17 9 | * 10 | * 宝石与石头 11 | */ 12 | public class NumJewelsInStones_771 { 13 | 14 | public int numJewelsInStones(String J, String S) { 15 | int result = 0; 16 | char[] js = J.toCharArray(); 17 | char[] ss = S.toCharArray(); 18 | 19 | 20 | Set set = new HashSet<>(js.length); 21 | for (char j : js){ 22 | set.add(j); 23 | } 24 | for (char s : ss){ 25 | if (set.contains(s)){ 26 | result++; 27 | } 28 | } 29 | return result; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/双指针/RemoveDuplicatesfromSortedArray_26.java: -------------------------------------------------------------------------------- 1 | package 双指针; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/23 下午10:15 6 | * 7 | * 删除排序数组中的重复项 8 | * 9 | * 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 10 | */ 11 | public class RemoveDuplicatesfromSortedArray_26 { 12 | 13 | /** 14 | * 思路:用2个指针: 15 | * 1个指针i从1移动到length 16 | * 1个指针newlen记录不重复的个数,只有出现不重复的时候它才能+1 17 | */ 18 | public int removeDuplicates(int[] nums) { 19 | if(nums.length < 2) return nums.length; 20 | int newlen = 1; 21 | for(int i=1;i mid) 28 | l = mid + 1; 29 | else 30 | r = mid - 1; 31 | } 32 | return r; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/数学/CountPrimes_204.java: -------------------------------------------------------------------------------- 1 | package 数学; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/29 下午9:18 6 | * 7 | * 计数质数 8 | */ 9 | public class CountPrimes_204 { 10 | 11 | public static void main(String[] args) { 12 | CountPrimes_204 c = new CountPrimes_204(); 13 | System.out.println(c.countPrimes(10)); 14 | } 15 | 16 | public int countPrimes(int n) { 17 | boolean[] notPrime = new boolean[n]; 18 | int count = 0; 19 | for (int i = 2; i < n; i++) { 20 | if (notPrime[i] == false) { 21 | count++; 22 | for (int j = 2; i * j < n; j++) { 23 | notPrime[i * j] = true; 24 | } 25 | } 26 | } 27 | return count; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/字符串/LongestCommonPrefix_14.java: -------------------------------------------------------------------------------- 1 | package 字符串; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/6/23 1:53 PM 6 | */ 7 | public class LongestCommonPrefix_14 { 8 | public static void main(String[] args) { 9 | LongestCommonPrefix_14 n = new LongestCommonPrefix_14(); 10 | String a[] = {"c","acc","ccc"}; 11 | String s = n.longestCommonPrefix(a); 12 | } 13 | public String longestCommonPrefix(String[] strs) { 14 | if(strs.length == 0) return ""; 15 | String pre = strs[0]; 16 | for(int i=1;i stack = new Stack(); 17 | for (char c : chars) { 18 | if (c == '('){ 19 | stack.push(')'); 20 | }else if (c == '{'){ 21 | stack.push('}'); 22 | }else if (c == '['){ 23 | stack.push(']'); 24 | }else if (stack.isEmpty() || stack.pop() != c){ 25 | return false; 26 | } 27 | } 28 | return stack.isEmpty(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/数组/SortArrayByParity_905.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/22 上午10:57 6 | * 7 | * 按奇偶排序数组 8 | */ 9 | public class SortArrayByParity_905 { 10 | 11 | public static void main(String[] args) { 12 | SortArrayByParity_905 s = new SortArrayByParity_905(); 13 | int[] ints = s.sortArrayByParity(new int[]{3, 1, 2, 4}); 14 | for (int i : ints) { 15 | System.out.println(i); 16 | } 17 | } 18 | 19 | public int[] sortArrayByParity(int[] A) { 20 | for (int i = 0, j = 0; j < A.length; j++) { 21 | if (A[j] % 2 == 0) { 22 | int temp = A[i]; 23 | A[i++] = A[j]; 24 | A[j] = temp; 25 | } 26 | } 27 | return A; 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/动态规划/TwoSequencesDP/LongestCommonSubsequence_77.java: -------------------------------------------------------------------------------- 1 | package 动态规划.TwoSequencesDP; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/5 下午1:00 6 | *

7 | * 给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度。 8 | */ 9 | public class LongestCommonSubsequence_77 { 10 | 11 | public int longestCommonSubsequence(String A, String B) { 12 | int m = A.length(); 13 | int n = B.length(); 14 | int[][] dp = new int[m + 1][n + 1]; 15 | for (int i = 1; i <= m; i++) { 16 | for (int j = 1; j <= n; j++) { 17 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 18 | if (A.charAt(i - 1) == B.charAt(j - 1)) { 19 | dp[i][j] = dp[i - 1][j - 1] + 1; 20 | } 21 | } 22 | } 23 | return dp[m][n]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/链表/合并/GetIntersectionNode_160.java: -------------------------------------------------------------------------------- 1 | package 链表.合并; 2 | 3 | 4 | /** 5 | * Created by jiangyunxiong on 2018/5/2. 6 | */ 7 | public class GetIntersectionNode_160 { 8 | 9 | /** 10 | * 找出两个链表的交点 11 | * 12 | * @param headA 13 | * @param headB 14 | * @return 15 | */ 16 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 17 | ListNode l1 = headA, l2 = headB; 18 | while (l1 != l2) { 19 | l1 = (l1 == null) ? headB : l1.next; 20 | l2 = (l2 == null) ? headA : l2.next; 21 | } 22 | return l1; 23 | } 24 | 25 | class ListNode { 26 | public int val; 27 | public ListNode next; 28 | 29 | public ListNode(int x) { 30 | val = x; 31 | next = null; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/二分查找/FindPeakElement_162.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/30 下午3:30 6 | * 7 | * 寻找峰值,峰值元素是指其值大于左右相邻值的元素。 8 | */ 9 | public class FindPeakElement_162 { 10 | 11 | /** 12 | * 时间复杂度:O(log2n) 13 | * 思路:二分查找,如果mid在波峰的递增部分,那么l=mid+1,如果mid在波峰的递减部分,r=mid, 当l=r时,也就是mid在波峰,那么返回 14 | */ 15 | public int findPeakElement(int[] nums) { 16 | if (nums == null || nums.length == 1) { 17 | return nums == null || nums.length == 0 ? -1 : 0; 18 | } 19 | int l = 0, r = nums.length - 1; 20 | while (l < r) { 21 | int mid =l+(r-l)/2; 22 | if (nums[mid] 7 | * 8 | * 字符的最短距离 9 | * 10 | * 1.从左边遍历找出最近距离 11 | * 2.从右边遍历找出最近距离 12 | * 3.选择最近 13 | */ 14 | public class ShortestToChar_821 { 15 | public int[] shortestToChar(String S, char C) { 16 | int n = S.length(); 17 | int[] res = new int[n]; 18 | 19 | int pos = -n; 20 | for (int i = 0; i < n; i++) { 21 | if (S.charAt(i) == C) { 22 | pos = i; 23 | } 24 | res[i] = i - pos; 25 | } 26 | for (int i = n - 1; i >= 0; --i) { 27 | if (S.charAt(i) == C) { 28 | pos = i; 29 | } 30 | res[i] = Math.min(res[i], Math.abs(i - pos)); 31 | } 32 | return res; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/动态规划/GameDP/PredicttheWinner_486.java: -------------------------------------------------------------------------------- 1 | package 动态规划.GameDP; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/5 下午6:01 6 | *

7 | * 预测赢家 8 | * 9 | * 与877题.石子游戏 相同 10 | */ 11 | public class PredicttheWinner_486 { 12 | 13 | public boolean PredictTheWinner(int[] nums) { 14 | int n = nums.length; 15 | //dp[i][j]保存第一个动作玩家从i到j得到的分数比第二个玩家多多少 16 | int[][] dp = new int[n][n]; 17 | for (int i = 0; i < n; i++) 18 | dp[i][i] = nums[i]; 19 | for (int len = 1; len < n; len++) { 20 | for (int i = 0; i < n - len; i++) { 21 | int j = i + len; 22 | //每个玩家可以从数组的左端或右端选择一个数字c 23 | dp[i][j] = Math.max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1]); 24 | } 25 | } 26 | return dp[0][n - 1] >= 0; 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/动态规划/MatrixDP/UniquePaths_62.java: -------------------------------------------------------------------------------- 1 | package 动态规划.MatrixDP; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/5 上午10:09 6 | *

7 | * 不同路径(模版) 8 | *

9 | * 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角 ,问总共有多少条不同的路径? 10 | */ 11 | public class UniquePaths_62 { 12 | 13 | public int uniquePaths(int m, int n) { 14 | if (m == 0 || n == 0) return 0; 15 | int[][] dp = new int[m][n]; 16 | //初始化第一行第一列某个位置的来源都只有一种情况 17 | for (int i = 0; i < m; i++) 18 | dp[i][0] = 1; 19 | for (int j = 0; j < n; j++) 20 | dp[0][j] = 1; 21 | for (int i = 1; i < m; i++) { 22 | for (int j = 1; j < n; j++) { 23 | // 要么从上边来,要么从左边来 24 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 25 | } 26 | } 27 | return dp[m - 1][n - 1]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/排序/八大排序/Insertion.java: -------------------------------------------------------------------------------- 1 | package 排序.八大排序; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/4 14:17 6 | * @Description: 插入排序 7 | *

8 | * 插入排序从左到右进行,每次都将当前元素插入到左侧已经排序的数组中,使得插入之后左部数组依然有序。 9 | * 第 j 元素是通过不断向左比较并交换来实现插入过程:当第 j 元素小于第 j - 1 元素,就将它们的位置交换,然后令 j 指针向左移动一个位置,不断进行以上操作。 10 | */ 11 | public class Insertion extends Base { 12 | 13 | public static void sort(int[] a) { 14 | int N = a.length; 15 | for (int i = 1; i < N; i++) { 16 | for (int j = i; j > 0 && compare(a[j], a[j - 1]); j--) { 17 | swap(a, j, j - 1); 18 | } 19 | } 20 | } 21 | 22 | public static void main(String[] args) { 23 | int[] a = {1, 5, 8, 6, 6, 2, 2, 3, 33, 4, 4}; 24 | Insertion.sort(a); 25 | for (int i : a) { 26 | System.out.println(i); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/数学/PalindromeNumber_9.java: -------------------------------------------------------------------------------- 1 | package 数学; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/4/5 9:57 AM 6 | * 7 | * 回文数 8 | * 9 | * 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 10 | */ 11 | public class PalindromeNumber_9 { 12 | /** 13 | * 思路:如果 计算 1221 / 1000, 则可得首位1, 如果 1221 % 10, 则可得到末尾1,进行比较,然后把中间的22取出继续比较。 14 | */ 15 | public boolean isPalindrome(int x) { 16 | if (x < 0) 17 | return false; 18 | int div = 1; 19 | while (x / div >= 10) 20 | div *= 10;// 取数字的首位数字 21 | while (x > 0) { 22 | int left = x / div; 23 | int right = x % 10; 24 | if (left != right) 25 | return false; 26 | x = (x % div) / 10; // 去掉头和尾 27 | div /= 100; // div除于两位 28 | } 29 | return true; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/数学/DiStringMatch_942.java: -------------------------------------------------------------------------------- 1 | package 数学; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2018/12/22 下午12:33 8 | * 9 | * 增减字符串匹配 10 | */ 11 | public class DiStringMatch_942 { 12 | public static void main(String[] args) { 13 | DiStringMatch_942 s =new DiStringMatch_942(); 14 | System.out.println(Arrays.toString(s.diStringMatch("III"))); 15 | } 16 | 17 | public int[] diStringMatch(String S) { 18 | int n = S.length(); 19 | int[] str = new int[n + 1]; 20 | int left =0; 21 | int right = n; 22 | char[] chars = S.toCharArray(); 23 | for (int i=0;i< n;i++){ 24 | str[i] = chars[i] == 'I'?left++:right--; 25 | } 26 | int i = str[n - 1]; 27 | str[n] = chars[n-1] == 'I'? i+1:i-1; 28 | return str; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/数组/TwoSum_1.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/4/5 10:01 AM 8 | * 9 | * 两数之和 10 | * 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标 11 | */ 12 | public class TwoSum_1 { 13 | public int[] twoSum(int[] nums, int target) { 14 | 15 | if (nums == null) { 16 | return null; 17 | } 18 | HashMap map = new HashMap<>(); 19 | for (int i = 0; i < nums.length; i++) { 20 | map.put(nums[i], i); 21 | } 22 | for (int i = 0; i < nums.length; i++) { 23 | if (map.get(target - nums[i]) != null && map.get(target - nums[i]) != i) { 24 | return new int[] { i, map.get(target - nums[i]) }; 25 | 26 | } 27 | } 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/链表/合并/MergeTwoLists_21.java: -------------------------------------------------------------------------------- 1 | package 链表.合并; 2 | 3 | 4 | /** 5 | * Created by jiangyunxiong on 2018/5/2. 6 | */ 7 | public class MergeTwoLists_21 { 8 | /** 9 | * 合并两个有序链 10 | * @param l1 11 | * @param l2 12 | * @return 13 | */ 14 | public ListNode mergeTwoLists(ListNode l1, ListNode l2){ 15 | if (l1 == null) return l2; 16 | if (l2 == null) return l1; 17 | if(l1.val < l2.val){ 18 | l1.next = mergeTwoLists(l1.next, l2); 19 | return l1; 20 | }else { 21 | l2.next = mergeTwoLists(l1, l2.next); 22 | return l2; 23 | } 24 | } 25 | class ListNode { 26 | public int val; 27 | public ListNode next; 28 | 29 | public ListNode(int x) { 30 | val = x; 31 | next = null; 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/kSum/TwoSum_1.java: -------------------------------------------------------------------------------- 1 | package kSum; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/14 下午8:14 8 | * 9 | * 两数之和 10 | * 11 | * 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。 12 | */ 13 | public class TwoSum_1 { 14 | 15 | public int[] twoSum(int[] nums, int target) { 16 | 17 | if (nums == null) { 18 | return null; 19 | } 20 | HashMap map = new HashMap<>(); 21 | for (int i = 0; i < nums.length; i++) { 22 | map.put(nums[i], i); 23 | } 24 | for (int i = 0; i < nums.length; i++) { 25 | if (map.get(target - nums[i]) != null && map.get(target - nums[i]) != i) { 26 | return new int[]{i, map.get(target - nums[i])}; 27 | 28 | } 29 | } 30 | return null; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/二叉树/搜索/LowestCommonAncestorofBinaryTree_236.java: -------------------------------------------------------------------------------- 1 | package 二叉树.搜索; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/3 下午8:47 6 | * 7 | * 二叉树的最小公共祖先 8 | */ 9 | public class LowestCommonAncestorofBinaryTree_236 { 10 | class TreeNode { 11 | int val; 12 | TreeNode left; 13 | TreeNode right; 14 | TreeNode(int x) { val = x; } 15 | } 16 | 17 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 18 | if(root == null) return null; 19 | if(p == root || q == root) return root; 20 | 21 | TreeNode left = lowestCommonAncestor(root.left, p, q); 22 | TreeNode right = lowestCommonAncestor(root.right, p, q); 23 | 24 | if(left != null && right != null){ 25 | return root; 26 | } 27 | return left == null ? right : left; 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/字符串/LongestSubstringWithoutRepeatingCharacters_3.java: -------------------------------------------------------------------------------- 1 | package 字符串; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2019/1/23 下午10:44 9 | * 无重复字符的最长子串 10 | * 11 | * 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 12 | */ 13 | public class LongestSubstringWithoutRepeatingCharacters_3 { 14 | public int lengthOfLongestSubstring(String s) { 15 | int n = s.length(); 16 | int res = 0; 17 | int end = 0, start = 0; 18 | Set set = new HashSet<>(); 19 | while(start 8 | * 选择出数组中的最小元素,将它与数组的第一个元素交换位置。再从剩下的元素中选择出最小的元素, 9 | * 将它与数组的第二个元素交换位置。不断进行这样的操作,直到将整个数组排序。 10 | */ 11 | public class Selection extends Base { 12 | 13 | public static void sort(int[] a) { 14 | int N = a.length; 15 | for (int i = 0; i < N; i++) { 16 | int min = i; 17 | for (int j = i + 1; j < N; j++) 18 | if (compare(a[j], a[min])) 19 | min = j; 20 | swap(a, i, min); 21 | } 22 | } 23 | 24 | public static void main(String[] args) { 25 | int[] a = {1, 5, 8, 6, 6, 2, 2, 3, 33, 4, 4}; 26 | Selection.sort(a); 27 | for (int i : a) { 28 | System.out.println(i); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/数学/AddBinary_67.java: -------------------------------------------------------------------------------- 1 | package 数学; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/4/5 9:36 AM 6 | * 7 | * 二进制求和 8 | * 9 | * 给定两个二进制字符串,返回他们的和(用二进制表示) 10 | */ 11 | public class AddBinary_67 { 12 | /** 13 | * 用了两个指针分别指向a和b的末尾,然后每次取出一个字符,转为数字,若无法取出字符则按0处理,然后定义进位carry,初始化为0,将三者加起来,对2取余即为当前位的数字,对2取商即为当前进位的值,记得最后还要判断下carry,如果为1的话,要在结果最前面加上一个1。 14 | */ 15 | public String addBinary(String a, String b) { 16 | String res = ""; 17 | int m = a.length() - 1, n = b.length() - 1, carry = 0; 18 | while (m >= 0 || n >= 0) { 19 | int p = m >= 0 ? a.charAt(m--) - '0' : 0; 20 | int q = n >= 0 ? b.charAt(n--) - '0' : 0; 21 | int sum = p + q + carry; 22 | res = String.valueOf(sum % 2) + res;//当前数 23 | carry = sum / 2; //进位数 24 | } 25 | return carry == 1 ? "1" + res : res; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/深度优先搜索/TreePostorderTraversal_590.java: -------------------------------------------------------------------------------- 1 | package 深度优先搜索; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/22 下午5:30 9 | * 10 | * N叉树的后序遍历 11 | */ 12 | public class TreePostorderTraversal_590 { 13 | class Node { 14 | public int val; 15 | public List children; 16 | 17 | public Node() { 18 | } 19 | 20 | public Node(int _val, List _children) { 21 | val = _val; 22 | children = _children; 23 | } 24 | } 25 | 26 | List list = new ArrayList<>(); 27 | 28 | public List postorder(Node root) { 29 | if (root != null) { 30 | for(Node n : root.children){ 31 | postorder(n); 32 | } 33 | list.add(root.val); 34 | } 35 | return list; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/双指针/ContainerWithMostWater_11.java: -------------------------------------------------------------------------------- 1 | package 双指针; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/23 下午10:07 6 | */ 7 | public class ContainerWithMostWater_11 { 8 | /** 9 | * 由于桶的容量由最短的那个木板决定: Vol = min(h[left],h[right]) * (right - left) 10 | * 11 | * left和right都向中央移动,每次移动left和Right中间高度较小的(因为反正都是移动一次,宽度肯定缩小1,这时候只能指望高度增加来增加容量,肯定是替换掉高度较小的,才有可能找到更大的容量。) 12 | * 13 | * 看新桶子的容量是不是大于Vol_max,直到left和right相交。 14 | */ 15 | public int maxArea(int[] height) { 16 | int l = 0, r = height.length-1; 17 | int i = height[l] > height[r] ? r:l; 18 | int vol, vol_max = height[i]*(r-l); 19 | while(lvol_max) vol_max = vol; 24 | } 25 | return vol_max; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/深度优先搜索/TreePreorderTraversal_589.java: -------------------------------------------------------------------------------- 1 | package 深度优先搜索; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/22 下午5:21 9 | * 10 | * N叉树的前序遍历 11 | */ 12 | public class TreePreorderTraversal_589 { 13 | class Node { 14 | public int val; 15 | public List children; 16 | 17 | public Node() { 18 | } 19 | 20 | public Node(int _val, List _children) { 21 | val = _val; 22 | children = _children; 23 | } 24 | } 25 | 26 | 27 | List list = new ArrayList<>(); 28 | 29 | public List preorder(Node root) { 30 | if (root != null) { 31 | list.add(root.val); 32 | for(Node n : root.children){ 33 | preorder(n); 34 | } 35 | } 36 | return list; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/栈/SimplifyPath_71.java: -------------------------------------------------------------------------------- 1 | package 栈; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/3 下午11:04 8 | *

9 | * 问题:解析linux路径,有”.”表示不变和”..”表示回上层。 10 | */ 11 | public class SimplifyPath_71 { 12 | public String simplifyPath(String path) { 13 | Stack stack = new Stack<>(); 14 | String[] paths = path.split("/+"); 15 | for (String s : paths) { 16 | if (s.equals("..")) { 17 | if (!stack.isEmpty()) { 18 | stack.pop(); 19 | } 20 | } else if (!s.equals(".") && !s.equals("")) { 21 | stack.push(s); 22 | } 23 | } 24 | String res = ""; 25 | while (!stack.isEmpty()) { 26 | res = "/" + stack.pop() + res; 27 | } 28 | if (res.length() == 0) return "/"; 29 | return res; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/数组/BitAnd2bitCharacters_717.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/25 上午12:09 6 | *

7 | * 1比特与2比特字符 8 | * 9 | * 因为两种字符互不干扰,只要我们遍历到了数字1,那么其必定是两位字符,所以后面一位也得跟着,而遍历到了数字0,那么就必定是单个位字符。所以我们可以用一个变量i来记录当前遍历到的位置,如果遇到了0,那么i自增1,如果遇到了1,那么i自增2,我们循环的条件是i < n-1,即留出最后一位,所以当循环退出后,当i正好停留在n-1上,说明最后一位是单独分割开的,因为题目中限定了最后一位一定是0,所以没必要再判断了 10 | */ 11 | public class BitAnd2bitCharacters_717 { 12 | 13 | public static void main(String[] args) { 14 | BitAnd2bitCharacters_717 b = new BitAnd2bitCharacters_717(); 15 | int[] str = {0, 1, 0}; 16 | System.out.println(b.isOneBitCharacter(str)); 17 | } 18 | 19 | public boolean isOneBitCharacter(int[] bits) { 20 | 21 | int n = bits.length, i = 0; 22 | while (i < n - 1) { 23 | if (bits[i] == 0) ++i; 24 | else i+= 2; 25 | } 26 | return i == n - 1; 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/数组/IntersectionTwoArrays_349.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/26 下午8:08 9 | * 10 | * 两个数组的交集 11 | */ 12 | public class IntersectionTwoArrays_349 { 13 | public int[] intersection(int[] nums1, int[] nums2) { 14 | Set set = new HashSet<>(); 15 | Set intersect = new HashSet<>(); 16 | for (int i = 0; i < nums1.length; i++) { 17 | set.add(nums1[i]); 18 | } 19 | for (int i = 0; i < nums2.length; i++) { 20 | if (set.contains(nums2[i])) { 21 | intersect.add(nums2[i]); 22 | } 23 | } 24 | int[] result = new int[intersect.size()]; 25 | int i = 0; 26 | for (Integer num : intersect) { 27 | result[i++] = num; 28 | } 29 | return result; 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/动态规划/SequenceDP/LongestIncreasingSubsequence_300.java: -------------------------------------------------------------------------------- 1 | package 动态规划.SequenceDP; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/1 上午1:40 6 | *

7 | * 最长上升子序列(DP + 二分) 8 | *

9 | * b[i]=max(b[i],b[j]+1); 10 | */ 11 | public class LongestIncreasingSubsequence_300 { 12 | 13 | 14 | public int lengthOfLIS(int[] nums) { 15 | int i, j, max, n = nums.length; 16 | int[] b = new int[100000]; 17 | b[0] = 1;//以a[0]结尾的最长递增子序列长度为1 18 | for (i = 1; i < n; i++) { 19 | b[i] = 1;//b[i]最小值为1 20 | for (j = 0; j < i; j++) { 21 | if (nums[i] > nums[j]) { 22 | b[i] = Math.max(b[i], b[j] + 1); 23 | } 24 | } 25 | } 26 | for (max = i = 0; i < n; i++) { 27 | if (b[i] > max) { 28 | max = b[i]; 29 | } 30 | } 31 | return max; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/深度优先搜索/IncreasingOrderSearchTree_897.java: -------------------------------------------------------------------------------- 1 | package 深度优先搜索; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/23 下午2:07 6 | * 7 | * 递增顺序查找树 8 | */ 9 | public class IncreasingOrderSearchTree_897 { 10 | 11 | TreeNode newTree, head; 12 | 13 | public TreeNode increasingBST(TreeNode root) { 14 | 15 | newTree = new TreeNode(0); 16 | head = newTree; 17 | traversal(root); 18 | return head.right; 19 | } 20 | 21 | private void traversal(TreeNode root){ 22 | if (root == null) 23 | return; 24 | 25 | traversal(root.left); 26 | newTree.right = new TreeNode(root.val); 27 | newTree = newTree.right; 28 | traversal(root.right); 29 | } 30 | 31 | 32 | class TreeNode { 33 | int val; 34 | TreeNode left; 35 | TreeNode right; 36 | 37 | TreeNode(int x) { 38 | val = x; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/栈/NextGreaterElementI_496.java: -------------------------------------------------------------------------------- 1 | package 栈; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Stack; 6 | 7 | /** 8 | * @Author jiangyunxiong 9 | * @Date 2018/12/23 下午8:23 10 | * 11 | * 下一个更大元素 I 12 | */ 13 | public class NextGreaterElementI_496 { 14 | 15 | public int[] nextGreaterElement(int[] nums1, int[] nums2) { 16 | 17 | Map map = new HashMap<>(); 18 | Stack stack = new Stack<>(); 19 | 20 | 21 | int[] res = new int[nums1.length]; 22 | 23 | for (int i = 0; i < nums2.length; i++) { 24 | while(!stack.isEmpty()&&stack.peek() 7 | * Bottom-up 提前阻断法(复杂度 O(N)) 8 | * 在对root做dfs时,会从下至上获得每个root的左右子树高度,当我们发现有一例左右子树高度差 >1的情况时return -1,代表此树不是平衡树,后面的高度计算都没有意义了,之后一路return -1,不再做后面的DFS。 9 | */ 10 | public class BalanceTree_110 { 11 | class TreeNode { 12 | int val; 13 | TreeNode left; 14 | TreeNode right; 15 | 16 | TreeNode(int x) { 17 | val = x; 18 | } 19 | } 20 | 21 | public boolean isBalanced(TreeNode root) { 22 | return height(root) != -1; 23 | } 24 | 25 | private int height(TreeNode root) { 26 | if (root == null) return 0; 27 | int left = height(root.left); 28 | if (left == -1) return -1; 29 | int right = height(root.right); 30 | if (right == -1 || Math.abs(left - right) > 1) return -1; 31 | return Math.max(left, right) + 1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/字符串/UniqueMorseRepresentations_804.java: -------------------------------------------------------------------------------- 1 | package 字符串; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/22 上午10:42 9 | * 10 | * 唯一摩尔斯密码词 11 | */ 12 | public class UniqueMorseRepresentations_804 { 13 | public int uniqueMorseRepresentations(String[] words) { 14 | 15 | String[] map = new String[]{".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."}; 16 | 17 | 18 | Set set = new HashSet<>(); 19 | 20 | for (String s : words) { 21 | StringBuilder sb = new StringBuilder(); 22 | char[] chars = s.toCharArray(); 23 | for (int i = 0; i < chars.length; i++) { 24 | sb.append(map[chars[i]-'a']); 25 | } 26 | set.add(sb.toString()); 27 | } 28 | return set.size(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/排序/八大排序/Bubble.java: -------------------------------------------------------------------------------- 1 | package 排序.八大排序; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/4 14:16 6 | * @Description: 冒泡排序 7 | *

8 | * 通过从左到右不断交换相邻逆序的相邻元素,在一轮的交换之后,可以让未排序的元素上浮到最右侧,是的右侧是已排序的。 9 | * 在一轮交换中,如果没有发生交换,就说明数组已经是有序的,此时可以直接退出。 10 | */ 11 | public class Bubble extends Base { 12 | 13 | public static void sort(int[] a) { 14 | int N = a.length; 15 | boolean hasSorted = false; 16 | for (int i = 0; i < N && !hasSorted; i++) { 17 | hasSorted = true; 18 | for (int j = 0; j < N - i - 1; j++) { 19 | if (compare(a[j + 1], a[j])) { 20 | hasSorted = false; 21 | swap(a, j, j + 1); 22 | } 23 | } 24 | } 25 | } 26 | 27 | public static void main(String[] args) { 28 | int[] a = {1, 5, 8, 6, 6, 2, 2, 3, 33, 4, 4}; 29 | Bubble.sort(a); 30 | for (int i : a) { 31 | System.out.println(i); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/二分查找/BinarySearch_704.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/24 下午11:36 6 | * 7 | * 典型的二分查找 8 | * 时间复杂度:O(log2n) 9 | */ 10 | public class BinarySearch_704 { 11 | 12 | /** 13 | * 我们做二分查找类型的题时,会发现有时候没有等号while(l target) { 29 | right = mid - 1; 30 | } else if (num == target) { 31 | return mid; 32 | } else { 33 | left = mid + 1; 34 | } 35 | } 36 | return -1; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/排序/八大排序/Shell.java: -------------------------------------------------------------------------------- 1 | package 排序.八大排序; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/4 14:17 6 | * @Description: 希尔排序 7 | *

8 | * 对于大规模的数组,插入排序很慢,因为它只能交换相邻的元素,每次只能将逆序数量减少 1。 9 | * 希尔排序的出现就是为了改进插入排序的这种局限性,它通过交换不相邻的元素,每次可以将逆序数量减少大于 1。 10 | * 希尔排序使用插入排序对间隔 h 的序列进行排序。通过不断减小 h,最后令 h=1,就可以使得整个数组是有序的。 11 | */ 12 | public class Shell extends Base { 13 | 14 | public static void sort(int[] a) { 15 | int N = a.length; 16 | int h = 1; 17 | while (h < N / 3) 18 | h = 3 * h + 1; 19 | 20 | while (h >= 1) { 21 | for (int i = h; i < N; i++) 22 | for (int j = i; j >= h && compare(a[j], a[j - h]); j -= h) 23 | swap(a, j, j - h); 24 | h = h / 3; 25 | } 26 | } 27 | 28 | public static void main(String[] args) { 29 | int[] a = {1, 5, 8, 6, 6, 2, 2, 3, 33, 4, 4}; 30 | Shell.sort(a); 31 | for (int i : a) { 32 | System.out.println(i); 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/二分查找/Sum4_454.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/30 上午8:05 9 | * 10 | * 给定四个长度相同的数组,在每个数组中取一个数字,在所有的组合中和为零的组合有多少个? 11 | */ 12 | public class Sum4_454 { 13 | 14 | /** 15 | * 思路:把四个数组分为两组,每组包含两个数组。把其中一组中的任意两个值和存入hashmap中,然后在hashmap查找另外两个数组的值的组合。这其实是相当于转化为了一个two sum问题。 16 | */ 17 | public int fourSumCount(int[] A, int[] B, int[] C, int[] D) { 18 | 19 | Map map = new HashMap<>(); 20 | 21 | for (int i =0;i r = new ArrayList<>(); 13 | 14 | public ArrayList generateParenthesis(int n) { 15 | //保证左边‘(’的数量始终大于等于右边的‘)’数量,可以考虑回溯法 16 | gp("", 0, 0, n); 17 | return r; 18 | } 19 | 20 | private void gp(String s, int left, int right, int n) { 21 | if (right == n) { 22 | r.add(s); 23 | } 24 | if (left < n) { 25 | gp(s + "(", left + 1, right, n); 26 | // 递归过程中 左括号x的个数必须大于等于右括号个数 27 | if (left > right) { 28 | gp(s + ")", left, right + 1, n); 29 | } 30 | } 31 | } 32 | 33 | public static void main(String[] args) { 34 | GenerateParentheses_22 g = new GenerateParentheses_22(); 35 | System.out.println(g.generateParenthesis(2)); 36 | } 37 | } -------------------------------------------------------------------------------- /src/尺取法/MinSubArrayLen_209.java: -------------------------------------------------------------------------------- 1 | package 尺取法; 2 | 3 | /** 4 | * Created by jiangyunxiong on 2018/5/3. 5 | * 6 | * 长度最小的子数组 7 | * 8 | * 题目要求在一个正数数组中寻找一个连续的子数组,使得这个子数组的和值大于等于给定的s,并要求这个子数组的长度最小 9 | */ 10 | public class MinSubArrayLen_209 { 11 | 12 | 13 | public int minSubArrayLen(int s, int[] nums) { 14 | int n = nums.length, l = 0, r = 0, sum = 0, mlen = n + 1; 15 | while (true) { 16 | while (r < n && sum < s) { 17 | sum += nums[r]; 18 | r++; 19 | } 20 | if (sum < s) 21 | break; 22 | mlen = Math.min(mlen, r - 1); 23 | sum -= nums[l]; 24 | l++; 25 | } 26 | mlen = mlen == n + 1 ? 0 : mlen; 27 | return mlen; 28 | } 29 | 30 | public static void main(String[] args) { 31 | int[] arr = {2, 3, 1, 2, 4, 3}; 32 | int s = 7; 33 | MinSubArrayLen_209 m = new MinSubArrayLen_209(); 34 | System.out.println(m.minSubArrayLen(s, arr)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/链表/删除/RemoveNthNodeFromEndofList_19.java: -------------------------------------------------------------------------------- 1 | package 链表.删除; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/24 11:09 6 | * @Description: 删除链表的倒数第N个节点 7 | * 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 8 | * 给定一个链表: 1->2->3->4->5, 和 n = 2. 9 | *

10 | * 当删除了倒数第二个节点后,链表变为 1->2->3->5. 11 | */ 12 | public class RemoveNthNodeFromEndofList_19 { 13 | public class ListNode { 14 | int val; 15 | ListNode next; 16 | 17 | ListNode(int x) { 18 | val = x; 19 | } 20 | } 21 | 22 | 23 | public ListNode removeNthFromEnd(ListNode head, int n) { 24 | ListNode newhead = new ListNode(-1); 25 | newhead.next = head; 26 | remove(newhead, n); 27 | return newhead.next; 28 | } 29 | 30 | private int remove(ListNode node, int n) { 31 | if (node.next == null) return 1; 32 | int level = remove(node.next, n) + 1; //层数+1 33 | if (level == n+1){ 34 | node.next = node.next.next; 35 | } 36 | return level; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/贪心/MinimumNumberofArrowstoBurstBalloons_452.java: -------------------------------------------------------------------------------- 1 | package 贪心; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/20 下午10:27 9 | * 10 | * 投飞镖刺破气球 11 | * 12 | */ 13 | public class MinimumNumberofArrowstoBurstBalloons_452 { 14 | 15 | /** 16 | * 思路:先计算最多能组成的不重叠区间个数,然后用区间总个数减去不重叠区间的个数。 17 | */ 18 | public int findMinArrowShots(int[][] points) { 19 | if (points.length == 0){ 20 | return 0; 21 | } 22 | Arrays.sort(points, new Comparator() { 23 | @Override 24 | public int compare(int[] o1, int[] o2) { 25 | return o1[1] - o2[1]; 26 | } 27 | }); 28 | 29 | int num =1 , end = points[0][1]; 30 | for(int i=1;i 7 | * 最小路径和 8 | *

9 | * 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 10 | *

11 | * 说明:每次只能向下或者向右移动一步。 12 | */ 13 | public class MinimumPathSum_64 { 14 | 15 | public int minPathSum(int[][] grid) { 16 | if (grid == null || grid.length == 0 || grid[0].length == 0) return -1; 17 | int m = grid.length; 18 | int n = grid[0].length; 19 | int[][] dp = new int[m][n]; 20 | //初始化 21 | dp[0][0] = grid[0][0]; 22 | for (int i = 1; i < m; i++) dp[i][0] = dp[i - 1][0] + grid[i][0]; 23 | for (int j = 1; j < n; j++) dp[0][j] = dp[0][j - 1] + grid[0][j]; 24 | 25 | for (int i = 1; i < m; i++) { 26 | for (int j = 1; j < n; j++) { 27 | // 要么从上边来,要么从左边来 28 | dp[i][j] = grid[i][j] + Math.min(dp[i - 1][j], dp[i][j - 1]); 29 | } 30 | } 31 | return dp[m - 1][n - 1]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/数组/FizzBuzz_412.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/23 下午8:03 9 | *

10 | * 写一个程序,输出从 1 到 n 数字的字符串表示。 11 | *

12 | * 1. 如果 n 是3的倍数,输出“Fizz”; 13 | *

14 | * 2. 如果 n 是5的倍数,输出“Buzz”; 15 | *

16 | * 3.如果 n 同时是3和5的倍数,输出 “FizzBuzz”。 17 | */ 18 | public class FizzBuzz_412 { 19 | public static void main(String[] args) { 20 | FizzBuzz_412 f = new FizzBuzz_412(); 21 | System.out.println(f.fizzBuzz(1)); 22 | } 23 | 24 | public List fizzBuzz(int n) { 25 | List res = new ArrayList<>(); 26 | for (int i = 1; i <= n; i++) { 27 | if (i % 3 == 0 && i % 5 == 0) { 28 | res.add("FizzBuzz"); 29 | } else if (i % 3 == 0) { 30 | res.add("Fizz"); 31 | } else if (i % 5 == 0) { 32 | res.add("Buzz"); 33 | } else { 34 | res.add(i + ""); 35 | } 36 | } 37 | return res; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/二叉树/构造/ConvertSortedArrayBinarySearchTree_108.java: -------------------------------------------------------------------------------- 1 | package 二叉树.构造; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/14 15:17 6 | * @Description: 把一个有序数组转换成一颗二分查找树 7 | */ 8 | public class ConvertSortedArrayBinarySearchTree_108 { 9 | 10 | 11 | /** 12 | * 思路:树的遍历 + 二分查找 13 | * 把中间元素转化为根,然后递归构造左右子树 14 | * @param nums 15 | * @return 16 | */ 17 | public TreeNode sortedArrayToBST(int[] nums) { 18 | if (nums == null || nums.length == 0) return null; 19 | 20 | return helper(nums, 0, nums.length - 1); 21 | } 22 | 23 | private TreeNode helper(int[] nums, int l, int r) { 24 | if (l > r) return null; 25 | int m = l + (r - l) / 2; 26 | TreeNode root = new TreeNode(nums[m]); 27 | root.left = helper(nums, l, m - 1); 28 | root.right = helper(nums, m + 1, r); 29 | return root; 30 | } 31 | 32 | class TreeNode { 33 | int val; 34 | TreeNode left; 35 | TreeNode right; 36 | 37 | TreeNode(int x) { 38 | val = x; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/栈/ImplementStackusingQueues_225.java: -------------------------------------------------------------------------------- 1 | package 栈; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2019/1/3 下午9:47 9 | * 10 | * 用队列实现栈 11 | */ 12 | public class ImplementStackusingQueues_225 { 13 | 14 | private Queue queue = new LinkedList<>(); 15 | 16 | 17 | /** 18 | * Push element x onto stack. 19 | */ 20 | public void push(int x) { 21 | queue.offer(x); 22 | // 入队后反转 23 | for (int i = 1; i < queue.size(); i++) { 24 | queue.add(queue.poll()); 25 | } 26 | } 27 | 28 | /** 29 | * Removes the element on top of the stack and returns that element. 30 | */ 31 | public int pop() { 32 | return queue.poll(); 33 | } 34 | 35 | /** 36 | * Get the top element. 37 | */ 38 | public int top() { 39 | return queue.peek(); 40 | } 41 | 42 | /** 43 | * Returns whether the stack is empty. 44 | */ 45 | public boolean empty() { 46 | return queue.isEmpty(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/二叉树/搜索/MinimumAbsoluteDifferenceinBST_530.java: -------------------------------------------------------------------------------- 1 | package 二叉树.搜索; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/24 下午10:43 6 | *

7 | * 二叉搜索树的最小绝对差 8 | * 9 | * 给定一个所有节点为非负值的二叉搜索树,求树中任意两节点的差的绝对值的最小值 10 | */ 11 | public class MinimumAbsoluteDifferenceinBST_530 { 12 | 13 | int min = Integer.MAX_VALUE; 14 | Integer prev = null; 15 | 16 | /** 17 | * 思路:中序遍历二分搜索树,计算当前节点数据与上一个节点数据的绝对值的差值,遍历结束返回最小的绝对值差值 18 | * 时间复杂度:O(n) 19 | * 空间复杂度:O(1) 20 | */ 21 | public int getMinimumDifference(TreeNode root) { 22 | 23 | if (root == null) { 24 | return min; 25 | } 26 | getMinimumDifference(root.left); 27 | if (prev != null) { 28 | min = Math.min(min, root.val - prev); 29 | } 30 | prev = root.val; 31 | getMinimumDifference(root.right); 32 | return min; 33 | } 34 | 35 | class TreeNode { 36 | int val; 37 | TreeNode left; 38 | TreeNode right; 39 | 40 | TreeNode(int x) { 41 | val = x; 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/数学/SelfDividingNumbers_728.java: -------------------------------------------------------------------------------- 1 | package 数学; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/22 下午1:31 9 | * 10 | * 自除数 是指可以被它包含的每一位数除尽的数。 11 | */ 12 | public class SelfDividingNumbers_728 { 13 | public List selfDividingNumbers(int left, int right) { 14 | List list = new ArrayList<>(); 15 | for (int i = left; i <= right; i++) { 16 | if (i < 10) { 17 | list.add(i); 18 | continue; 19 | } 20 | if (vaild(i)){ 21 | list.add(i); 22 | } 23 | } 24 | return list; 25 | } 26 | 27 | private boolean vaild(int n) { 28 | int cache = n; 29 | while (n > 1) { 30 | int remain = n%10; 31 | if (remain == 0){ 32 | return false; 33 | } 34 | if (cache % remain != 0){ 35 | return false; 36 | } 37 | n = (n -remain) /10; 38 | } 39 | return true; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/other/链表/RemoveLastKthNode.java: -------------------------------------------------------------------------------- 1 | package other.链表; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/26 11:38 6 | * @Description: 在单链表和双链表中删除倒数第k个节点 7 | */ 8 | public class RemoveLastKthNode { 9 | class Node { 10 | public int value; 11 | public Node next; 12 | 13 | public Node(int data){ 14 | this.value = data; 15 | } 16 | } 17 | 18 | /** 19 | * @param head 20 | * @param lastKth 21 | * @return 22 | */ 23 | public Node removeLastKthNode(Node head,int lastKth){ 24 | if (head == null || lastKth < 1){ 25 | return head; 26 | } 27 | Node cur = head; 28 | while (cur != null){ 29 | lastKth--; 30 | cur = cur.next; 31 | } 32 | if (lastKth == 0){ 33 | head = head.next; 34 | } 35 | if (lastKth < 0){ 36 | cur = head; 37 | while (++lastKth != 0){ 38 | cur = cur.next; 39 | } 40 | cur.next = cur.next.next; 41 | } 42 | return head; 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/栈/MinStack_155.java: -------------------------------------------------------------------------------- 1 | package 栈; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/3 下午9:53 8 | *

9 | * 问题:设计一个能返回栈中最小值的栈结构。 10 | *

11 | * 思路:考虑使用另一个辅助栈,用来存储[0..i]的最小值。 12 | */ 13 | public class MinStack_155 { 14 | 15 | private LinkedList list = new LinkedList(); // 存储压入栈中的所有值 16 | private LinkedList mins = new LinkedList(); // 存储当前栈中的最小值 17 | 18 | 19 | public void push(int x) { 20 | //如果最小值栈中没有值,或者当前元素x比最小值栈中的最小值还要小,则把x放入最小值栈中 21 | if (mins.size() < 1 || mins.getLast() >= x) { 22 | mins.add(x); 23 | } 24 | list.add(x); 25 | } 26 | 27 | public void pop() { 28 | // pop 的时候,有可能 pop 出的是当前栈中的最小值。因此在 pop 函数操作时,需同时操作维护最小值的 linkedlist 29 | if (list.getLast().equals(mins.getLast())) { 30 | mins.removeLast(); 31 | } 32 | list.removeLast(); 33 | } 34 | 35 | public int top() { 36 | return list.getLast(); 37 | } 38 | 39 | public int getMin() { 40 | return mins.getLast(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/并查集/BinaryTreeLevelOrderTraversal_107.java: -------------------------------------------------------------------------------- 1 | package 并查集; 2 | 3 | 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @Author jiangyunxiong 9 | * @Date 2018/12/31 下午3:19 10 | * 11 | * 二叉树的层序遍历(从下到上) 12 | */ 13 | public class BinaryTreeLevelOrderTraversal_107 { 14 | public List> levelOrderBottom(TreeNode root) { 15 | List> wrapList = new LinkedList>(); 16 | levelMaker(wrapList, root, 0); 17 | return wrapList; 18 | } 19 | 20 | private void levelMaker(List> list, TreeNode root, int level) { 21 | if (root == null) return; 22 | if (level >= list.size()) 23 | list.add(0, new LinkedList()); 24 | levelMaker(list, root.left, level + 1); 25 | levelMaker(list, root.right, level + 1); 26 | list.get(list.size() - level - 1).add(root.val); 27 | } 28 | 29 | class TreeNode { 30 | int val; 31 | TreeNode left; 32 | TreeNode right; 33 | 34 | TreeNode(int x) { 35 | val = x; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/动态规划/TwoSequencesDP/EditDistance_72.java: -------------------------------------------------------------------------------- 1 | package 动态规划.TwoSequencesDP; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/5 下午12:54 6 | * 7 | * 问题:给出两个单词word1和word2,计算出将word1 转换为word2的最少操作次数。你总共三种操作方法:插入一个字符、删除一个字符、替换一个字符。 8 | */ 9 | public class EditDistance_72 { 10 | 11 | public int minDistance(String word1, String word2) { 12 | int m = word1.length(); 13 | int n = word2.length(); 14 | //dp[i][j]表示word1的第i个字符匹配上word2的前j个字符 15 | int[][] dp = new int[m + 1][n + 1]; 16 | //删除i个字符 17 | for (int i = 0; i < m + 1; i++) dp[i][0] = i; 18 | //删除j个字符 19 | for (int j = 0; j < n + 1; j++) dp[0][j] = j; 20 | 21 | for (int i = 1; i < m + 1; i++) { 22 | for (int j = 1; j < n + 1; j++) { 23 | if (word1.charAt(i - 1) == word2.charAt(j - 1)) { 24 | dp[i][j] = dp[i - 1][j - 1]; 25 | } else { 26 | dp[i][j] = 1 + Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])); 27 | } 28 | } 29 | } 30 | return dp[m][n]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/数组/SortArrayByParityII_922.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/22 下午4:31 6 | * 7 | * 按奇偶排序数组 II 8 | */ 9 | public class SortArrayByParityII_922 { 10 | public static void main(String[] args) { 11 | SortArrayByParityII_922 s = new SortArrayByParityII_922(); 12 | int[] ints = s.sortArrayByParityII(new int[]{2, 4, 5, 6, 3, 1, 7, 8}); 13 | for (int i : ints) { 14 | System.out.println(i); 15 | } 16 | } 17 | 18 | public int[] sortArrayByParityII(int[] A) { 19 | int i = 0, j = 1, n = A.length; 20 | while (i < n && j < n) { 21 | while (i < n && A[i] % 2 == 0) { 22 | i += 2; 23 | } 24 | while (j < n && A[j] % 2 == 1) { 25 | j += 2; 26 | } 27 | if (i < n && j < n) { 28 | swap(A, i, j); 29 | } 30 | } 31 | return A; 32 | } 33 | 34 | 35 | private void swap(int[] A, int i, int j) { 36 | int temp = A[i]; 37 | A[i] = A[j]; 38 | A[j] = temp; 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/动态规划/GameDP/HouseRobber_198.java: -------------------------------------------------------------------------------- 1 | package 动态规划.GameDP; 2 | 3 | /** 4 | * Created by jiangyunxiong on 2018/5/2. 5 | *

6 | * 抢劫一排住户,但是不能抢邻近的住户,求最大抢劫量 7 | */ 8 | public class HouseRobber_198 { 9 | 10 | /** 11 | * 定义 dp 数组用来存储最大的抢劫量,其中 dp[i] 表示抢到第 i 个住户时的最大抢劫量。由于不能抢劫邻近住户,因此如果抢劫了第 i 个住户那么只能抢劫 i - 2 和 i - 3 的住户,所以 12 | */ 13 | public int rob(int[] nums) { 14 | int n = nums.length; 15 | /** 16 | * 初始化前面三个,因为前面三个是固定 17 | */ 18 | if (n == 0) return 0; 19 | if (n == 1) return nums[0]; 20 | if (n == 2) return Math.max(nums[0], nums[1]); 21 | int[] dp = new int[n]; 22 | dp[0] = nums[0]; 23 | dp[1] = nums[1]; 24 | dp[2] = nums[0] + nums[2]; 25 | for (int i = 3; i < n; i++) { 26 | dp[i] = Math.max(dp[i - 2], dp[i - 3]) + nums[i]; 27 | } 28 | return Math.max(dp[n - 1], dp[n - 2]); 29 | } 30 | 31 | public static void main(String[] args) { 32 | HouseRobber_198 dp = new HouseRobber_198(); 33 | int[] str = {1, 2, 3, 1}; 34 | System.out.println(dp.rob(str)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/二分查找/ArrangeCoins_441.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * Created by jiangyunxiong on 2018/5/2. 5 | * 摆硬币 6 | * 你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。给定一个数字 n,找出可形成完整阶梯行的总行数。 7 | */ 8 | public class ArrangeCoins_441 { 9 | 10 | /** 11 | * 解法一 12 | *

13 | * 时间复杂度:O(log2n) 14 | * 思路:因为每个行硬币个数是逐行递增,所以使用二分查找,比较前mid行之和 与 n ,如果相等返回mid 15 | */ 16 | public int arrangeCoins(int n) { 17 | int l = 0, r = n; 18 | while (l <= r) { 19 | int mid = l + (r - l) / 2; 20 | int sqrt = mid * (mid + 1) / 2;//前mid行之和 21 | if (sqrt == n) 22 | return mid; 23 | if (sqrt < n) 24 | l = mid + 1; 25 | else 26 | r = mid - 1; 27 | } 28 | return r; 29 | } 30 | 31 | /** 32 | * 解法二 33 | *

34 | * 时间复杂度:O(1) 35 | * 思路:充分利用了等差数列的性质,我们建立等式, n = (1 + x) * x / 2, 我们用一元二次方程的求根公式可以得到 x = (-1 + sqrt(8 * n + 1)) / 2, 然后取整后就是能填满的行数 36 | */ 37 | public int arrangeCoins2(int n) { 38 | return (int) ((-1 + Math.sqrt(1 + 8 * (long) n)) / 2); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/链表/反转/ReverseList_77.java: -------------------------------------------------------------------------------- 1 | package 链表.反转; 2 | 3 | 4 | /** 5 | * Created by jiangyunxiong on 2018/5/2. 6 | */ 7 | public class ReverseList_77 { 8 | 9 | /** 10 | * 链表反转 1、递归 11 | */ 12 | public ListNode reverseList(ListNode head) { 13 | if (head == null || head.next == null) 14 | return head; 15 | ListNode next = head.next; 16 | ListNode newHead = reverseList(next); 17 | next.next = head; 18 | head.next = null; 19 | return newHead; 20 | } 21 | 22 | /** 23 | * 链表反转 2、头插法 24 | */ 25 | public ListNode reverseList1(ListNode head){ 26 | ListNode newHead = new ListNode(-1); 27 | while(head != null){ 28 | ListNode next = head.next; 29 | head.next = newHead.next; 30 | newHead.next = head; 31 | head = next; 32 | } 33 | return newHead.next; 34 | } 35 | 36 | class ListNode { 37 | public int val; 38 | public ListNode next; 39 | 40 | public ListNode(int x) { 41 | val = x; 42 | next = null; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/二叉树/遍历/BinaryTreePreorderTraversal_144.java: -------------------------------------------------------------------------------- 1 | package 二叉树.遍历; 2 | import java.util.ArrayList; 3 | import java.util.List; 4 | import java.util.Stack; 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/2 下午10:03 8 | * 9 | * 二叉树前序遍历 10 | */ 11 | public class BinaryTreePreorderTraversal_144 { 12 | class TreeNode { 13 | int val; 14 | TreeNode left; 15 | TreeNode right; 16 | 17 | TreeNode(int x) { 18 | val = x; 19 | } 20 | } 21 | 22 | /** 23 | * 思路:用一个栈来实现,由于遍历过程中要先访问树的左子树,而后右子树,所以实现的时候先把根节点的右孩子入栈,而后是左孩子。 24 | */ 25 | public List preorderTraversal(TreeNode root) { 26 | 27 | List result = new ArrayList(); 28 | Stack s =new Stack<>(); 29 | if(root != null) 30 | s.push(root); 31 | 32 | while(!s.isEmpty()){ 33 | TreeNode temp = s.pop(); 34 | result.add(temp.val); 35 | 36 | if(temp.right!=null) 37 | s.push(temp.right); 38 | if(temp.left!=null) 39 | s.push(temp.left); 40 | } 41 | return result; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/链表/反转/RotateRight_61.java: -------------------------------------------------------------------------------- 1 | package 链表.反转; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/29 下午9:55 6 | * 旋转链表 7 | * 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。 8 | */ 9 | public class RotateRight_61 { 10 | class ListNode { 11 | int val; 12 | ListNode next; 13 | 14 | ListNode(int x) { 15 | val = x; 16 | } 17 | } 18 | 19 | /** 20 | * 思路: 21 | *

22 | * 1. 先求出整个链表的长度 23 | * 2. 根据k值找到需要移动的部分链表的前驱(l-n%l) 24 | * 3. 在前驱之后将链表断开,移动后半部分 25 | */ 26 | public ListNode rotateRight(ListNode head, int k) { 27 | if (head == null || head.next == null) return head; 28 | ListNode dummy = new ListNode(0); 29 | dummy.next = head; 30 | ListNode fast = dummy, slow = dummy; 31 | int i; 32 | for (i = 0; fast.next != null; i++) { 33 | fast = fast.next; 34 | } 35 | for (int j = i - k % i; j > 0; j--) { 36 | slow = slow.next; 37 | } 38 | fast.next = dummy.next;//翻转 39 | dummy.next = slow.next; 40 | slow.next = null; 41 | return dummy.next; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/二叉树/搜索/FindBottomLeftTreeValue_513.java: -------------------------------------------------------------------------------- 1 | package 二叉树.搜索; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/2 下午10:59 8 | * 9 | * 问题:找到二叉树的最后一层的最左边的值 10 | */ 11 | public class FindBottomLeftTreeValue_513 { 12 | class TreeNode { 13 | int val; 14 | TreeNode left; 15 | TreeNode right; 16 | TreeNode(int x) { val = x; } 17 | } 18 | public int findBottomLeftValue(TreeNode root) { 19 | int res = 0; 20 | if (root == null) return res; 21 | Queue queue = new LinkedList<>(); 22 | queue.offer(root); 23 | while (!queue.isEmpty()) { 24 | int size = queue.size(); 25 | for (int i = 0; i < size; i++) { 26 | TreeNode node = queue.poll(); 27 | // 每一次最左边结点值 28 | if(i == 0) res = node.val; 29 | if (node.left != null) 30 | queue.offer(node.left); 31 | if (node.right != null) 32 | queue.offer(node.right); 33 | } 34 | } 35 | return res; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/二叉树/搜索/MergeTrees_617.java: -------------------------------------------------------------------------------- 1 | package 二叉树.搜索; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/22 下午12:52 6 | * 7 | * 合并二叉树 8 | * 9 | * 合并的树的每一个点的值等于两个二叉树相对位置的点的值的合 10 | */ 11 | public class MergeTrees_617 { 12 | 13 | TreeNode n = null; 14 | 15 | /** 16 | * 思路:前序遍历两棵二叉树 17 | * 1、节点都为空,return null, 18 | * 2、有一个结点为空,取不为空的结点值作为结点值, 19 | * 3、两棵二叉树的结点都不为空时,取两个结点相加所得的值作为结点值 20 | */ 21 | public TreeNode mergeTrees(TreeNode t1, TreeNode t2) { 22 | 23 | if (t1 == null && t2 == null) { 24 | return null; 25 | } 26 | int val = (t1 == null ? 0 : t1.val) + (t2 == null ? 0 : t2.val); 27 | TreeNode newNode = new TreeNode(val); 28 | 29 | newNode.left = mergeTrees(t1 == null ? null : t1.left, t2 == null ? null : t2.left); 30 | newNode.right = mergeTrees(t1 == null ? null : t1.right, t2 == null ? null : t2.right); 31 | 32 | return newNode; 33 | } 34 | 35 | 36 | class TreeNode { 37 | int val; 38 | TreeNode left; 39 | TreeNode right; 40 | 41 | TreeNode(int x) { 42 | val = x; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/深度优先搜索/EmployeeImportance_690.java: -------------------------------------------------------------------------------- 1 | package 深度优先搜索; 2 | 3 | import java.util.HashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | /** 8 | * @Author jiangyunxiong 9 | * @Date 2018/12/29 下午9:54 10 | * 11 | * 员工的重要性 12 | */ 13 | public class EmployeeImportance_690 { 14 | class Employee { 15 | // It's the unique id of each node; 16 | // unique id of this employee 17 | public int id; 18 | // the importance value of this employee 19 | public int importance; 20 | // the id of direct subordinates 21 | public List subordinates; 22 | } 23 | 24 | 25 | Map employeeMap = new HashMap<>(); 26 | 27 | public int getImportance(List employees, int id) { 28 | 29 | for (Employee e : employees) { 30 | employeeMap.put(e.id, e); 31 | } 32 | return dfs(id); 33 | } 34 | 35 | private int dfs(int eid){ 36 | Employee employee = employeeMap.get(eid); 37 | int answer = employee.importance; 38 | for (int id:employee.subordinates){ 39 | answer += dfs(id); 40 | } 41 | return answer; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/数组/IntersectionTwoArraysII_350.java: -------------------------------------------------------------------------------- 1 | package 数组; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/26 下午8:26 9 | * 10 | * 两个数组的交集 II 11 | */ 12 | public class IntersectionTwoArraysII_350 { 13 | 14 | public int[] intersect(int[] nums1, int[] nums2) { 15 | HashMap map = new HashMap(); 16 | ArrayList result = new ArrayList(); 17 | for(int i = 0; i < nums1.length; i++) 18 | { 19 | if(map.containsKey(nums1[i])) map.put(nums1[i], map.get(nums1[i])+1); 20 | else map.put(nums1[i], 1); 21 | } 22 | 23 | for(int i = 0; i < nums2.length; i++) 24 | { 25 | if(map.containsKey(nums2[i]) && map.get(nums2[i]) > 0) 26 | { 27 | result.add(nums2[i]); 28 | map.put(nums2[i], map.get(nums2[i])-1); 29 | } 30 | } 31 | 32 | int[] r = new int[result.size()]; 33 | for(int i = 0; i < result.size(); i++) 34 | { 35 | r[i] = result.get(i); 36 | } 37 | 38 | return r; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/贪心/ReconstructQueue_406.java: -------------------------------------------------------------------------------- 1 | package 贪心; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * Created by jiangyunxiong on 2018/5/2. 9 | * 10 | * 根据身高重建队列 11 | */ 12 | public class ReconstructQueue_406 { 13 | 14 | public int[][] reconstructQueue(int[][] people) { 15 | if (people == null || people.length == 0 || people[0].length == 0) return new int[0][0]; 16 | //身高降序、k 值升序 17 | Arrays.sort(people, (a, b) -> { 18 | if (a[0] == b[0]) return a[1] - b[1]; 19 | return b[0] - a[0]; 20 | }); 21 | int N = people.length; 22 | //为了在每次插入操作时不影响后续的操作,身高较高的学生应该先做插入操作,否则身高较小的学生原先正确插入第 k 个位置可能会变成第 k+1 个位置。 23 | List tmp = new ArrayList<>(); 24 | for (int i = 0; i < N; i++) { 25 | int index = people[i][1]; 26 | int[] p = new int[]{people[i][0], people[i][1]}; 27 | tmp.add(index, p); 28 | } 29 | 30 | int[][] ret = new int[N][2]; 31 | for (int i = 0; i < N; i++) { 32 | ret[i][0] = tmp.get(i)[0]; 33 | ret[i][1] = tmp.get(i)[1]; 34 | } 35 | return ret; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/二分查找/SearchinRotatedSortedArrayII_81.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/14 15:05 6 | * @Description: 是在旋转有序数组中搜索的延伸,现在数组中允许出现重复数字 7 | */ 8 | public class SearchinRotatedSortedArrayII_81 { 9 | 10 | public boolean search(int[] nums, int target) { 11 | if (nums == null || nums.length == 0) return false; 12 | 13 | int l = 0; 14 | int r = nums.length - 1; 15 | while (l <= r) { 16 | int m = l + (r - l) / 2; 17 | if (target == nums[m]) return true; 18 | //说明从m到r一定是有序的(没有受到rotate的影响) 19 | if (nums[m] < nums[r]) { 20 | if (target > nums[m] && target <= nums[r]) { 21 | l = m + 1; 22 | } else { 23 | r = m - 1; 24 | } 25 | //说明从l到m一定是有序的 26 | } else if (nums[m] > nums[r]) { 27 | if (target >= nums[l] && target < nums[m]) { 28 | r = m - 1; 29 | } else { 30 | l = m + 1; 31 | } 32 | }else{ 33 | r--; 34 | } 35 | } 36 | return false; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/栈/BackspaceStringCompare_844.java: -------------------------------------------------------------------------------- 1 | package 栈; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2018/12/26 上午8:12 8 | * 9 | * 比较含退格的字符串 10 | */ 11 | public class BackspaceStringCompare_844 { 12 | 13 | public boolean backspaceCompare(String S, String T) { 14 | char[] s = S.toCharArray(); 15 | char[] t = T.toCharArray(); 16 | 17 | Stack stack1 = new Stack(); 18 | Stack stack2 = new Stack(); 19 | 20 | for (char n : s){ 21 | if (n == '#' && !stack1.isEmpty()){ 22 | stack1.pop(); 23 | }else { 24 | stack1.push(n); 25 | } 26 | } 27 | for (char n : t){ 28 | if (n == '#' && !stack2.isEmpty()){ 29 | stack2.pop(); 30 | }else { 31 | stack2.push(n); 32 | } 33 | } 34 | while(!stack1.isEmpty() && !stack2.isEmpty()){ 35 | if (stack1.pop() != stack2.pop()){ 36 | return false; 37 | }else if (stack1.isEmpty() && stack2.isEmpty()){ 38 | return true; 39 | } 40 | } 41 | 42 | return false; 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/二叉树/性质/TrimBinarySearchTree_669.java: -------------------------------------------------------------------------------- 1 | package 二叉树.性质; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/23 下午7:09 6 | * 7 | * 修剪二叉搜索树 8 | * 9 | * 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (L<=R) 10 | */ 11 | public class TrimBinarySearchTree_669 { 12 | 13 | 14 | /** 15 | * 思路:递归修剪,根据二叉搜索树的特性,根的值大于左子结点,小于右子结点,得出: 16 | * 1、如果root.val小于L的值,则直接舍弃左子树,返回继续修剪以root.right为根结点的右子树; 17 | * 2、如果root.val大于R的值,则直接舍弃右子树,返回继续修剪以root.left为根结点的左子树; 18 | * 3、在[L, R]范围内,则继续修剪左子树和右子树,然后返回root. 19 | */ 20 | public TreeNode trimBST(TreeNode root, int L, int R) { 21 | if (root == null) { 22 | return null; 23 | } 24 | if (root.val < L) { 25 | return trimBST(root.right, L, R); 26 | } else if (root.val > R) { 27 | return trimBST(root.left, L, R); 28 | } else { 29 | root.left = trimBST(root.left, L, R); 30 | root.right = trimBST(root.right, L, R); 31 | return root; 32 | } 33 | } 34 | class TreeNode { 35 | int val; 36 | TreeNode left; 37 | TreeNode right; 38 | 39 | TreeNode(int x) { 40 | val = x; 41 | } 42 | } 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/动态规划/MatrixDP/UniquePathsII_63.java: -------------------------------------------------------------------------------- 1 | package 动态规划.MatrixDP; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/5 上午10:55 6 | * 7 | * 不同路径 II 8 | * 9 | * 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角,考虑网格中有障碍物,问总共有多少条不同的路径? 10 | * 11 | */ 12 | public class UniquePathsII_63 { 13 | 14 | public int uniquePathsWithObstacles(int[][] obstacleGrid) { 15 | int m = obstacleGrid.length; 16 | int n = obstacleGrid[0].length; 17 | if (m == 0 || n == 0) return 0; 18 | int[][] dp = new int[m][n]; 19 | for (int i = 0; i < m; i++) { 20 | if (obstacleGrid[i][0] == 0) 21 | dp[i][0] = 1; 22 | else 23 | break; 24 | } 25 | for (int j = 0; j < n; j++) { 26 | if (obstacleGrid[0][j] == 0) 27 | dp[0][j] = 1; 28 | else 29 | break; 30 | } 31 | for (int i = 1; i < m; i++) { 32 | for (int j = 1; j < n; j++) { 33 | if (obstacleGrid[i][j] == 0) { 34 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 35 | } else { 36 | dp[i][j] = 0; 37 | } 38 | } 39 | } 40 | return dp[m - 1][n - 1]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/排序/八大排序/QuickSort.java: -------------------------------------------------------------------------------- 1 | package 排序.八大排序; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/4 14:17 6 | * @Description: 快速排序 7 | *

8 | * 快速排序通过一个基准元素将数组分为两个子数组,左子数组小于等于基准元素,右子数组大于等于基准元素,将这两个子数组排序也就将整个数组排序了。 9 | */ 10 | public class QuickSort extends Base { 11 | 12 | 13 | public static void sort(int[] a) { 14 | sort(a, 0, a.length - 1); 15 | } 16 | 17 | private static void sort(int[] a, int l, int h) { 18 | if (h <= l) 19 | return; 20 | int j = partition(a, l, h); 21 | sort(a, l, j - 1); 22 | sort(a, j + 1, h); 23 | } 24 | 25 | private static int partition(int[] a, int l, int h) { 26 | int i = l, j = h + 1; 27 | int v = a[l]; 28 | while (true) { 29 | while (compare(a[++i], v) && i != h) ; 30 | while (compare(v, a[--j]) && j != l) ; 31 | if (i >= j) 32 | break; 33 | swap(a, i, j); 34 | } 35 | swap(a, l, j); 36 | return j; 37 | } 38 | 39 | public static void main(String[] args) { 40 | int[] a = {1, 5, 8, 6, 6, 2, 2, 3, 33, 4, 4}; 41 | QuickSort.sort(a); 42 | for (int i : a) { 43 | System.out.println(i); 44 | } 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /src/二叉树/搜索/BinaryTreeRightSideView_199.java: -------------------------------------------------------------------------------- 1 | package 二叉树.搜索; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | 8 | /** 9 | * @Author jiangyunxiong 10 | * @Date 2019/1/2 下午10:50 11 | * 12 | * 题目:返回二叉树每层的最右边节点的值 13 | * 14 | */ 15 | public class BinaryTreeRightSideView_199 { 16 | class TreeNode { 17 | int val; 18 | TreeNode left; 19 | TreeNode right; 20 | TreeNode(int x) { val = x; } 21 | } 22 | 23 | public List rightSideView(TreeNode root) { 24 | List res = new ArrayList<>(); 25 | if (root == null) return res; 26 | 27 | Queue queue = new LinkedList<>(); 28 | queue.offer(root); 29 | while (!queue.isEmpty()) { 30 | int size = queue.size(); 31 | for (int i = 0; i < size; i++) { 32 | TreeNode node = queue.poll(); 33 | // 每次把每层的最右边一个节点的值添加到results中 34 | if(i == size - 1) res.add(node.val); 35 | if (node.left != null) 36 | queue.offer(node.left); 37 | if (node.right != null) 38 | queue.offer(node.right); 39 | } 40 | } 41 | return res; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/栈/EvaluateReversePolishNotation_150.java: -------------------------------------------------------------------------------- 1 | package 栈; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/3 下午10:04 8 | * 9 | * 逆波兰表达式求值 10 | * 11 | * 思路:只需要定义一个stack,如果是+, -, *, /四个运算符,就取出栈顶的两个数,进行相应操作,之后将计算得到的结果压入栈中; 12 | * 如果是数字,就直接入栈。最终stack只剩下一个元素,这个元素就是逆波兰表达式的值 13 | */ 14 | public class EvaluateReversePolishNotation_150 { 15 | 16 | public int evalRPN(String[] tokens) { 17 | Stack s=new Stack(); 18 | 19 | for(int i=0;i largestValues(TreeNode root) { 20 | List res = new ArrayList<>(); 21 | if (root == null) return res; 22 | Queue queue = new LinkedList<>(); 23 | queue.offer(root); 24 | while (!queue.isEmpty()) { 25 | int size = queue.size(); 26 | int max = Integer.MIN_VALUE; 27 | for (int i = 0; i < size; i++) { 28 | TreeNode node = queue.poll(); 29 | if (node.val > max) max = node.val; 30 | if (node.left != null) 31 | queue.offer(node.left); 32 | if (node.right != null) 33 | queue.offer(node.right); 34 | } 35 | res.add(max); 36 | } 37 | return res; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/二叉树/遍历/BinaryTreeInorderTraversal_94.java: -------------------------------------------------------------------------------- 1 | package 二叉树.遍历; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Stack; 6 | 7 | /** 8 | * @Author jiangyunxiong 9 | * @Date 2019/1/2 下午10:06 10 | *

11 | * 二叉树中序遍历 12 | * 13 | */ 14 | public class BinaryTreeInorderTraversal_94 { 15 | 16 | class TreeNode { 17 | int val; 18 | TreeNode left; 19 | TreeNode right; 20 | 21 | TreeNode(int x) { 22 | val = x; 23 | } 24 | } 25 | 26 | 27 | /** 28 | * 思路:由于二叉树中序遍历要先遍历左孩子,再是根节点,最后是右孩子。 29 | * 所以算法先找到根节点的最左孩子,把一路下来的左孩子依次入栈,访问最左孩子,而后是访问根节点,然后把根节点右孩子当做当前节点。重复上述过程直到节点都访问完。 30 | */ 31 | public List inorderTraversal(TreeNode root) { 32 | List result = new ArrayList(); 33 | Stack s = new Stack<>(); 34 | TreeNode p = root; 35 | while (!s.isEmpty() || p != null) { 36 | // 左孩子依次入栈,访问最左孩子 37 | if (p != null) { 38 | s.push(p); 39 | p = p.left; 40 | } else { 41 | p = s.pop(); 42 | result.add(p.val); 43 | // 把根节点右孩子当做当前节点 44 | p = p.right; 45 | } 46 | } 47 | return result; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/排序/KthLargestElementinanArray_215.java: -------------------------------------------------------------------------------- 1 | package 排序; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/6 下午7:06 6 | * 7 | * 数组中的第K个最大元素 8 | */ 9 | public class KthLargestElementinanArray_215 { 10 | 11 | public int findKthLargest(int[] nums, int k) { 12 | k = nums.length -k; 13 | int lo = 0; 14 | int hi =nums.length-1; 15 | while(lok){ 20 | hi=j-1; 21 | }else{ 22 | break; 23 | } 24 | } 25 | return nums[k]; 26 | } 27 | 28 | public int partition(int[] a, int lo, int hi){ 29 | int i = lo; 30 | int j = hi + 1; 31 | while(true) { 32 | while(i < hi && less(a[++i], a[lo])); 33 | while(j > lo && less(a[lo], a[--j])); 34 | if(i >= j) { 35 | break; 36 | } 37 | exch(a, i, j); 38 | } 39 | exch(a, lo, j); 40 | return j; 41 | } 42 | 43 | private void exch(int[] a, int i, int j){ 44 | int t = a[i]; 45 | a[i] = a[j]; 46 | a[j] = t; 47 | } 48 | 49 | private boolean less(int v, int w) { 50 | return v < w; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/链表/合并/AddTwoNumbers_2.java: -------------------------------------------------------------------------------- 1 | package 链表.合并; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/24 10:46 6 | * @Description: 两个链表求和,和也是一个链表(链表是逆序存的数字) (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 7 | */ 8 | public class AddTwoNumbers_2 { 9 | public class ListNode { 10 | int val; 11 | ListNode next; 12 | 13 | ListNode(int x) { 14 | val = x; 15 | } 16 | } 17 | /** 18 | * 思路: 19 | * 首先做个大循环,对每一位进行操作: 20 | * 当前位:(A[i]+B[i])%10 21 | * 进位:(A[i]+B[i])/10 22 | * 逆序存的数字 23 | */ 24 | public ListNode addTwoNumbers(ListNode l1, ListNode l2) { 25 | ListNode c1 = l1; 26 | ListNode c2 = l2; 27 | ListNode sentinel = new ListNode(0); 28 | ListNode d = sentinel; 29 | int sum = 0; 30 | while (c1 != null || c2 != null) { 31 | sum /= 10; 32 | if (c1 != null) { 33 | sum += c1.val; 34 | c1 = c1.next; 35 | } 36 | if (c2 != null) { 37 | sum += c2.val; 38 | c2 = c2.next; 39 | } 40 | d.next = new ListNode(sum % 10); 41 | d = d.next; 42 | } 43 | if (sum/10 == 1){ 44 | d.next = new ListNode(1); 45 | } 46 | return sentinel.next; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/排序/SortColors_75.java: -------------------------------------------------------------------------------- 1 | package 排序; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/20 下午9:10 6 | *

7 | * 按颜色进行排序 8 | *

9 | * Input: [2,0,2,1,1,0] 10 | * Output: [0,0,1,1,2,2] 11 | */ 12 | 13 | /** 14 | * 15 | * 中心思想:三向切分快速排序 16 | * 17 | * 用两个指针left, right来分割数组。left用来记录第一个1, right用来记录从右数起第一个非2数。 18 | * left起始为0,right起始为n-1. 遍历时, 19 | * 1、遇到0, 就将nums[left]和nums[i]换一换,将0换到左边去,由于现在nums[left]是0了,left++, i++; 20 | * 2、遇到1,left和right都不动,i++; 21 | * 3、遇到2,和Nums[right]换一换把2换到右边去,现在Nums[right]上是2所以right--, nums[i]上是0或者1,所以i不动,要继续检查是0还是1. 22 | */ 23 | public class SortColors_75 { 24 | 25 | public void sortColors(int[] nums) { 26 | 27 | if (nums.length == 0) { 28 | return; 29 | } 30 | 31 | int left = 0, right = nums.length - 1, i = 0; 32 | 33 | while (i <= right) { 34 | if (nums[i] == 0) { 35 | swap(nums, left, i); 36 | i++; 37 | left++; 38 | } else if (nums[i] == 1) { 39 | i++; 40 | } else { 41 | swap(nums, right, i); 42 | right--; 43 | } 44 | } 45 | 46 | } 47 | 48 | private void swap(int[] nums, int i, int j) { 49 | int temp = nums[i]; 50 | nums[i] = nums[j]; 51 | nums[j] = temp; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/二叉树/路径/BinaryTreeMaximumPathSum_124.java: -------------------------------------------------------------------------------- 1 | package 二叉树.路径; 2 | 3 | 4 | /** 5 | * @Author jiangyunxiong 6 | * @Date 2018/12/31 上午10:10 7 | *

8 | * 2个结点之间的最长路径 9 | * 10 | * 11 | */ 12 | public class BinaryTreeMaximumPathSum_124 { 13 | 14 | int ans; 15 | 16 | public int maxPathSum(TreeNode root) { 17 | ans = Integer.MIN_VALUE; 18 | maxDeep(root); 19 | return ans; 20 | } 21 | 22 | /** 23 | * 1、前序遍历 24 | * 2、求根结点到所有叶子结点的pathsum,遍历整颗树 25 | * 3、求根结点到叶子结点的最大深度 26 | */ 27 | public int maxDeep(TreeNode root) { 28 | if (root == null) return 0; 29 | //叶子结点 30 | if (root.left == null && root.right == null) { 31 | ans = Math.max(ans, root.val); 32 | return root.val; 33 | } else { 34 | int left = maxDeep(root.left); 35 | int right = maxDeep(root.right); 36 | int tmp = Math.max(left, right) + root.val; 37 | tmp = Math.max(tmp, root.val); 38 | 39 | ans = Math.max(ans, tmp); 40 | ans = Math.max(ans, left+right+root.val); 41 | return tmp; 42 | } 43 | } 44 | 45 | class TreeNode { 46 | int val; 47 | TreeNode left; 48 | TreeNode right; 49 | 50 | TreeNode(int x) { 51 | val = x; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/二叉树/搜索/PopulatingNextRightPointersinEachNode_116.java: -------------------------------------------------------------------------------- 1 | package 二叉树.搜索; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2019/1/3 下午8:45 6 | * 填充同一层的兄弟节点 7 | * 8 | * 给定完全二叉树, 9 | * 1 10 | * / \ 11 | * 2 3 12 | * / \ / \ 13 | * 4 5 6 7 14 | * 调用你的函数后,该完全二叉树变为: 15 | * 1 -> NULL 16 | * / \ 17 | * 2 -> 3 -> NULL 18 | * / \ / \ 19 | * 4->5->6->7 -> NULL 20 | */ 21 | public class PopulatingNextRightPointersinEachNode_116 { 22 | class TreeLinkNode { 23 | int val; 24 | TreeLinkNode left, right, next; 25 | 26 | TreeLinkNode(int x) { 27 | val = x; 28 | } 29 | } 30 | 31 | /** 32 | * 思路: 33 | * 1、对于其左子节点的处理方法是,由于是完全二叉树,所以若节点的左子结点存在的话,其右子节点必定存在,所以左子结点的next指针可以直接指向其右子节点 34 | * 2、对于其右子节点的处理方法是,判断其父节点的next是否为空,若不为空,则指向其next指针指向的节点的左子结点,若为空则指向NULL 35 | * @param root 36 | */ 37 | public void connect(TreeLinkNode root) { 38 | if (root == null) return; 39 | if (root.left != null) { 40 | // 1的left是2,1的right是3,所以2要指向3 41 | root.left.next = root.right; 42 | } 43 | if (root.next != null && root.right != null) { 44 | // 2的right是5,2的next的left是6,所以5要指向6 45 | root.right.next = root.next.left; 46 | } 47 | connect(root.left); 48 | connect(root.right); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/二分查找/SearchRotatedSortedArray_33.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/14 14:49 6 | * @Description: 在旋转有序数组中搜索 7 | */ 8 | public class SearchRotatedSortedArray_33 { 9 | 10 | /** 11 | * 思路: 12 | * 如果target==A[m],那么m就是我们要的结果,直接返回; 13 | * 如果A[m]=A[r],那么说明从l到m一定是有序的,同样只需要判断target是否在这个范围内,相应的移动边缘即可。 15 | * 16 | * 时间复杂度是O(logn),空间复杂度是O(1) 17 | */ 18 | public int search(int[] A, int target) { 19 | if (A == null || A.length == 0) return -1; 20 | 21 | int l = 0; 22 | int r = A.length - 1; 23 | while (l <= r) { 24 | int m = l + (r - l) / 2; 25 | if (target == A[m]) return m; 26 | //说明从m到r一定是有序的(没有受到rotate的影响) 27 | if (A[m] < A[r]) { 28 | if (target > A[m] && target <= A[r]) { 29 | l = m + 1; 30 | } else { 31 | r = m - 1; 32 | } 33 | //说明从l到m一定是有序的 34 | } else { 35 | if (target >= A[l] && target < A[m]) { 36 | r = m - 1; 37 | } else { 38 | l = m + 1; 39 | } 40 | } 41 | } 42 | return -1; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/栈/BaseballGame_682.java: -------------------------------------------------------------------------------- 1 | package 栈; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2018/12/23 下午5:11 8 | * 9 | * 棒球比赛 10 | */ 11 | public class BaseballGame_682 { 12 | 13 | public static void main(String[] args) { 14 | 15 | String[] str = {"5","2","C","D","+"}; 16 | BaseballGame_682 b = new BaseballGame_682(); 17 | System.out.println(b.calPoints(str)); 18 | } 19 | 20 | public int calPoints(String[] ops) { 21 | Stack stack = new Stack<>(); 22 | 23 | int sum = 0; 24 | 25 | for (String s : ops) { 26 | if (s.charAt(0) == 'C') { 27 | int x = stack.pop(); 28 | sum -= x; 29 | } else if (s.charAt(0) == 'D') { 30 | int x = stack.peek(); 31 | int n = 2 * x; 32 | sum += n; 33 | stack.push(n); 34 | } else if (s.charAt(0) == '+') { 35 | int x = stack.pop(); 36 | int y = stack.peek(); 37 | stack.push(x); 38 | int n = (x + y); 39 | sum += n; 40 | stack.push(n); 41 | } else { 42 | int x = Integer.parseInt(s); 43 | sum += x; 44 | stack.push(x); 45 | } 46 | } 47 | 48 | return sum; 49 | } 50 | } -------------------------------------------------------------------------------- /src/二叉树/搜索/AverageofLevelsinBinaryTree_637.java: -------------------------------------------------------------------------------- 1 | package 二叉树.搜索; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | 8 | /** 9 | * @Author jiangyunxiong 10 | * @Date 2018/12/24 下午9:38 11 | * 12 | * 二叉树的层平均值 13 | */ 14 | public class AverageofLevelsinBinaryTree_637 { 15 | 16 | public List averageOfLevels(TreeNode root) { 17 | 18 | List res = new ArrayList<>(); 19 | if (root == null) { 20 | return res; 21 | } 22 | 23 | Queue queue = new LinkedList<>(); 24 | queue.offer(root); 25 | while (!queue.isEmpty()) { 26 | int size = queue.size(); 27 | int count = size; 28 | double sum = 0.0; 29 | while (size > 0) { 30 | TreeNode node = queue.poll(); 31 | sum += node.val; 32 | if (node.left != null) 33 | queue.offer(node.left); 34 | if (node.right != null) 35 | queue.offer(node.right); 36 | size--; 37 | } 38 | res.add(sum/count); 39 | } 40 | return res; 41 | } 42 | 43 | 44 | public class TreeNode { 45 | int val; 46 | TreeNode left; 47 | TreeNode right; 48 | 49 | TreeNode(int x) { 50 | val = x; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/并查集/WordSearch_79.java: -------------------------------------------------------------------------------- 1 | package 并查集; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/31 下午9:22 6 | */ 7 | public class WordSearch_79 { 8 | static boolean[][] visited; 9 | 10 | public boolean exist(char[][] board, String word) { 11 | int n = board.length; 12 | int m = board[0].length; 13 | visited = new boolean[n][m]; 14 | 15 | for (int i = 0; i < n; i++) { 16 | for (int j = 0; j < m; j++) { 17 | if (word.charAt(0) == board[i][j] && search(board, word, i, j, 0)) { 18 | return true; 19 | } 20 | } 21 | } 22 | return false; 23 | } 24 | 25 | private boolean search(char[][] board, String word, int i, int j, int index) { 26 | if (index == word.length()) { 27 | return true; 28 | } 29 | if (i >= board.length || i < 0 || j >= board[i].length || j < 0 || board[i][j] != word.charAt(index) || visited[i][j]) { 30 | return false; 31 | } 32 | visited[i][j] = true; 33 | if (search(board, word, i - 1, j, index + 1) 34 | || search(board, word, i + 1, j, index + 1) 35 | || search(board, word, i, j - 1, index + 1) 36 | || search(board, word, i, j + 1, index + 1)) { 37 | return true; 38 | } 39 | visited[i][j] = false; 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/二叉树/层序遍历/NaryTreeLevelOrderTraversal_429.java: -------------------------------------------------------------------------------- 1 | package 二叉树.层序遍历; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | import java.util.Queue; 6 | 7 | /** 8 | * @Author jiangyunxiong 9 | * @Date 2018/12/23 下午8:38 10 | * 11 | * N叉树的层序遍历 12 | */ 13 | public class NaryTreeLevelOrderTraversal_429 { 14 | 15 | public List> levelOrder(Node root) { 16 | List> res = new LinkedList<>(); 17 | if (root == null) { 18 | return res; 19 | } 20 | Queue queue = new LinkedList<>(); 21 | queue.offer(root); 22 | 23 | while (!queue.isEmpty()) { 24 | List eachLayer = new LinkedList<>(); 25 | int layerSize = queue.size(); 26 | for (int i = 0; i < layerSize; ++i) { 27 | Node temp = queue.poll(); 28 | eachLayer.add(temp.val); 29 | for (Node node : temp.children) { 30 | queue.offer(node); 31 | } 32 | } 33 | res.add(eachLayer); 34 | } 35 | return res; 36 | } 37 | 38 | class Node { 39 | public int val; 40 | public List children; 41 | 42 | public Node() { 43 | } 44 | 45 | public Node(int _val, List _children) { 46 | val = _val; 47 | children = _children; 48 | } 49 | } 50 | } 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /src/二叉树/层序遍历/BinaryTreeLevelOrderTraversal_102.java: -------------------------------------------------------------------------------- 1 | package 二叉树.层序遍历; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | 8 | /** 9 | * @Author jiangyunxiong 10 | * @Date 2019/1/2 下午10:28 11 | * 12 | * 二叉树的层序遍历(从上到下) 13 | * 14 | * 基础模版代码,其他各种各样的层序搜索题都是本题的变种,稍微在本题代码基础上修改一下即可 15 | */ 16 | public class BinaryTreeLevelOrderTraversal_102 { 17 | class TreeNode { 18 | int val; 19 | TreeNode left; 20 | TreeNode right; 21 | 22 | TreeNode(int x) { 23 | val = x; 24 | } 25 | } 26 | 27 | public List> levelOrder(TreeNode root) { 28 | List> res = new ArrayList<>(); 29 | if (root == null) return res; 30 | Queue queue = new LinkedList<>(); 31 | queue.offer(root); 32 | while (!queue.isEmpty()) { 33 | //记录每行 34 | List level = new ArrayList<>(); 35 | int size = queue.size(); 36 | for (int i = 0; i < size; i++) { 37 | TreeNode node = queue.poll(); 38 | level.add(node.val); 39 | if (node.left != null) 40 | queue.offer(node.left); 41 | if (node.right != null) 42 | queue.offer(node.right); 43 | } 44 | res.add(level); 45 | } 46 | return res; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/栈/LongestValidParentheses_32.java: -------------------------------------------------------------------------------- 1 | package 栈; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/3 下午9:21 8 | * 9 | * 最长有效括号(考察点:栈/动态规划) 10 | * 11 | * 用栈存放左括号的下标,遇到左括号,将其下标存入栈中。 12 | * 遇到右括号,若此时栈为空,说明这个不是有效括号对里的,跳过,更新有效括号的起始点; 13 | * 若是栈不为空,则栈顶元素出栈。此时,若栈为空,后面不一定没有接合法的有效括号对,所以,计算当前和有效括号起始点的距离,并更新最大值 14 | */ 15 | public class LongestValidParentheses_32 { 16 | public static void main(String[] args) { 17 | LongestValidParentheses_32 l = new LongestValidParentheses_32(); 18 | System.out.println(l.longestValidParentheses(")()())")); 19 | } 20 | public int longestValidParentheses(String s) { 21 | //存放每一个左括号的位置 22 | Stack stack = new Stack<>(); 23 | int res = 0; 24 | // 当前括号组合的最左侧边界 25 | int start = -1; 26 | for (int i = 0; i < s.length(); i++) { 27 | if (s.charAt(i) == '(') { 28 | stack.push(i); 29 | } else { 30 | //当前括号组合为空 31 | if (stack.empty()) { 32 | start = i; 33 | } else { 34 | stack.pop(); 35 | if (stack.empty()) { 36 | res = Math.max(res, i - start); 37 | } else { 38 | res = Math.max(res, i - stack.peek()); 39 | } 40 | } 41 | } 42 | } 43 | return res; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/回溯/LetterCasePermutation_784.java: -------------------------------------------------------------------------------- 1 | package 回溯; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/29 下午11:31 9 | *

10 | * 字母大小写全排列 11 | *

12 | * 回溯法, 遇到字母分大小写情况回溯, 遇到非字母直接回溯 13 | */ 14 | public class LetterCasePermutation_784 { 15 | 16 | public static void main(String[] args) { 17 | LetterCasePermutation_784 l = new LetterCasePermutation_784(); 18 | System.out.println(l.letterCasePermutation("a1b2")); 19 | } 20 | 21 | public List letterCasePermutation(String S) { 22 | List ret = new ArrayList<>(); 23 | bktrace(S.toCharArray(), ret, new StringBuilder(), 0); 24 | return ret; 25 | } 26 | 27 | 28 | private void bktrace(char[] s, List ret, StringBuilder sb, int i) { 29 | if (i == s.length) { 30 | ret.add(sb.toString()); 31 | return; 32 | } 33 | char c = s[i]; 34 | if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { 35 | sb.append(Character.toLowerCase(c)); 36 | bktrace(s, ret, sb, i+1); 37 | sb.deleteCharAt(sb.length()-1); 38 | 39 | sb.append(Character.toUpperCase(c)); 40 | bktrace(s, ret, sb, i+1); 41 | sb.deleteCharAt(sb.length()-1); 42 | }else{ 43 | sb.append(c); 44 | bktrace(s, ret, sb, i+1); 45 | sb.deleteCharAt(sb.length()-1); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/二叉树/层序遍历/BinaryTreeLevelOrderTraversalII_107.java: -------------------------------------------------------------------------------- 1 | package 二叉树.层序遍历; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | 8 | /** 9 | * @Author jiangyunxiong 10 | * @Date 2019/1/2 下午10:32 11 | * 12 | * 二叉树的层序遍历(从下到上) 13 | * 14 | */ 15 | public class BinaryTreeLevelOrderTraversalII_107 { 16 | class TreeNode { 17 | int val; 18 | TreeNode left; 19 | TreeNode right; 20 | 21 | TreeNode(int x) { 22 | val = x; 23 | } 24 | } 25 | 26 | /** 27 | * 思路:只要在普通的层序遍历代码中修改一处:results.add(0, level);,这样每次头插到结果中。 28 | */ 29 | public List> levelOrderBottom(TreeNode root) { 30 | List> res = new ArrayList<>(); 31 | if (root == null) return res; 32 | Queue queue = new LinkedList<>(); 33 | queue.offer(root); 34 | while (!queue.isEmpty()) { 35 | //记录每行 36 | List level = new ArrayList<>(); 37 | int size = queue.size(); 38 | for (int i = 0; i < size; i++) { 39 | TreeNode node = queue.poll(); 40 | level.add(node.val); 41 | if (node.left != null) 42 | queue.offer(node.left); 43 | if (node.right != null) 44 | queue.offer(node.right); 45 | } 46 | res.add(0, level); 47 | } 48 | return res; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/栈/ImplementQueueusingStacks_232.java: -------------------------------------------------------------------------------- 1 | package 栈; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/3 下午9:33 8 | * 9 | * 用两个栈实现队列 10 | */ 11 | public class ImplementQueueusingStacks_232 { 12 | private Stack stack1 = new Stack<>(); 13 | private Stack stack2 = new Stack<>(); 14 | 15 | /** 16 | * 队列的 push() 操作,就直接在 stack1 上进行栈的 push() 操作即可 17 | */ 18 | public void push(int x) { 19 | stack1.push(x); 20 | } 21 | 22 | /** 23 | * 队列的 pop() 操作,其实就是得到 stack1 中最底下的那个元素,怎么得到呢?先把上面逐个退出的元素一个个放在另一个栈 stack2 中; 24 | * 当 stack1 为空的时候,stack2 的栈顶元素,就是要取得的元素,用栈的 pop() 操作取出 25 | * 在将该元素进行返回前,再将 stack2 中的元素倒回到 stack1 中,然后将该元素返回 26 | */ 27 | public int pop() { 28 | // 如果stack2为空 29 | if (stack2.isEmpty()) { 30 | // 且stack1不为空 31 | while (!stack1.isEmpty()) { 32 | // 则不断把stack1中的元素pop出来,并push到stack2中暂存 33 | stack2.push(stack1.pop()); 34 | } 35 | } 36 | // stack2的栈顶元素其实就是stack1的栈底元素,我们要pop队列的队首元素其实也就是pop栈的栈底元素 37 | return stack2.pop(); 38 | } 39 | 40 | public int peek() { 41 | if (stack2.isEmpty()) { 42 | while (!stack1.isEmpty()) { 43 | stack2.push(stack1.pop()); 44 | } 45 | } 46 | return stack2.peek(); 47 | } 48 | 49 | public boolean empty() { 50 | return stack1.isEmpty() && stack2.isEmpty(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/贪心/NonOverlappingIntervals_435.java: -------------------------------------------------------------------------------- 1 | package 贪心; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/20 下午10:04 9 | * 10 | * 不重叠的区间个数 11 | */ 12 | public class NonOverlappingIntervals_435 { 13 | 14 | /** 15 | * 思路: 16 | * 先计算最多能组成的不重叠区间个数,然后用区间总个数减去不重叠区间的个数。 17 | * 在每次选择中,区间的结尾最为重要,选择的区间结尾越小,留给后面的区间的空间越大,那么后面能够选择的区间个数也就越大。 18 | * 按区间的结尾进行排序,每次选择结尾最小,并且和前一个区间不重叠的区间。 19 | */ 20 | public int eraseOverlapIntervals(Interval[] intervals) { 21 | 22 | if (intervals.length == 0) { 23 | return 0; 24 | } 25 | 26 | Arrays.sort(intervals, new Comparator() { 27 | @Override 28 | public int compare(Interval o1, Interval o2) { 29 | return o1.end - o2.end; 30 | } 31 | }); 32 | 33 | int num = 1; 34 | int end = intervals[0].end; 35 | for (int i = 1; i < intervals.length; i++) { 36 | if (intervals[i].start < end){ 37 | continue; 38 | } 39 | end = intervals[i].end; 40 | num++; 41 | } 42 | return intervals.length - num; 43 | } 44 | 45 | 46 | 47 | class Interval { 48 | int start; 49 | int end; 50 | 51 | Interval() { 52 | start = 0; 53 | end = 0; 54 | } 55 | 56 | Interval(int s, int e) { 57 | start = s; 58 | end = e; 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/字符串/RomanToInt_13.java: -------------------------------------------------------------------------------- 1 | package 字符串; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2019/6/23 2:33 PM 9 | *

10 | *

11 | * 思路 12 | * 1. 首先将所有的组合可能性列出并添加到哈希表中 13 | * 2. 然后对字符串进行遍历,由于组合只有两种,一种是 1 个字符,一种是 2 个字符,其中 2 个字符优先于 1 个字符 14 | * 3. 先判断两个字符的组合在哈希表中是否存在,存在则将值取出加到结果 ans 中,并向后移2个字符。不存在则将判断当前 1 个字符是否存在,存在则将值取出加到结果 ans 中,并向后移 1 个字符 15 | * 4. 遍历结束返回结果 ans 16 | */ 17 | public class RomanToInt_13 { 18 | public static void main(String[] args) { 19 | RomanToInt_13 r = new RomanToInt_13(); 20 | r.romanToInt("III"); 21 | } 22 | 23 | public int romanToInt(String s) { 24 | Map map = new HashMap<>(); 25 | map.put("I", 1); 26 | map.put("IV", 4); 27 | map.put("V", 5); 28 | map.put("IX", 9); 29 | map.put("X", 10); 30 | map.put("XL", 40); 31 | map.put("L", 50); 32 | map.put("XC", 90); 33 | map.put("C", 100); 34 | map.put("CD", 400); 35 | map.put("D", 500); 36 | map.put("CM", 900); 37 | map.put("M", 1000); 38 | int res = 0; 39 | for (int i = 0; i < s.length(); ) { 40 | if (s.length() > i + 1 && map.containsKey(s.substring(i, i + 2))) { 41 | res += map.get(s.substring(i, i + 2)); 42 | i += 2; 43 | } else { 44 | res += map.get(s.substring(i, i + 1)); 45 | i++; 46 | } 47 | } 48 | return res; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/二分查找/CountCompleteTreeNodes_222.java: -------------------------------------------------------------------------------- 1 | package 二分查找; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/30 上午9:01 6 | * 7 | * 计算一个完全二叉树所有的节点数(完全二叉树:除最后一层外,每一层上的节点数均达到最大值) 8 | */ 9 | public class CountCompleteTreeNodes_222 { 10 | class TreeNode { 11 | int val; 12 | TreeNode left; 13 | TreeNode right; 14 | 15 | TreeNode(int x) { 16 | val = x; 17 | } 18 | } 19 | 20 | /** 21 | * 时间复杂度:O(log(n)^2) 22 | * 23 | * 思路: 24 | * 完全二叉数的高度可以通过不断地访问左子树就可以获取 25 | * 判断左右子树的高度 26 | * 如果相等说明左子树是满二叉树,然后进一步判断右子树的节点树(最后一层最后出现的节点必然在右子树中) 27 | * 如果不等说明右子树是深度小于左子树的满二叉树, 然后进一步判断左子树的节点数(最后一层最后出现的节点必然在左子树中) 28 | * 29 | * @param root 30 | * @return 31 | */ 32 | public int countNodes(TreeNode root) { 33 | if (root == null) 34 | return 0; 35 | int ld = height(root.left); 36 | int rd = height(root.right); 37 | if (ld == rd) { 38 | // 1< stack = new Stack<>(); 22 | int sign = 1; 23 | int res = 0; 24 | for (int i = 0; i < s.length(); i++) { 25 | if (Character.isDigit(s.charAt(i))) { 26 | int num = s.charAt(i) - '0'; 27 | // 如果下一个还是数字,就继续计算 28 | while (i + 1 < s.length() && Character.isDigit(s.charAt(i + 1))) { 29 | int next = s.charAt(i + 1) - '0'; 30 | num = num * 10 + next; 31 | i++; 32 | } 33 | res += num * sign; 34 | } else if (s.charAt(i) == '+') { 35 | sign = 1; 36 | } else if (s.charAt(i) == '-') { 37 | sign = -1; 38 | } else if (s.charAt(i) == '(') { 39 | stack.push(res); 40 | stack.push(sign); 41 | res = 0; 42 | sign = 1; 43 | } else if (s.charAt(i) == ')') { 44 | res = res * stack.pop() + stack.pop(); 45 | } 46 | } 47 | return res; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/深度优先搜索/Matrix_542.java: -------------------------------------------------------------------------------- 1 | package 深度优先搜索; 2 | 3 | import java.util.ArrayDeque; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2018/12/29 下午10:58 8 | * 9 | * 给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。 10 | */ 11 | public class Matrix_542 { 12 | public int[][] updateMatrix(int[][] matrix) { 13 | 14 | /** 15 | BFS思想, 把所有1都置为最大值, 把所有为0的位置加入队列中, 每次从队列中poll 16 | 一个节点, 更新其四周的节点, 如果被更新的节点距离变小了就将其入队列准备更新其邻接点 17 | **/ 18 | int m = matrix.length; 19 | if (m < 1) { 20 | return matrix; 21 | } 22 | int n = matrix[0].length; 23 | ArrayDeque queue = new ArrayDeque<>(); 24 | for (int i = 0; i < m; i++) { 25 | for (int j = 0; j < n; j++) { 26 | if (matrix[i][j] == 1) { 27 | matrix[i][j] = Integer.MAX_VALUE; 28 | } else { 29 | queue.offer(new int[]{i, j}); 30 | } 31 | } 32 | } 33 | int[][] dirs = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; 34 | 35 | while (!queue.isEmpty()) { 36 | int[] node = queue.poll(); 37 | for (int[] dir : dirs) { 38 | int x = node[0] + dir[0]; 39 | int y = node[1] + dir[1]; 40 | if (x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] <= matrix[node[0]][node[1]] + 1) 41 | continue; 42 | matrix[x][y] = matrix[node[0]][node[1]] + 1; 43 | queue.offer(new int[]{x, y}); 44 | } 45 | } 46 | return matrix; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/深度优先搜索/Permutations_46.java: -------------------------------------------------------------------------------- 1 | package 深度优先搜索; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2019/1/1 下午5:49 9 | * 10 | * 深度优先搜索的基本框架 11 | */ 12 | public class Permutations_46 { 13 | 14 | public static void main(String[] args) { 15 | Permutations_46 p = new Permutations_46(); 16 | int[] a = {1, 2, 3}; 17 | System.out.println(p.permute(a)); 18 | } 19 | 20 | public static List> res = new ArrayList<>(); 21 | 22 | //暂存小答案 23 | public static int[] path = new int[100]; 24 | 25 | //标记用过 26 | public static boolean[] v = new boolean[100]; 27 | 28 | /** 29 | * 套路,输入:一般有个指针,代表搜到哪了,还有题目给的数据 30 | * 31 | * @param idx 32 | * @param nums 33 | */ 34 | public static void robot(int idx, int[] nums) { 35 | //第一行一定是边界值判断,非法直接return 36 | if (idx >= nums.length) { 37 | ArrayList tmp = new ArrayList<>(); 38 | for (int i = 0; i < nums.length; i++) { 39 | tmp.add(nums[path[i]]); 40 | 41 | } 42 | res.add(tmp); 43 | return; 44 | } 45 | for (int i = 0; i < nums.length; i++) { 46 | if (!v[i]) { 47 | path[idx] = i; 48 | v[i] = true; 49 | robot(idx + 1, nums); 50 | v[i] = false; 51 | } 52 | } 53 | 54 | 55 | } 56 | 57 | 58 | public List> permute(int[] nums) { 59 | res.clear(); 60 | robot(0, nums); 61 | return res; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/二叉树/遍历/BinaryTreePostorderTraversal_145.java: -------------------------------------------------------------------------------- 1 | package 二叉树.遍历; 2 | 3 | 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Stack; 7 | 8 | /** 9 | * @Author jiangyunxiong 10 | * @Date 2019/1/2 下午10:17 11 | *

12 | * 二叉树后序遍历 13 | */ 14 | public class BinaryTreePostorderTraversal_145 { 15 | 16 | class TreeNode { 17 | int val; 18 | TreeNode left; 19 | TreeNode right; 20 | 21 | TreeNode(int x) { 22 | val = x; 23 | } 24 | } 25 | 26 | /** 27 | * 思路: 28 | * 二叉树的后序遍历顺序为,root->left, root->right, root,因此需要保存根节点的状态。 29 | * 对于节点p可以分情况讨论 30 | * 1. p如果是叶子节点,直接输出 31 | * 2. p如果有孩子,且孩子没有被访问过,则按照右孩子,左孩子的顺序依次入栈 32 | * 3. p如果有孩子,而且孩子都已经访问过,则访问p节点 33 | */ 34 | public List postorderTraversal(TreeNode root) { 35 | ArrayList list = new ArrayList(); 36 | TreeNode p = root, r = null;//p记录当前节点,r记录上一次访问节点 37 | Stack s = new Stack(); 38 | while (p != null || !s.isEmpty()) { 39 | if (p != null) {//左孩子一直入栈,直到左孩子为空 40 | s.push(p); 41 | p = p.left; 42 | } else { 43 | p = s.peek(); 44 | p = p.right; 45 | if (p != null && p != r) {//如果栈顶元素的左孩子不为空,且 46 | s.push(p); 47 | p = p.left; 48 | } else { 49 | p = s.pop(); 50 | list.add(p.val); 51 | r = p; 52 | p = null; 53 | } 54 | } 55 | } 56 | return list; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/分治/DiffWaysToCompute_241.java: -------------------------------------------------------------------------------- 1 | package 分治; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2018/12/20 下午11:24 9 | * 10 | * 给表达式加括号 11 | */ 12 | public class DiffWaysToCompute_241 { 13 | 14 | public static void main(String[] args) { 15 | DiffWaysToCompute_241 n = new DiffWaysToCompute_241(); 16 | n.diffWaysToCompute("2-1-1"); 17 | } 18 | 19 | public List diffWaysToCompute(String input) { 20 | 21 | List ways = new ArrayList<>(); 22 | for (int i = 0; i < input.length(); i++) { 23 | char c = input.charAt(i); 24 | if (c == '+' || c == '-' || c == '*') { 25 | List left = diffWaysToCompute(input.substring(0, i)); 26 | List right = diffWaysToCompute(input.substring(i + 1)); 27 | for (int l : left) { 28 | for (int r : right) { 29 | switch (c) { 30 | case '+': 31 | ways.add(l + r); 32 | break; 33 | case '-': 34 | ways.add(l - r); 35 | break; 36 | case '*': 37 | ways.add(l * r); 38 | break; 39 | } 40 | } 41 | } 42 | } 43 | } 44 | if (ways.size() == 0) { 45 | ways.add(Integer.valueOf(input)); 46 | } 47 | return ways; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/kSum/ThreeSumClosest_16.java: -------------------------------------------------------------------------------- 1 | package kSum; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/14 下午10:58 8 | * 最接近的三数之和 9 | * 10 | * 给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。 11 | */ 12 | public class ThreeSumClosest_16 { 13 | 14 | /** 15 | * 思路: 16 | * 1、先排序,因为会使用双指针 17 | * 2、当确定好了第一个数字后,就在剩下的num里找两数之和,从而简化为two sum问题,通过sum-target得到diff, 18 | * 3、如果diff比closest小,更新closest 19 | */ 20 | public int threeSumClosest(int[] num, int target) { 21 | if(num == null || num.length <= 2) return Integer.MIN_VALUE; 22 | 23 | Arrays.sort(num); 24 | int closest = num[0] + num[1] + num[2] - target; 25 | for(int i = 0;i target){//说明总和比target大,右指针左移获取更小的总和 44 | r--; 45 | }else{//说明总和比target小,左指针右移获取更大的总和 46 | l++; 47 | } 48 | } 49 | return closest; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/二叉树/层序遍历/BinaryTreeZigzagLevelOrderTraversal_103.java: -------------------------------------------------------------------------------- 1 | package 二叉树.层序遍历; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | 8 | /** 9 | * @Author jiangyunxiong 10 | * @Date 2019/1/2 下午10:37 11 | * 二叉树的锯齿形层次遍历 12 | * 13 | * 给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 14 | */ 15 | public class BinaryTreeZigzagLevelOrderTraversal_103 { 16 | 17 | class TreeNode { 18 | int val; 19 | TreeNode left; 20 | TreeNode right; 21 | 22 | TreeNode(int x) { 23 | val = x; 24 | } 25 | } 26 | 27 | /** 28 | * 思路:记录行数,当奇数,从左到右添加到level,当偶数反之 29 | */ 30 | public List> zigzagLevelOrder(TreeNode root) { 31 | List> res = new ArrayList<>(); 32 | if (root == null) return res; 33 | //记录行数,当奇数,从左到右添加到level,否则反之 34 | int depth = 1; 35 | Queue queue = new LinkedList<>(); 36 | queue.offer(root); 37 | while (!queue.isEmpty()) { 38 | //记录每行 39 | List level = new ArrayList<>(); 40 | int size = queue.size(); 41 | for (int i = 0; i < size; i++) { 42 | TreeNode node = queue.poll(); 43 | if (depth % 2 == 1) { 44 | level.add(node.val); 45 | } else { 46 | level.add(0, node.val); 47 | } 48 | if (node.left != null) 49 | queue.offer(node.left); 50 | if (node.right != null) 51 | queue.offer(node.right); 52 | } 53 | res.add(level); 54 | depth++; 55 | } 56 | return res; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/并查集/SerializeDeserializeBinary_297.java: -------------------------------------------------------------------------------- 1 | package 并查集; 2 | 3 | import java.util.Arrays; 4 | import java.util.Deque; 5 | import java.util.LinkedList; 6 | 7 | /** 8 | * @Author jiangyunxiong 9 | * @Date 2018/12/31 下午4:03 10 | * 11 | * 二叉树的序列化与反序列化 12 | */ 13 | public class SerializeDeserializeBinary_297 { 14 | 15 | private static final String spliter = ","; 16 | private static final String NN = "X"; 17 | 18 | 19 | // Encodes a tree to a single string. 20 | public String serialize(TreeNode root) { 21 | StringBuilder sb = new StringBuilder(); 22 | buildString(root, sb); 23 | return sb.toString(); 24 | 25 | } 26 | 27 | private void buildString(TreeNode node, StringBuilder sb) { 28 | if (node == null) { 29 | sb.append(NN).append(spliter); 30 | } else { 31 | sb.append(node.val).append(spliter); 32 | buildString(node.left, sb); 33 | buildString(node.right, sb); 34 | } 35 | } 36 | 37 | // Decodes your encoded data to tree. 38 | public TreeNode deserialize(String data) { 39 | Deque nodes = new LinkedList<>(); 40 | ((LinkedList) nodes).addAll(Arrays.asList(data.split(spliter))); 41 | return buildTree(nodes); 42 | } 43 | 44 | private TreeNode buildTree(Deque nodes) { 45 | String val = nodes.remove(); 46 | if (val.equals(NN)) return null; 47 | else { 48 | TreeNode node = new TreeNode(Integer.valueOf(val)); 49 | node.left = buildTree(nodes); 50 | node.right = buildTree(nodes); 51 | return node; 52 | } 53 | } 54 | 55 | class TreeNode { 56 | int val; 57 | TreeNode left; 58 | TreeNode right; 59 | 60 | TreeNode(int x) { 61 | val = x; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/字典树/AddSearchWord_211.java: -------------------------------------------------------------------------------- 1 | package 字典树; 2 | 3 | 4 | /** 5 | * @Author jiangyunxiong 6 | * @Date 2018/12/31 下午11:04 7 | *

8 | * 字典树 9 | */ 10 | public class AddSearchWord_211 { 11 | 12 | public class TrieNode { 13 | public TrieNode[] children = new TrieNode[26]; 14 | public String item = ""; 15 | } 16 | 17 | /** 18 | * Initialize your data structure here. 19 | */ 20 | public AddSearchWord_211() { 21 | } 22 | 23 | 24 | private TrieNode root = new TrieNode(); 25 | 26 | /** 27 | * Adds a word into the data structure. 28 | */ 29 | public void addWord(String word) { 30 | TrieNode node = root; 31 | for (char c : word.toCharArray()) { 32 | if (node.children[c - 'a'] == null) { 33 | node.children[c - 'a'] = new TrieNode(); 34 | } 35 | node = node.children[c - 'a']; 36 | } 37 | node.item = word; 38 | } 39 | 40 | /** 41 | * Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. 42 | */ 43 | public boolean search(String word) { 44 | return match(word.toCharArray(), 0, root); 45 | } 46 | 47 | private boolean match(char[] chs, int k, TrieNode node) { 48 | if (k == chs.length) 49 | return !node.item.equals(""); 50 | if (chs[k] != '.') { 51 | return node.children[chs[k] - 'a'] != null && match(chs, k + 1, node.children[chs[k] - 'a']); 52 | } else { 53 | for (int i = 0; i < node.children.length; i++) { 54 | if (node.children[i] != null) { 55 | if (match(chs, k + 1, node.children[i])) { 56 | return true; 57 | } 58 | } 59 | } 60 | } 61 | return false; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/kSum/ThreeSum_15.java: -------------------------------------------------------------------------------- 1 | package kSum; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @Author jiangyunxiong 9 | * @Date 2019/1/14 下午8:41 10 | * 三数之和 11 | *

12 | * 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。 13 | */ 14 | public class ThreeSum_15 { 15 | 16 | List> ret = new ArrayList>(); 17 | 18 | /** 19 | * 这题相比2SUM多了几个难点: 20 | * 21 | * 1. 数组里允许重复的数 22 | * 2. 结果要按升序排列 23 | * 3. 结果中不能出现重复的结 24 | * 25 | * 思路:排序 + 左右夹逼,注意过滤重复项 26 | */ 27 | public List> threeSum(int[] nums) { 28 | 29 | if (nums == null || nums.length < 3) { 30 | return ret; 31 | } 32 | Arrays.sort(nums); 33 | 34 | int len = nums.length; 35 | for (int i = 0; i < len - 2; i++) { 36 | if (i > 0 && nums[i] == nums[i - 1])//过滤重复项 37 | continue; 38 | find(nums, i + 1, len - 1, nums[i]); 39 | 40 | } 41 | return ret; 42 | 43 | } 44 | 45 | private void find(int[] nums, int begin, int end, int target) { 46 | int l = begin, r = end; 47 | //左右夹逼的方法 48 | while (l < r) { 49 | if (nums[l] + nums[r] + target == 0) { 50 | List ans = new ArrayList(); 51 | ans.add(target); 52 | ans.add(nums[l]); 53 | ans.add(nums[r]); 54 | ret.add(ans); 55 | while (l < r && nums[l] == nums[l + 1]) l++;//过滤重复项 56 | while (l < r && nums[r] == nums[r - 1]) r--;//过滤重复项 57 | l++; 58 | r--; 59 | } else if (nums[l] + nums[r] + target < 0) { 60 | l++; 61 | } else { 62 | r--; 63 | } 64 | } 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/二叉树/搜索/AddOneRowtoTree_623.java: -------------------------------------------------------------------------------- 1 | package 二叉树.搜索; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | /** 7 | * @Author jiangyunxiong 8 | * @Date 2019/1/3 下午8:42 9 | * 10 | * 在二叉树中增加一行 11 | * 12 | * 给定一个二叉树,根节点为第1层,深度为 1。在其第 d 层追加一行值为 v 的节点。 13 | */ 14 | public class AddOneRowtoTree_623 { 15 | 16 | class TreeNode { 17 | int val; 18 | TreeNode left; 19 | TreeNode right; 20 | TreeNode(int x) { val = x; } 21 | } 22 | 23 | /** 24 | * 思路:层序遍历,每遍历完一行,d减一,当d==1时,就到了需要增加行的深度位置, 25 | * 然后新建值为v的左右子结点,作为原结点的新左右子结点,将原有的左子结点连到新建的左子结点的左子结点上,将原有的右子结点连到新建的右子结点的右子结点 26 | */ 27 | public TreeNode addOneRow(TreeNode root, int v, int d) { 28 | if(root == null) return null; 29 | if(d == 1){ 30 | TreeNode newRoot = new TreeNode(v); 31 | newRoot.left = root; 32 | return newRoot; 33 | } 34 | Queue queue = new LinkedList<>(); 35 | queue.add(root); 36 | while(!queue.isEmpty()){ 37 | //检测d为0时,直接返回,因为添加操作已经完成,没必要遍历剩下的结点 38 | if(--d == 0) return root; 39 | int size = queue.size(); 40 | for(int i=0;i 8 | * 归并排序的思想是将数组分成两部分,分别进行排序,然后归并起来。 9 | */ 10 | public class MergeSort extends Base { 11 | 12 | private static int[] aux; 13 | 14 | private static void merge(int[] a, int l, int m, int h) { 15 | int i = l, j = m + 1; 16 | 17 | for (int k = l; k <= h; k++) 18 | aux[k] = a[k];//将数据复制到辅助数组 19 | 20 | for (int k = l; k <= h; k++) { 21 | if (i > m) 22 | a[k] = aux[j++]; 23 | else if (j > h) 24 | a[k] = aux[i++]; 25 | else if (compare(aux[i], a[j])) 26 | a[k] = aux[i++]; // 先进行这一步,保证稳定性 27 | else 28 | a[k] = aux[j++]; 29 | } 30 | } 31 | 32 | /** 33 | * 自顶向下归并排序 34 | * 35 | * @param a 36 | */ 37 | public static void sortUpDown(int[] a) { 38 | aux = new int[a.length]; 39 | sort(a, 0, a.length - 1); 40 | } 41 | 42 | private static void sort(int[] a, int l, int h) { 43 | if (h <= l) 44 | return; 45 | int mid = l + (h - l) / 2; 46 | sort(a, l, mid); 47 | sort(a, mid + 1, h); 48 | merge(a, l, mid, h); 49 | } 50 | 51 | /** 52 | * 自底向上归并排序 53 | * 先归并那些微型数组,然后成对归并得到的微型数组。 54 | * 55 | * @param a 56 | */ 57 | public static void sortDownUp(int[] a) { 58 | int N = a.length; 59 | aux = new int[N]; 60 | for (int sz = 1; sz < N; sz += sz) { 61 | for (int lo = 0; lo < N - sz; lo += sz + sz) { 62 | merge(a, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, N - 1)); 63 | } 64 | } 65 | } 66 | 67 | public static void main(String[] args) { 68 | int[] a = {1, 5, 8, 6, 6, 2, 2, 3, 33, 4, 4}; 69 | MergeSort.sortUpDown(a); 70 | for (int i : a) { 71 | System.out.println(i); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/动态规划/背包问题/CoinChange_322.java: -------------------------------------------------------------------------------- 1 | package 动态规划.背包问题; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/12 下午6:35 8 | *

9 | * 给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。 10 | * 如果没有任何一种硬币组合能组成总金额,返回 -1。 11 | */ 12 | public class CoinChange_322 { 13 | /** 14 | * 思路:完全背包问题,你可以认为每种硬币的数量是无限的 15 | * 采用动态规划维护一个二维数组dp,dp[i][j]表示从第一个元素到第i个元素累计总金额为j时的最少硬币数量,递推公式为: 16 | * dp[i][j] = min(dp[i - 1][j], dp[i][j - coins[i-1]]+1); 17 | */ 18 | public int coinChange(int[] coins, int amount) { 19 | 20 | 21 | if (amount < 0 || coins.length == 0) { 22 | return -1; 23 | } 24 | 25 | int n = coins.length; 26 | int[][] dp = new int[n + 1][amount + 1]; 27 | 28 | for (int i = 1; i < n + 1; i++) { 29 | dp[i][0] = 0; 30 | } 31 | for (int j = 1; j < amount + 1; j++) { 32 | dp[0][j] = amount + 1; 33 | } 34 | 35 | for (int i = 1; i < n + 1; i++) { 36 | for (int j = 1; j < amount + 1; j++) { 37 | if (j >= coins[i - 1]) { 38 | dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - coins[i - 1]] + 1); 39 | } else { 40 | dp[i][j] = dp[i - 1][j]; 41 | } 42 | } 43 | } 44 | 45 | return dp[n][amount] == (amount + 1) ? -1 : dp[n][amount]; 46 | 47 | } 48 | 49 | /** 50 | * 空间复杂度降为一维,递推公式为: 51 | * dp[i] = min(dp[i], dp[i - coins[j]] + 1); 52 | */ 53 | public int coinChange2(int[] coins, int amount) { 54 | if (coins == null || coins.length == 0 || amount <= 0) return 0; 55 | int[] dp = new int[amount + 1]; 56 | Arrays.fill(dp, amount + 1); 57 | dp[0] = 0; 58 | for (int j = 0; j < coins.length; j++) 59 | for (int i = coins[j]; i <= amount; i++) 60 | dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1); 61 | return dp[amount] > amount ? -1 : dp[amount]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/字典树/Trie_208.java: -------------------------------------------------------------------------------- 1 | package 字典树; 2 | 3 | /** 4 | * @Auther: Jesper 5 | * @Date: 2019/1/9 18:12 6 | * @Description: 实现 Trie (前缀树) 7 | */ 8 | public class Trie_208 { 9 | 10 | class TrieNode { 11 | public char val; 12 | public boolean isWord; 13 | TrieNode[] children = new TrieNode[26]; 14 | 15 | public TrieNode() { 16 | } 17 | 18 | TrieNode(char c) { 19 | TrieNode node = new TrieNode(); 20 | node.val = c; 21 | } 22 | } 23 | 24 | private TrieNode root; 25 | 26 | /** 27 | * Initialize your data structure here. 28 | */ 29 | 30 | public Trie_208() { 31 | root = new TrieNode(); 32 | root.val = ' '; 33 | } 34 | 35 | 36 | /** 37 | * Inserts a word into the trie. 38 | */ 39 | public void insert(String word) { 40 | TrieNode node = root; 41 | for (char c : word.toCharArray()) { 42 | if (node.children[c - 'a'] == null) { 43 | node.children[c - 'a'] = new TrieNode(c); 44 | } 45 | node = node.children[c - 'a']; 46 | } 47 | node.isWord = true; 48 | } 49 | 50 | /** 51 | * Returns if the word is in the trie. 52 | */ 53 | public boolean search(String word) { 54 | TrieNode node = root; 55 | for (char c : word.toCharArray()) { 56 | if (node.children[c - 'a'] == null) { 57 | return false; 58 | } 59 | node = node.children[c - 'a']; 60 | } 61 | return node.isWord; 62 | } 63 | 64 | /** 65 | * Returns if there is any word in the trie that starts with the given prefix. 66 | */ 67 | public boolean startsWith(String prefix) { 68 | TrieNode node = root; 69 | for (char c : prefix.toCharArray()) { 70 | if (node.children[c - 'a'] == null) { 71 | return false; 72 | } 73 | node = node.children[c - 'a']; 74 | } 75 | return true; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/动态规划/背包问题/PartitionEqualSubsetSum_416.java: -------------------------------------------------------------------------------- 1 | package 动态规划.背包问题; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2019/1/12 上午11:42 8 | * 9 | * 给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 10 | */ 11 | public class PartitionEqualSubsetSum_416 { 12 | 13 | /** 14 | * 思路: 典型的01背包问题,在n个物品中选出一定物品,填满sum/2的背包。 15 | * 若只考虑第i个整数的策略(选或不选)如果我们不选取第i个整数,dp[i][j]=dp[i-1][j],这意味着如果第一个i-1元素已经到达j,dp[i][j]也会到达j(我们可以忽略nums[i])。如果我们选择nums[i]。dp 16 | * [i][j]=dp[i-1][j-nums[i]],表示j由当前值nums[i]组成,其余由其他以前的数字组成。因此,转换函数是dp[i][j]=dp[i-1][j]dp[i-1][j-nums[i]] 17 | * 18 | * 时间和空间复杂度均为O(n*Sum) 19 | */ 20 | public boolean canPartition(int[] nums) { 21 | int sum = 0; 22 | 23 | for (int num : nums) { 24 | sum += num; 25 | } 26 | 27 | if ((sum & 1) == 1) { 28 | return false; 29 | } 30 | sum /= 2; 31 | 32 | int n = nums.length; 33 | boolean[][] dp = new boolean[n + 1][sum + 1]; 34 | for (int i = 0; i < dp.length; i++) { 35 | Arrays.fill(dp[i], false); 36 | } 37 | 38 | dp[0][0] = true; 39 | 40 | for (int i = 1; i < n + 1; i++) { 41 | dp[i][0] = true; 42 | } 43 | for (int j = 1; j < sum + 1; j++) { 44 | dp[0][j] = false; 45 | } 46 | 47 | for (int i = 1; i < n + 1; i++) { 48 | for (int j = 1; j < sum + 1; j++) { 49 | if (j >= nums[i - 1]) { 50 | dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i - 1]]; 51 | } 52 | } 53 | } 54 | 55 | return dp[n][sum]; 56 | } 57 | 58 | /** 59 | * 时间复杂度基本已经不能再优化了,但空间复杂度却可以优化到O(Sum) 60 | */ 61 | public boolean canPartition2(int[] nums) { 62 | if (nums.length <= 1) { 63 | return false; 64 | } 65 | int sum = 0; 66 | for (int i = 0; i < nums.length; i++) { 67 | sum += nums[i]; 68 | } 69 | if (sum % 2 != 0) { 70 | return false; 71 | } 72 | 73 | sum /= 2; 74 | 75 | boolean[] dp = new boolean[sum + 1]; 76 | Arrays.fill(dp, false); 77 | 78 | dp[0] = true; 79 | for (int i = 1; i < nums.length; i++) { 80 | for (int j = sum; j >= nums[i]; j--) { 81 | dp[j] = dp[j] || dp[j - nums[i]]; 82 | } 83 | } 84 | return dp[sum]; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/链表/双向/MyLinkedList_707.java: -------------------------------------------------------------------------------- 1 | package 链表.双向; 2 | 3 | /** 4 | * @Author jiangyunxiong 5 | * @Date 2018/12/27 下午9:07 6 | *

7 | * 双向链表 8 | */ 9 | public class MyLinkedList_707 { 10 | /** 11 | * Initialize your data structure here. 12 | */ 13 | class Node { 14 | int val; 15 | Node next; 16 | 17 | public Node(int v) { 18 | this.val = v; 19 | } 20 | } 21 | 22 | Node currHead; 23 | Node currTail; 24 | int size; 25 | 26 | 27 | public MyLinkedList_707() { 28 | currHead = null; 29 | currTail = null; 30 | 31 | size = 0; 32 | } 33 | 34 | /** 35 | * Get the value of the index-th node in the linked list. If the index is invalid, return -1. 36 | */ 37 | public int get(int index) { 38 | if (index >= size) return -1; 39 | Node tmp = currHead; 40 | for (int i = 0; i < index; i++) tmp = tmp.next; 41 | 42 | return tmp.val; 43 | 44 | } 45 | 46 | /** 47 | * Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. 48 | */ 49 | public void addAtHead(int val) { 50 | Node tmp = new Node(val); 51 | tmp.next = currHead; 52 | currHead = tmp; 53 | if (currTail == null) currTail = currHead; 54 | size++; 55 | } 56 | 57 | /** 58 | * Append a node of value val to the last element of the linked list. 59 | */ 60 | public void addAtTail(int val) { 61 | 62 | Node tmp = new Node(val); 63 | if (currTail != null) currTail.next = tmp; 64 | if (currTail == null) currHead = tmp; 65 | currTail = tmp; 66 | size++; 67 | 68 | } 69 | 70 | /** 71 | * Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. 72 | */ 73 | public void addAtIndex(int index, int val) { 74 | 75 | if (index > size) return; 76 | 77 | if (index == size) { 78 | addAtTail(val); 79 | return; 80 | } 81 | if (index == 0) { 82 | addAtHead(val); 83 | return; 84 | } 85 | 86 | Node ith = currHead; 87 | for (int i = 0; i < index - 1; i++) ith = ith.next; 88 | 89 | Node tmp = new Node(val); 90 | Node saveIth = ith; 91 | ith = ith.next; 92 | 93 | saveIth.next = tmp; 94 | tmp.next = ith; 95 | 96 | size++; 97 | } 98 | 99 | /** 100 | * Delete the index-th node in the linked list, if the index is valid. 101 | */ 102 | public void deleteAtIndex(int index) { 103 | if (size == 0) return; 104 | if (index >= size) return; 105 | if (index == 0) { 106 | if (size == 1) { 107 | size = 0; 108 | currHead = null; 109 | currTail = null; 110 | return; 111 | } 112 | currHead = currHead.next; 113 | size--; 114 | return; 115 | } 116 | 117 | if (index != 0) { 118 | Node ith = currHead; 119 | for (int i = 0; i < index - 1; i++) ith = ith.next; 120 | if (index == size - 1) { 121 | currTail = ith; 122 | currTail.next = null; 123 | size--; 124 | return; 125 | } 126 | Node nekMinnit = ith.next; 127 | ith.next = nekMinnit.next; 128 | 129 | } 130 | 131 | size--; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/字符串/NumUniqueEmails_929.java: -------------------------------------------------------------------------------- 1 | package 字符串; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @Author jiangyunxiong 7 | * @Date 2018/12/22 上午9:01 8 | * 9 | * 独特的电子邮件地址 10 | */ 11 | public class NumUniqueEmails_929 { 12 | 13 | public static void main(String[] args) { 14 | NumUniqueEmails_929 n = new NumUniqueEmails_929(); 15 | String[] s = new String[]{"ihbumoogi+e@rbsvc.com","n.j.ax.t.xcsoz+k@lo.xap.com","x+x.a.w.c+z.e.u+m.y@fnsx.com", 16 | "fj.j.j.w+tv+g.ri@dvmqt.y.com","fj.j.j.w+z.o.z.h.h@dvmqt.y.com","dg.nru.bcsyw+d@nkynkj.ckq.com", 17 | "h.f.q.ns+tshpz@nn.r.com","ihbumoogi+e@rbsvc.com","s+l.dl.sft.vn.q@tqbxjqg.com", 18 | "zze.ovoqr+ds@cx.kahuobzk.com","n.j.ax.t.xcsoz+y@lo.xap.com","n.j.ax.t.xcsoz+c@lo.xap.com", 19 | "fj.j.j.w+z.ps.fp@dvmqt.y.com","f.q+ibv.d.usw.s@sanzdu.com","s+h+b+v.c+wv+jl+c@tqbxjqg.com", 20 | "fj.j.j.w+zr.yim@dvmqt.y.com","x+hwywuxhys@fm.qeqlb.com","o.rs+ik.h.s.d.fv@zpavzp.g.com", 21 | "n.j.ax.t.xcsoz+m@lo.xap.com","e.pt.o.rn+a.uj.u@mqhs.com","x+p+ad+rg+g+n+b+l@fm.qeqlb.com","e.pt.o.rn+e.j.b+o@mqhs.com","e.pt.o.rn+t.x.u+w@mqhs.com","q+e.el.pbr.gkg@knryg.zpztb.com","h.f.q.ns+z.mq+i+f@nn.r.com","x+ou.x+n.fp+lp.t@fnsx.com","ihbumoogi+c@rbsvc.com","x+wv+pq+gyfq.g@fnsx.com","x+mg.t.qg.toff@fm.qeqlb.com","q+d.gzbzme.v+n@knryg.zpztb.com","q+c.f.g.a.i.h.b+h.o@knryg.zpztb.com","zze.ovoqr+yl@cx.kahuobzk.com","ihbumoogi+p@rbsvc.com","n.j.ax.t.xcsoz+e@lo.xap.com","ihbumoogi+b@rbsvc.com","dg.nru.bcsyw+e@nkynkj.ckq.com","h.f.q.ns+f+pust@nn.r.com","s+un.e.t.u.r.t.v.s@tqbxjqg.com","s+l+nqqg.khwb@tqbxjqg.com","fj.j.j.w+n.ggl.u@dvmqt.y.com","n.j.ax.t.xcsoz+b@lo.xap.com","o.rs+lb.z.z.ff.e@zpavzp.g.com","x+vd+lm.a+ui+z.j@fm.qeqlb.com","e.pt.o.rn+kocq@mqhs.com","q+ugt+zzi.e+em@knryg.zpztb.com","zze.ovoqr+nv@cx.kahuobzk.com","zze.ovoqr+yt@cx.kahuobzk.com","zze.ovoqr+fn@cx.kahuobzk.com","f.q+e.d+j.x+b.p+g+s@sanzdu.com","e.pt.o.rn+d.p.p+w@mqhs.com","q+jtigu.e.h.ro@knryg.zpztb.com","h.f.q.ns+rfu+qv@nn.r.com","x+y.x.ki.h+i.lj+e@fm.qeqlb.com","f.q+k.dl.myo.x+b@sanzdu.com","zze.ovoqr+pq@cx.kahuobzk.com","x+q.g.ln.e+e+f.b.v@fm.qeqlb.com","fj.j.j.w+v.p+jo+u@dvmqt.y.com","q+rhhbhnysj@knryg.zpztb.com","fj.j.j.w+wkzvo@dvmqt.y.com","h.f.q.ns+s.x+w+l+a@nn.r.com","n.j.ax.t.xcsoz+v@lo.xap.com","z.q.qs+ibb.q+b.h@gorofcn.com","z.q.qs+x.mw.o+lw@gorofcn.com","q+aca+cmy+f.q.a@knryg.zpztb.com","n.j.ax.t.xcsoz+r@lo.xap.com","z.q.qs+iafh.x+h@gorofcn.com","x+o.fq.dd.d+h.yk@fnsx.com","dg.nru.bcsyw+u@nkynkj.ckq.com","h.f.q.ns+q.e.q.c+t@nn.r.com","q+n.u.d.jm.jbx.v@knryg.zpztb.com","gb.s.uuxow+ge@dmn.qt.com","o.rs+t.mby.z+gv@zpavzp.g.com","o.rs+al.j.k.v.a+h@zpavzp.g.com","x+v+j.m+q.u+h.k+g+z@fnsx.com","e.pt.o.rn+b.a.h.h@mqhs.com","zze.ovoqr+z.m@cx.kahuobzk.com","o.rs+v+z.z.w.p+hu@zpavzp.g.com","e.pt.o.rn+kahp@mqhs.com","fj.j.j.w+d+j.o.r+p@dvmqt.y.com","o.rs+lmo.c+u.za@zpavzp.g.com","x+d+h.xm.t.y+i+p+s@fm.qeqlb.com","ab.dvi.g+z.etq@fu.p.com","q+lnbfkjawq@knryg.zpztb.com","xwlznirsxh+p@mzdvwed.com","x+l.m.co.d+z.i.i.i@fm.qeqlb.com","s+h.o.xep.j.ud+j@tqbxjqg.com","x+gc.dss.k.d+r.m@fm.qeqlb.com","zze.ovoqr+rr@cx.kahuobzk.com","n.j.ax.t.xcsoz+m@lo.xap.com","s+g.k.z+v.yq.y.z+r@tqbxjqg.com","h.f.q.ns+y.f+r.y.w@nn.r.com","z.q.qs+o.ek+n.q+j@gorofcn.com","n.j.ax.t.xcsoz+q@lo.xap.com","q+b.m.c+p.b.m+o.u.b@knryg.zpztb.com"}; 22 | System.out.println(n.numUniqueEmails(s)); 23 | System.out.println(s.length); 24 | } 25 | 26 | public int numUniqueEmails(String[] emails) { 27 | Set set = new HashSet<>(); 28 | 29 | for (String i : emails){ 30 | String[] split = i.split("@"); 31 | String key= split[0].replace(".", "").split("\\+")[0]; 32 | set.add(new StringBuilder().append(key).append(split[1]).toString()); 33 | 34 | } 35 | return set.size() ; 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* 4 | 5 | - [二分查找](#%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE) 6 | - [双指针](#%E5%8F%8C%E6%8C%87%E9%92%88) 7 | - [kSum](#ksum) 8 | - [哈希表](#%E5%93%88%E5%B8%8C%E8%A1%A8) 9 | - [字典树](#%E5%AD%97%E5%85%B8%E6%A0%91) 10 | - [字符串](#%E5%AD%97%E7%AC%A6%E4%B8%B2) 11 | - [尺取法](#%E5%B0%BA%E5%8F%96%E6%B3%95) 12 | - [并查集](#%E5%B9%B6%E6%9F%A5%E9%9B%86) 13 | - [排序](#%E6%8E%92%E5%BA%8F) 14 | - [数学](#%E6%95%B0%E5%AD%A6) 15 | - [数组](#%E6%95%B0%E7%BB%84) 16 | - [栈](#%E6%A0%88) 17 | - [链表](#%E9%93%BE%E8%A1%A8) 18 | - [链表删除](#%E9%93%BE%E8%A1%A8%E5%88%A0%E9%99%A4) 19 | - [链表反转](#%E9%93%BE%E8%A1%A8%E5%8F%8D%E8%BD%AC) 20 | - [链表合并](#%E9%93%BE%E8%A1%A8%E5%90%88%E5%B9%B6) 21 | - [双向链表](#%E5%8F%8C%E5%90%91%E9%93%BE%E8%A1%A8) 22 | - [二叉树](#%E4%BA%8C%E5%8F%89%E6%A0%91) 23 | - [二叉树的遍历](#%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86) 24 | - [二叉树的层序遍历](#%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86) 25 | - [二叉树的路径](#%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%B7%AF%E5%BE%84) 26 | - [二叉树的搜索](#%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%90%9C%E7%B4%A2) 27 | - [二叉树的构造](#%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9E%84%E9%80%A0) 28 | - [二叉树的性质](#%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%80%A7%E8%B4%A8) 29 | - [深度优先搜索](#%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2) 30 | - [贪心](#%E8%B4%AA%E5%BF%83) 31 | - [回溯](#%E5%9B%9E%E6%BA%AF) 32 | - [分治](#%E5%88%86%E6%B2%BB) 33 | - [动态规划](#%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92) 34 | - [GameDP](#gamedp) 35 | - [MatrixDP](#matrixdp) 36 | - [SequenceDP](#sequencedp) 37 | - [TwoSequenceDP](#twosequencedp) 38 | - [背包问题](#%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98) 39 | 40 | 41 | 42 | 43 | 44 | ## 二分查找 45 | - [[704] Binary Search](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/BinarySearch_704.java) 46 | - [[441] Arranging Coins](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/ArrangeCoins_441.java) 47 | - [[222] Count Complete Tree Nodes](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/CountCompleteTreeNodes_222.java) 48 | - [[162] Find Peak Element](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/FindPeakElement_162.java) 49 | - [[744] Find Smallest Letter Greater Than Target](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/FindSmallestLetterGreaterThan_744.java) 50 | - [[278] First Bad Version](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/FirstBadVersion_278.java) 51 | - [[374] Guess Number Higher or Lower](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/GuessNumberHigherorLower_374.java) 52 | - [[69] Sqrt(x)](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/MySqrt_69.java) 53 | - [[852] Peak Index in a Mountain Array](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/PeakIndexInMountainArray_852.java) 54 | - [[35] Search Insert Position](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/SearchInsertPosition_35.java) 55 | - [[540] Single Element in a Sorted Array](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/SingleNonDuplicate_540.java) 56 | - [[454] 4Sum II](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/Sum4_454.java) 57 | - [[33] Search in Rotated Sorted Array](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/SearchRotatedSortedArray_33.java) 58 | - [[81] Search in Rotated Sorted Array II](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE/SearchinRotatedSortedArrayII_81.java) 59 | 60 | 61 | 62 | ## 双指针 63 | - [[633] Sum of Square Numbers ](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8F%8C%E6%8C%87%E9%92%88/JudgeSquareSum_633.java) 64 | - [[11] Container With Most Water ](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8F%8C%E6%8C%87%E9%92%88/ContainerWithMostWater_11.java) 65 | - [[26] Remove Duplicates from Sorted Array](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8F%8C%E6%8C%87%E9%92%88/RemoveDuplicatesfromSortedArray_26.java) 66 | - [[27] Remove Element ](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8F%8C%E6%8C%87%E9%92%88/RemoveElement_27.java) 67 | - [[88] Merge Sorted Array ](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8F%8C%E6%8C%87%E9%92%88/MergeSortedArray_88.java) 68 | 69 | 70 | ## kSum 71 | - [[1] Two Sum](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/kSum/TwoSum_1.java) 72 | - [[15] 3Sum](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/kSum/ThreeSum_15.java) 73 | - [[16] 3Sum Closest](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/kSum/ThreeSumClosest_16.java) 74 | 75 | 76 | ## 哈希表 77 | - [[575] Distribute Candies ](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%93%88%E5%B8%8C%E8%A1%A8/DistributeCandies_575.java) 78 | - [[500] Keyboard Row](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%93%88%E5%B8%8C%E8%A1%A8/KeyboardRow_500.java) 79 | - [[771] Jewels and Stones](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%93%88%E5%B8%8C%E8%A1%A8/NumJewelsInStones_771.java) 80 | - [[884] Uncommon Words from Two Sentences](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%93%88%E5%B8%8C%E8%A1%A8/UncommonWordsfromTwoSentences_884.java) 81 | 82 | 83 | ## 字典树 84 | - [[211] Add and Search Word - Data structure design](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E5%85%B8%E6%A0%91/AddSearchWord_211.java) 85 | - [[208] Implement Trie (Prefix Tree)](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E5%85%B8%E6%A0%91/Trie_208) 86 | 87 | ## 字符串 88 | - [[22] Generate Parentheses](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E7%AC%A6%E4%B8%B2/GenerateParentheses_22.java) 89 | - [[929] Unique Email Addresses](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E7%AC%A6%E4%B8%B2/NumUniqueEmails_929.java) 90 | - [[821] Shortest Distance to a Character](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E7%AC%A6%E4%B8%B2/ShortestToChar_821.java) 91 | - [[709] To Lower Case](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E7%AC%A6%E4%B8%B2/ToLowerCase_709.java) 92 | - [[804] Unique Morse Code Words](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E7%AC%A6%E4%B8%B2/UniqueMorseRepresentations_804.java) 93 | - [[3] Longest Substring Without Repeating Characters](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E7%AC%A6%E4%B8%B2/LongestSubstringWithoutRepeatingCharacters_3.java) 94 | - [[14] Longest Common Prefix](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E7%AC%A6%E4%B8%B2/LongestCommonPrefix_14.java) 95 | - [[13] Roman to Integer](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%AD%97%E7%AC%A6%E4%B8%B2/RomanToInt_13.java) 96 | 97 | 98 | 99 | ## 尺取法 100 | - [[209] Minimum Size Subarray Sum](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%B0%BA%E5%8F%96%E6%B3%95/MinSubArrayLen_209.java) 101 | 102 | ## 并查集 103 | - [[107] Binary Tree Level Order Traversal II](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%B9%B6%E6%9F%A5%E9%9B%86/BinaryTreeLevelOrderTraversal_107.java) 104 | - [[684] Redundant Connection](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%B9%B6%E6%9F%A5%E9%9B%86/FindRedundantConnection_684.java) 105 | - [[112] Path Sum](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%B9%B6%E6%9F%A5%E9%9B%86/PathSum_112.java) 106 | - [[297] Serialize and Deserialize Binary Tree](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%B9%B6%E6%9F%A5%E9%9B%86/SerializeDeserializeBinary_297.java) 107 | - [[79] Word Search](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%B9%B6%E6%9F%A5%E9%9B%86/WordSearch_79.java) 108 | 109 | ## 排序 110 | - [[215] Kth Largest Element in an Array](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%8E%92%E5%BA%8F/KthLargestElementinanArray_215.java) 111 | - [[75] Sort Colors](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%8E%92%E5%BA%8F/SortColors_75.java) 112 | 113 | ## 数学 114 | - [[868] Binary Gap](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E5%AD%A6/BinaryGap_868.java) 115 | - [[204] Count Primes](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E5%AD%A6/CountPrimes_204.java) 116 | - [[942] DI String Match](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E5%AD%A6/DiStringMatch_942.java) 117 | - [[461] Hamming Distance](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E5%AD%A6/HammingDistance_461.java) 118 | - [[476] Number Complement](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E5%AD%A6/NumberComplement_476.java) 119 | - [[728] Self Dividing Numbers](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E5%AD%A6/SelfDividingNumbers_728.java) 120 | - [[67] Add Binary](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E5%AD%A6/AddBinary_67.java) 121 | - [[9] Palindrome Number](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E5%AD%A6/PalindromeNumber_9.java) 122 | - [[7] Reverse Integer](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E5%AD%A6/ReverseInteger_7.java) 123 | 124 | 125 | 126 | ## 数组 127 | - [[717] 1-bit and 2-bit Characters](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/BitAnd2bitCharacters_717.java) 128 | - [[412] Fizz Buzz](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/FizzBuzz_412.java) 129 | - [[832] Flipping an Image](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/FlipAndInvertImage_832.java) 130 | - [[349] Intersection of Two Arrays](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/IntersectionTwoArrays_349.java) 131 | - [[350] Intersection of Two Arrays II](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/IntersectionTwoArraysII_350.java) 132 | - [[905] Sort Array By Parity](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/SortArrayByParity_905.java) 133 | - [[922] Sort Array By Parity II](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/SortArrayByParityII_922.java) 134 | - [[766] Toeplitz Matrix](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/ToeplitzMatrix_766.java) 135 | - [[867] Transpose Matrix](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/Transpose_867.java) 136 | - [[66] Plus One](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/PlusOne_66.java) 137 | - [[1] Two Sum](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%95%B0%E7%BB%84/TwoSum_1.java) 138 | 139 | 140 | ## 栈 141 | - [[844] Backspace String Compare](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/BackspaceStringCompare_844.java) 142 | - [[682] Baseball Game](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/BaseballGame_682.java) 143 | - [[224] Basic Calculator](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/BasicCalculator_224.java) 144 | - [[150] Evaluate Reverse Polish Notation](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/EvaluateReversePolishNotation_150.java) 145 | - [[232] Implement Queue using Stacks](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/ImplementQueueusingStacks_232.java) 146 | - [[225] Implement Stack using Queues](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/ImplementStackusingQueues_225.java) 147 | - [[32] Longest Valid Parentheses](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/LongestValidParentheses_32.java) 148 | - [[155] Min Stack](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/MinStack_155.java) 149 | - [[496] Next Greater Element I](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/NextGreaterElementI_496.java) 150 | - [[71] Simplify Path](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/SimplifyPath_71.java) 151 | - [[20] Valid Parentheses](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%A0%88/ValidParentheses_20.java) 152 | 153 | 154 | 155 | ## 链表 156 | 157 | ### 链表删除 158 | - [[237] Delete Node in a Linked List](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E9%93%BE%E8%A1%A8/%E5%88%A0%E9%99%A4/DeleteNodeInLinkedList_237.java) 159 | - [[19] Remove Nth Node From End of List](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E9%93%BE%E8%A1%A8/%E5%88%A0%E9%99%A4/RemoveNthNodeFromEndofList_19.java) 160 | 161 | 162 | ### 链表反转 163 | - [[77] Combinations](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E9%93%BE%E8%A1%A8/%E5%8F%8D%E8%BD%AC/ReverseList_77.java) 164 | - [[24] Swap Nodes in Pairs](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E9%93%BE%E8%A1%A8/%E5%8F%8D%E8%BD%AC/SwapNodesinPairs_24.java) 165 | 166 | ### 链表合并 167 | - [[2] Add Two Numbers](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E9%93%BE%E8%A1%A8/%E5%90%88%E5%B9%B6/AddTwoNumbers_2.java) 168 | - [[160] Intersection of Two Linked Lists](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E9%93%BE%E8%A1%A8/%E5%90%88%E5%B9%B6/GetIntersectionNode_160.java) 169 | - [[21] Merge Two Sorted Lists](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E9%93%BE%E8%A1%A8/%E5%90%88%E5%B9%B6/MergeTwoLists_21.java) 170 | 171 | ### 双向链表 172 | - [[707] Design Linked List](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E9%93%BE%E8%A1%A8/%E5%8F%8C%E5%90%91/MyLinkedList_707.java) 173 | 174 | 175 | 176 | 177 | ## 二叉树 178 | 179 | ### 二叉树的遍历 180 | - [[144] Binary Tree Preorder Traversal](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E9%81%8D%E5%8E%86/BinaryTreePreorderTraversal_144.java) 181 | - [[94] Binary Tree Inorder Traversal](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E9%81%8D%E5%8E%86/BinaryTreeInorderTraversal_94.java) 182 | - [[145] Binary Tree Postorder Traversal](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E9%81%8D%E5%8E%86/BinaryTreePostorderTraversal_145.java) 183 | 184 | ### 二叉树的层序遍历 185 | - [[102] Binary Tree Level Order Traversal](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86/BinaryTreeLevelOrderTraversal_102.java) 186 | - [[107] Binary Tree Level Order Traversal II](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86/BinaryTreeLevelOrderTraversalII_107.java) 187 | - [[103] Binary Tree Zigzag Level Order Traversal](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86/BinaryTreeZigzagLevelOrderTraversal_103.java) 188 | - [[429] N-ary Tree Level Order Traversal](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E5%B1%82%E5%BA%8F%E9%81%8D%E5%8E%86/NaryTreeLevelOrderTraversal_429.java) 189 | 190 | ### 二叉树的路径 191 | - [[124] Binary Tree Maximum Path Sum](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E8%B7%AF%E5%BE%84/BinaryTreeMaximumPathSum_124.java) 192 | 193 | ### 二叉树的搜索 194 | 195 | - [[623] Add One Row to Tree](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/AddOneRowtoTree_623.java) 196 | - [[637] Average of Levels in Binary Tree](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/AverageofLevelsinBinaryTree_637.java) 197 | - [[199] Binary Tree Right Side View](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/BinaryTreeRightSideView_199.java) 198 | - [[513] Find Bottom Left Tree Value](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/FindBottomLeftTreeValue_513.java) 199 | - [[515] Find Largest Value in Each Tree Row](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/FindLargestValueinEachTreeRow_515.java) 200 | - [[236] Lowest Common Ancestor of a Binary Tree](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/LowestCommonAncestorofBinaryTree_236.java) 201 | - [[617] Merge Two Binary Trees](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/MergeTrees_617.java) 202 | - [[530] Minimum Absolute Difference in BST](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/MinimumAbsoluteDifferenceinBST_530.java) 203 | - [[116] Populating Next Right Pointers in Each Node](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/PopulatingNextRightPointersinEachNode_116.java) 204 | - [[700] Search in a Binary Search Tree](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%90%9C%E7%B4%A2/SearchBST_700.java) 205 | 206 | ### 二叉树的构造 207 | - [[108] Convert Sorted Array to Binary Search Tree](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/构造/ConvertSortedArrayBinarySearchTree_108.java) 208 | 209 | 210 | ### 二叉树的性质 211 | - [[669] Trim a Binary Search Tree](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%80%A7%E8%B4%A8/TrimBinarySearchTree_669.java) 212 | - [[110] Balanced Binary Tree ](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E4%BA%8C%E5%8F%89%E6%A0%91/%E6%80%A7%E8%B4%A8/BalanceTree_110.java) 213 | 214 | 215 | 216 | ## 深度优先搜索 217 | - [[690] Employee Importance](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2/EmployeeImportance_690.java) 218 | - [[897] Increasing Order Search Tree](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2/IncreasingOrderSearchTree_897.java) 219 | - [[872] Leaf-Similar Trees](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2/LeafSimilar_872.java) 220 | - [[542] 01 Matrix](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2/Matrix_542.java) 221 | - [[104] Maximum Depth of Binary Tree](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2/MaximumDepthofBinaryTree_104.java) 222 | - [[46] Permutations](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2/Permutations_46.java) 223 | - [[590] N-ary Tree Postorder Traversal](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2/TreePostorderTraversal_590.java) 224 | - [[589] N-ary Tree Preorder Traversal](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E6%B7%B1%E5%BA%A6%E4%BC%98%E5%85%88%E6%90%9C%E7%B4%A2/TreePreorderTraversal_589.java) 225 | 226 | ## 贪心 227 | - [[455] Assign Cookies](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E8%B4%AA%E5%BF%83/FindContentChildren_455.java) 228 | - [[392] Is Subsequence](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E8%B4%AA%E5%BF%83/IsSubsequence_392.java) 229 | - [[452] Minimum Number of Arrows to Burst Balloons ](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E8%B4%AA%E5%BF%83/MinimumNumberofArrowstoBurstBalloons_452.java) 230 | - [[435] Non-overlapping Intervals](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E8%B4%AA%E5%BF%83/NonOverlappingIntervals_435.java) 231 | - [[406] Queue Reconstruction by Height](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E8%B4%AA%E5%BF%83/ReconstructQueue_406.java) 232 | 233 | 234 | ## 回溯 235 | - [[401] Binary Watch](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%9B%9E%E6%BA%AF/BinaryWatch_401.java) 236 | - [[784] Letter Case Permutation ](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%9B%9E%E6%BA%AF/LetterCasePermutation_784.java) 237 | 238 | 239 | ## 分治 240 | - [[241] Different Ways to Add Parentheses](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%88%86%E6%B2%BB/DiffWaysToCompute_241.java) 241 | 242 | ## 动态规划 243 | 244 | ### GameDP 245 | - [[198] House Robber](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/GameDP/HouseRobber_198.java) 246 | - [[486] Predict the Winner](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/GameDP/PredicttheWinner_486.java) 247 | 248 | ### MatrixDP 249 | - [[64] Minimum Path Sum](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/MatrixDP/MinimumPathSum_64.java) 250 | - [[120] Triangle](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/MatrixDP/Triangle_120.java) 251 | - [[62] Unique Paths](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/MatrixDP/UniquePaths_62.java) 252 | - [[63] Unique Paths II](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/MatrixDP/UniquePathsII_63.java) 253 | 254 | ### SequenceDP 255 | - [[70] Climbing Stairs](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/SequenceDP/ClimbStairs_70.java) 256 | - [[55] Jump Game](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/SequenceDP/JumpGame_55.java) 257 | - [[300] Longest Increasing Subsequence](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/SequenceDP/LongestIncreasingSubsequence_300.java) 258 | 259 | ### TwoSequenceDP 260 | - [[72] Edit Distance](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/TwoSequencesDP/EditDistance_72.java) 261 | - [[77] Combinations](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/TwoSequencesDP/LongestCommonSubsequence_77.java) 262 | - [[53] Maximum Subarray](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/TwoSequencesDP/MaximumSubarray_53.java) 263 | 264 | ### 背包问题 265 | - [[416] Partition Equal Subset Sum](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/背包问题/PartitionEqualSubsetSum_416.java) 266 | - [[322] Coin Change](https://github.com/zaiyunduan123/leetcode-java/blob/master/src/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/背包问题/CoinChange_322.java) 267 | 268 | 269 | 270 | --------------------------------------------------------------------------------