diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4eecc56
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+*.idea/workspace.xml
+*.out/
+
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
\ No newline at end of file
diff --git a/.idea/junitgenerator-prj-settings.xml b/.idea/junitgenerator-prj-settings.xml
new file mode 100644
index 0000000..d73e792
--- /dev/null
+++ b/.idea/junitgenerator-prj-settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 0baf590..f048155 100644
--- a/README.md
+++ b/README.md
@@ -4,20 +4,23 @@
Easy
---
-题号|题目|Tags|star|
---- |--- |--- |--- |
+题号|题目|Tags|Star|Company|
+--- |--- |--- |--- |---|
[1](https://leetcode.com/problems/two-sum/description/) | [Two Sum](/src/Q1TwoSum.java) | HashMap | :star: :star: :star:
[7](https://leetcode.com/problems/reverse-integer/) | [Reverse Integer](/src/Q7ReverseInteger.java) | Integer | :star: :star:
[14](https://leetcode.com/problems/longest-common-prefix/description/) | [Longest Common Prefix](/src/Q14LongestCommonPrefix.java) | String | :star:
[20](https://leetcode.com/problems/valid-parentheses/description/) | [Valid Parentheses](/src/Q20ValidParentheses.java) | String、Stack | :star: :star: :star:
-[21](https://leetcode.com/problems/merge-two-sorted-lists/description/) | [Merge Two Sorted Lists](/src/Q21MergeTwoSortedLists.java) | LinkedList | :star: :star: :star:
-[53](https://leetcode.com/problems/maximum-subarray/description/) | [Maximum Subarray](/src/Q53MaximumSubarray.java) | Array、DP | :star: :star: :star: :star:
+[21](https://leetcode.com/problems/merge-two-sorted-lists/description/) | [Merge Two Sorted Lists](/src/Q21MergeTwoSortedLists.java) | LinkedList | :star: :star: :star: :star:
+[53](https://leetcode.com/problems/maximum-subarray/description/) | [Maximum Subarray](/src/Q53MaximumSubarray.java) | Array、DP | :star: :star: :star:
+[83](https://leetcode.com/problems/remove-duplicates-from-sorted-list/) | [Remove Duplicates from Sorted List](src/Q83RemoveDuplicatesfromSortedList.java) | ListNode | :star: :star: :star: | ByteDance
[88](https://leetcode.com/problems/merge-sorted-array/description/) | [Merge Sorted Array](/src/Q88MergeSortedArray.java) | Array、双指针
[100](https://leetcode.com/problems/same-tree/) | [Same Tree](/src/Q100SameTree.java) | Tree | :star: :star: :star:
[101](https://leetcode.com/problems/symmetric-tree/) | [Symmetric Tree](/src/Q101SymmetricTree.java) | Tree | :star: :star: :star:
[104](https://leetcode.com/problems/maximum-depth-of-binary-tree/description/) | [Maximum Depth of Binary Tree](/src/Q104MaximumDepthofBinaryTree.java) | Tree | :star: :star: :star:
[105](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/) | [Construct Binary Tree from Preorder and Inorder Traversal](/src/Q105ConstructBinaryTreefromPreorderandInorderTraversal.java) | Tree | :star: :star: :star:
-[108](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/) | [Convert Sorted Array to Binary Search Tree](/src/Q108ConvertSortedArraytoBinarySearchTree.java) | Tree | :star: :star: :star:
+[107](https://leetcode.com/problems/binary-tree-level-order-traversal-ii/submissions/) | [Binary Tree Level Order Traversal II](/src/Q107BinaryTreeLevelOrderTraversalII.java) | Tree | :star: :star:
+[108](https://leetcode.com/problems/convert-sorted-array-to-binary-search-tree/) | [Convert Sorted Array to Binary Search Tree](/src/Q108ConvertSortedArraytoBinarySearchTree.java) | BST | :star: :star: :star:
+[110](https://leetcode.com/problems/balanced-binary-tree/) | [Balanced Binary Tree](/src/Q110BalancedBinaryTree.java) | Tree,DFS | :star: :star: :star: :star:
[111](https://leetcode.com/problems/minimum-depth-of-binary-tree/) | [Minimum Depth of Binary Tree](/src/Q111MinimumDepthofBinaryTree.java) | Tree、递归 | :star: :star: :star:
[112](https://leetcode.com/problems/path-sum/) | [Path Sum](/src/Q112PathSum.java) | Tree | :star: :star:
[115](https://leetcode.com/problems/min-stack/) | [Min Stack](/src/Q155MinStack.java) | Stack | :star: :star: :star:
@@ -27,16 +30,18 @@ Easy
[122](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/) | [Best Time to Buy and Sell Stock II](/src/Q122BestTimetoBuyandSellStockII.java) | DP | :star:
[136](https://leetcode.com/problems/single-number/description/) | [Single Number](/src/Q136SingleNumber.java) | Array、二进制 | :star: :star: :star:
[141](https://leetcode.com/problems/linked-list-cycle/description/) | [Linked List Cycle](/src/Q141LinkedListCycle.java) | LinkedList、双指针 | :star: :star: :star:
-[148](https://leetcode.com/problems/sort-list/) | [Sort List](/src/Q148SortList.java) | LinkedList、MergeSort | :star: :star: :star:
-[160](https://leetcode.com/problems/intersection-of-two-linked-lists/description/) | [Intersection of Two Linked Lists](/src/Q160IntersectionofTwoLinkedLists.java) | LinkedList、双指针 | :star: :star: :star:
+[148](https://leetcode.com/problems/sort-list/) | [Sort List](/src/Q148SortList.java) | LinkedList、MergeSort | :star: :star: :star: :star: |ByteDance
+[160](https://leetcode.com/problems/intersection-of-two-linked-lists/description/) | [Intersection of Two Linked Lists](/src/Q160IntersectionofTwoLinkedLists.java) | LinkedList、双指针 | :star: :star: :star: :star: | ByteDance
[169](https://leetcode.com/problems/majority-element/description/) | [Majority Element](/src/Q169MajorityElement.java) | Array | :star: :star:
[198](https://leetcode.com/problems/house-robber/description/) | [House Robber](/src/Q198HouseRobber.java) | Array、DP | :star: :star: :star:
[200](https://leetcode.com/problems/number-of-islands/) | [Number of Islands](/src/Q200NumberofIslands.java) | DFS、BFS | :star: :star: :star:
-[206](https://leetcode.com/problems/reverse-linked-list/description/) | [Reverse Linked List](/src/Q206ReverseLinkedList.java) | ListNode | :star: :star: :star:
+[206](https://leetcode.com/problems/reverse-linked-list/description/) | [Reverse Linked List](/src/Q206ReverseLinkedList.java) | ListNode | :star: :star: :star: :star:
[207](https://leetcode.com/problems/course-schedule/) | [Course Schedule](/src/Q207CourseSchedule.java) | DFS、BFS | :star: :star: :star:
[217](https://leetcode.com/problems/contains-duplicate/description/) | [Contains Duplicate](/src/Q217ContainsDuplicate.java) | Array、HashTable | :star:
[226](https://leetcode.com/problems/invert-binary-tree/) | [Invert Binary Tree](/src/Q226InvertBinaryTree.java) | Tree | :star: :star: :star:
[234](https://leetcode.com/problems/palindrome-linked-list/description/) | [Palindrome Linked List](/src/Q234PalindromeLinkedList.java) | LinkedList、双指针 | :star: :star: :star:
+[235](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/) | [Lowest Common Ancestor of a Binary Search Tree](/src/Q235LowestCommonAncestorofaBinarySearchTree.java) | 递归 | :star: :star: :star:
+[257](https://leetcode.com/problems/binary-tree-paths/) | [Binary Tree Paths](/src/Q257BinaryTreePaths.java) | Tree, String | :star: :star: :star: :star:
[338](https://leetcode.com/problems/counting-bits/) | [Counting Bits](/src/Q338CountingBits.java) | bits | :star: :star: :star:
[401](https://leetcode.com/problems/binary-watch/description/) | [Binary Watch](/src/Q401BinaryWatch.java) | 递归 | :star:
[437](https://leetcode.com/problems/path-sum-iii/) | [Path Sum III](/src/Q437PathSumIII.java) | HashMap,Tree | :star: :star: :star:
@@ -44,16 +49,17 @@ Easy
[461](https://leetcode.com/problems/hamming-distance/) | [Hamming Distance](/src/Q461HammingDistance.java) | bits | :star: :star: :star:
[538](https://leetcode.com/problems/convert-bst-to-greater-tree/) | [Convert BST to Greater Tree](/src/Q538ConvertBSTtoGreaterTree.java) | 二叉搜索树 | :star: :star: :star:
[543](https://leetcode.com/problems/diameter-of-binary-tree/) | [ Diameter of Binary Tree](/src/Q543DiameterofBinaryTree.java) | Tree、递归 | :star: :star: :star:
-[572](https://leetcode.com/problems/subtree-of-another-tree/) | [Subtree of Another Tree](/src/Q572SubtreeofAnotherTree.java) | Tree | :star: :star: :star:
+[572](https://leetcode.com/problems/subtree-of-another-tree/) | [Subtree of Another Tree](/src/Q572SubtreeofAnotherTree.java) | Tree | :star: :star: :star: :star:
[581](https://leetcode.com/problems/shortest-unsorted-continuous-subarray/description/) | [Shortest Unsorted Continuous Subarray](/src/Q581ShortestUnsortedContinuousSubarray.java) | Array | :star: :star: :star:
[617](https://leetcode.com/problems/merge-two-binary-trees/) | [Merge Two Binary Trees](/src/Q617MergeTwoBinaryTrees.java) | Tree | :star: :star: :star:
[628](https://leetcode.com/problems/maximum-product-of-three-numbers/description/) | [Maximum Product of Three Numbers](/src/Q628MaximumProductofThreeNumbers.java) | Array | :star:
+[637](https://leetcode.com/problems/average-of-levels-in-binary-tree/) | [Average of Levels in Binary Tree](/src/Q637AverageofLevelsinBinaryTree.java) | Tree | :star: :star:
[771](https://leetcode.com/problems/jewels-and-stones/) | [Jewels and Stones](/src/Q771JewelsandStones.java) | String | :star:
Medium
---
-题号|题目|Tags|star|
----|---|--- |--- |
+题号|题目|Tags|Star|Company|
+---|---|--- |--- | --- |
[2](https://leetcode.com/problems/add-two-numbers/description/) | [Add Two Numbers](/src/Q2AddTwoNumbers.java) | LinkedList | :star: :star: :star:
[3](https://leetcode.com/problems/longest-substring-without-repeating-characters/description/) | [Longest Substring Without Repeating Characters](/src/Q3LongestSubstringWithoutRepeatingCharacters.java) | 双指针 | :star: :star: :star:
[5](https://leetcode.com/problems/longest-palindromic-substring/) | [Longest Palindromic Substring](/src/Q5LongestPalindromicSubstring.java) | String、动态规划 | :star: :star: :star:
@@ -61,6 +67,7 @@ Medium
[15](https://leetcode.com/problems/3sum/description/) | [3Sum](/src/Q153Sum.java) | Array、双指针 | :star: :star: :star:
[17](https://leetcode.com/problems/letter-combinations-of-a-phone-number/description/) | [Letter Combinations of a Phone Number](/src/Q17LetterCombinationsofaPhoneNumber.java) | 递归 | :star: :star: :star:
[19](https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/) | [Remove Nth Node From End of List](/src/Q19RemoveNthNodeFromEndofList.java) | 双指针 | :star: :star: :star:
+[21](https://leetcode.com/problems/merge-two-sorted-lists/) | [Merge Two Sorted Lists](/src/Q21MergeTwoSortedLists.java) | List,递归 | :star: :star: :star: :star:
[22](https://leetcode.com/problems/generate-parentheses/) | [Generate Parentheses](/src/Q22GenerateParentheses.java) | String、回溯法 | :star: :star: :star:
[24](https://leetcode.com/problems/swap-nodes-in-pairs/description/) | [Swap Nodes in Pairs](/src/Q24SwapNodesinPairs.java) | LinkedList | :star: :star: :star:
[34](https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/description/) | [Find First and Last Position of Element in Sorted Array](/src/Q34FindFirstandLastPositionofElementinSortedArray.java) | Array、BinarySearch | :star: :star: :star:
@@ -70,12 +77,13 @@ Medium
[47](https://leetcode.com/problems/permutations-ii/description/) | [PermutationsII](/src/Q47PermutationsII.java) | 回溯法 | :star: :star: :star:
[48](https://leetcode.com/problems/rotate-image/description/) | [Rotate Image](/src/Q48RotateImage.java) | 二维数组 | :star: :star:
[49](https://leetcode.com/problems/group-anagrams/description/) | [Group Anagrams](/src/Q49GroupAnagrams.java) | ArrayList, HashMap | :star: :star: :star:
+[54](https://leetcode.com/problems/spiral-matrix/) | [Spiral Matrix](/src/Q54SpiralMatrix.java) | 细节问题 | :star: :star:
[56](https://leetcode.com/problems/merge-intervals/description/) | [Merge Intervals](/src/Q56MergeIntervals.java) | 迭代器,自写比较函数 | :star: :star: :star:
[60](https://leetcode.com/problems/permutation-sequence/description/) | [Permutation Sequence](/src/Q60PermutationSequence.java) | Array、感觉像是递归
[61](https://leetcode.com/problems/rotate-list/description/) | [Rotate List](/src/Q61RotateList.java) | LinkedList、双指针 | :star:
[62](https://leetcode.com/problems/unique-paths/description/) | [Unique Paths](/src/Q62UniquePaths.java) | 二维数组、动态规划 | :star: :star: :star:
[63](https://leetcode.com/problems/unique-paths-ii/description/) | [Unique Paths II](/src/Q63UniquePathsII.java) | 二维数组、动态规划 | :star: :star: :star:
-[64](https://leetcode.com/problems/minimum-path-sum/description/) | [Minimum Path Sum](/src/Q64MinimumPathSum.java) | 二维数组、动态规划 | :star: :star: :star:
+[64](https://leetcode.com/problems/minimum-path-sum/description/) | [Minimum Path Sum](/src/Q64MinimumPathSum.java) | 二维数组、动态规划 | :star: :star: :star: :star:
[74](https://leetcode.com/problems/search-a-2d-matrix/) | [Search a 2D Matrix](/src/Q74Searcha2DMatrix.java) | 二分查找 | :star: :star:
[77](https://leetcode.com/problems/combinations/description/) | [Combinations](/src/Q77Combinations.java) | 回溯法 | :star: :star: :star:
[78](https://leetcode.com/problems/subsets/description/) | [Subsets](/src/Q78Subsets.java) | Array、回溯法 | :star: :star: :star:
@@ -85,21 +93,29 @@ Medium
[90](https://leetcode.com/problems/subsets-ii/description/) | [SubsetsII](/src/Q90SubsetsII.java) | Array、回溯法 | :star: :star: :star:
[92](https://leetcode.com/problems/reverse-linked-list-ii/) | [Reverse Linked List II](/src/Q92ReverseLinkedListII.java) | LinkedList | :star: :star: :star:
[94](https://leetcode.com/problems/binary-tree-inorder-traversal/description/) | [Binary Tree Inorder Traversal](/src/Q94BinaryTreeInorderTraversal.java) | Tree | :star: :star: :star:
-[96](https://leetcode.com/problems/unique-binary-search-trees/) | [Unique Binary Search Trees](/src/Q96UniqueBinarySearchTrees.java) | BST, 递归 | :star: :star: :star:
+[95](https://leetcode.com/problems/unique-binary-search-trees-ii/) | [Unique Binary Search Trees II](/src/Q95UniqueBinarySearchTreesII.java) | BST | :star: :star: :star:
+[96](https://leetcode.com/problems/unique-binary-search-trees/) | [Unique Binary Search Trees](/src/Q96UniqueBinarySearchTrees.java) | BST | :star: :star: :star:
+[98](https://leetcode.com/problems/validate-binary-search-tree/) | [Validate Binary Search Tree](/src/Q98ValidateBinarySearchTree.java) | BST | :star: :star: :star: | ByteDance
[102](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) | [Binary Tree Level Order Traversal](/src/Q102BinaryTreeLevelOrderTraversal.java) | Tree | :star: :star: :star:
-[103](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) | [Binary Tree Zigzag Level Order Traversal](/src/Q103BinaryTreeZigzagLevelOrderTraversal.java) | Tree | :star: :star: :star:
+[103](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) | [Binary Tree Zigzag Level Order Traversal](/src/Q103BinaryTreeZigzagLevelOrderTraversal.java) | Tree | :star: :star: :star: | ByteDance
+[109](https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/) | [Convert Sorted List to Binary Search Tree](/src/Q109ConvertSortedListtoBinarySearchTree.java) | BST | :star: :star: :star: :star
[113](https://leetcode.com/problems/path-sum-ii/) | [Path Sum II](/src/Q113PathSumII.java) | Tree | :star: :star:
-[114](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/) | [Flatten Binary Tree to Linked List](/src/Q114FlattenBinaryTreetoLinkedList.java) | Tree | :star: :star: :star:
-[120](https://leetcode.com/problems/triangle/) | [Triangle](/src/Q120Triangle.java) | DP | :star: :star: :star:
+[114](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/) | [Flatten Binary Tree to Linked List](/src/Q114FlattenBinaryTreetoLinkedList.java) | Tree、递归 | :star: :star: :star: :star | ByteDance
+[120](https://leetcode.com/problems/triangle/) | [Triangle](/src/Q120Triangle.java) | DP | :star: :star: :star: :star:
+[138](https://leetcode.com/problems/copy-list-with-random-pointer/) | [Copy List with Random Pointer](/src/Q138CopyListwithRandomPointer.java) | List | :star: :star: :star:
[139](https://leetcode.com/problems/word-break/) | [Word Break](/src/Q139WordBreak.java) | DP | :star: :star: :star:
[142](https://leetcode.com/problems/linked-list-cycle-ii/description/) | [Linked List Cycle II](/src/Q142LinkedListCycleII.java) | LinkedList、双指针 | :star: :star: :star:
[143](https://leetcode.com/problems/reorder-list/) | [Reorder List](/src/Q143ReorderList.java) | LinkedList | :star: :star: :star:
-[152](https://leetcode.com/problems/maximum-product-subarray/description/) | [Maximum Product Subarray](/src/Q152MaximumProductSubarray.java) | Array、 DP | :star: :star: :star:
+[152](https://leetcode.com/problems/maximum-product-subarray/description/) | [Maximum Product Subarray](/src/Q152MaximumProductSubarray.java) | Array、 DP | :star: :star: :star:
+[173](https://leetcode.com/problems/binary-search-tree-iterator/) | [Binary Search Tree Iterator](/src/Q173BinarySearchTreeIterator.java) | BST | :star: :star: :star:
+[199](https://leetcode.com/problems/binary-tree-right-side-view/) | [Binary Tree Right Side View](/src/Q199BinaryTreeRightSideView.java) | Tree,递归 | :star: :star: :star: :star: | ByteDance
[209](https://leetcode.com/problems/minimum-size-subarray-sum/description/) | [Minimum Size Subarray Sum](/src/Q209MinimumSizeSubarraySum.java) | Array、滑动窗口
[213](https://leetcode.com/problems/house-robber-ii/) | [House Robber II](/src/Q213HouseRobberII.java) | 动态规划 | :star: :star:
-[215](https://leetcode.com/problems/kth-largest-element-in-an-array/description/) | [Kth Largest Element in an Array](/src/Q215KthLargestElementinanArray.java) | Array、快速选择算法 | :star: :star: :star: :star:
+[215](https://leetcode.com/problems/kth-largest-element-in-an-array/description/) | [Kth Largest Element in an Array](/src/Q215KthLargestElementinanArray.java) | Array、快速选择算法 | :star: :star: :star: :star: | ihandy,ByteDance
[216](https://leetcode.com/problems/combination-sum-iii/description/) | [CombinationSumIII](/src/Q216CombinationSumIII.java) | Array、回溯法 | :star: :star: :star:
[221](https://leetcode.com/problems/maximal-square/) | [Maximal Square](/src/Q221MaximalSquare.java) | DP | :star: :star: :star:
+[230](https://leetcode.com/problems/kth-smallest-element-in-a-bst/) | [Kth Smallest Element in a BST](/src/Q230KthSmallestElementinaBST.java) | BST | :star: :star: :star: :star:
+[236](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/) | [Lowest Common Ancestor of a Binary Tree](/src/Q236LowestCommonAncestorofaBinaryTree.java) | 递归 | :star: :star: :star: :star: | ByteDance
[238](https://leetcode.com/problems/product-of-array-except-self/description/) | [Product of Array Except Self](/src/Q238ProductofArrayExceptSelf.java) | Array
[240](https://leetcode.com/problems/search-a-2d-matrix-ii/) | [Search a 2D Matrix II](/src/Q240Searcha2DMatrixII.java) | | :star: :star: :star:
[264](https://leetcode.com/problems/ugly-number-ii/) | [Ugly NumberII](/src/Q264UglyNumberII.java) | DP | :star: :star:
@@ -107,10 +123,14 @@ Medium
[287](https://leetcode.com/problems/find-the-duplicate-number/description/) | [Find the Duplicate Number](/src/Q287FindtheDuplicateNumber.java) | Array、双指针 | :star: :star: :star:
[300](https://leetcode.com/problems/longest-increasing-subsequence/) | [Longest Increasing Subsequence](/src/Q300LongestIncreasingSubsequence.java) | DP、Binary Search | :star: :star: :star:
[309](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/) | [Best Time to Buy and Sell Stock with Cooldown](/src/Q309BestTimetoBuyandSellStockwithCooldown.java) | DP、状态机 | :star: :star: :star:
+[322](https://leetcode.com/problems/coin-change/) | [Coin Change](/src/Q322CoinChange.java) | DP | :star: :star: :star: :star:
+[328](https://leetcode.com/problems/odd-even-linked-list/) | [Odd Even Linked List](/src/Q328OddEvenLinkedList.java) | ListNode | :star: :star:
[334](https://leetcode.com/problems/increasing-triplet-subsequence/) | [Increasing Triplet Subsequence](/src/Q334IncreasingTripletSubsequence.java) | | :star: :star:
-[337](https://leetcode.com/problems/house-robber-iii/) | [House Robber III](/src/Q337HouseRobberIII.java) | HashMap、DP | :star: :star: :star:
-[347](https://leetcode.com/problems/top-k-frequent-elements/) | [Top K Frequent Elements](/src/Q347TopKFrequentElements.java) | HashMap | :star: :star: :star:
-[357](https://leetcode.com/problems/count-numbers-with-unique-digits/description/) | [Count Numbers with Unique Digits](/src/Q357CountNumberswithUniqueDigits.java) | DP、回溯 | :star: :star: :star:
+[337](https://leetcode.com/problems/house-robber-iii/) | [House Robber III](/src/Q337HouseRobberIII.java) | HashMap、DP | :star: :star: :star:
+[343](https://leetcode.com/problems/integer-break/) | [Integer Break](/src/Q343IntegerBreak.java) | DP | :star: :star:
+[347](https://leetcode.com/problems/top-k-frequent-elements/) | [Top K Frequent Elements](/src/Q347TopKFrequentElements.java) | HashMap | :star: :star: :star: :star:
+[357](https://leetcode.com/problems/count-numbers-with-unique-digits/description/) | [Count Numbers with Unique Digits](/src/Q357CountNumberswithUniqueDigits.java) | DP、回溯 | :star: :star: :star:
+[416](https://leetcode.com/problems/partition-equal-subset-sum/) | [Partition Equal Subset Sum](/src/Q416PartitionEqualSubsetSum.java) | DP | :star: :star: :star: :star:
[438](https://leetcode.com/problems/find-all-anagrams-in-a-string/) | [Find All Anagrams in a String](/src/Q438FindAllAnagramsinaString.java) | HashTable、滑动窗口 | :star: :star: :star:
[442](https://leetcode.com/problems/find-all-duplicates-in-an-array/description/) | [Find All Duplicates in an Array](/src/Q442FindAllDuplicatesinanArray.java) | Array | :star: :star: :star:
[526](https://leetcode.com/problems/beautiful-arrangement/description/) | [BeautifulArrangement](/src/Q526BeautifulArrangement.java) | 回溯 | :star: :star: :star:
@@ -119,11 +139,18 @@ Medium
[673](https://leetcode.com/problems/number-of-longest-increasing-subsequence/) | [Number of Longest Increasing Subsequence](/src/Q673NumberofLongestIncreasingSubsequence.java) | DP | :star: :star:
[713](https://leetcode.com/problems/subarray-product-less-than-k/description/) | [Subarray Product Less Than K](/src/Q713SubarrayProductLessThanK.java) | 双指针、滑动窗口 | :star: :star:
[714](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/) | [Best Time to Buy and Sell Stock with Transaction Fee](/src/Q714BestTimetoBuyandSellStockwithTransactionFee.java) | 动态规划、状态机 | :star: :star: :star:
-
+[718](https://leetcode.com/problems/maximum-length-of-repeated-subarray/) | [Maximum Length of Repeated Subarray](/src/Q718MaximumLengthofRepeatedSubarray.java) | DP | :star: :star: :star:
+[946](https://leetcode.com/problems/validate-stack-sequences/) | [Validate Stack Sequences](/src/Q946ValidateStackSequences.java) | Stack | :star: :star:
+
Hard
---
-题号|题目|Tags|star|
----|---|--- |--- |
+题号|题目|Tags|Star|Company|
+---|---|--- |--- | ---|
[4](https://leetcode.com/problems/median-of-two-sorted-arrays/) | [Median of Two Sorted Arrays](/src/Q4MedianofTwoSortedArrays.java) | 分治思想、二分查找 | :star: :star: :star:
+[10](https://leetcode.com/problems/regular-expression-matching/) | [Regular Expression Matching](/src/Q10RegularExpressionMatching.java) | DP | :star: :star: :star:
+[23](https://leetcode.com/problems/merge-k-sorted-lists/) | [Merge k Sorted Lists](/src/Q23MergekSortedLists.java) | ListNode,归并排序,优先队列 | :star: :star: :star: :star:
[123](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/) | [Best Time to Buy and Sell Stock III](/src/Q123BestTimetoBuyandSellStockIII.java) | DP、状态机 | :star: :star: :star:
-[188](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/) | [Best Time to Buy and Sell Stock IV](/src/Q188BestTimetoBuyandSellStockIV.java) | DP | :star: :star: :star:
\ No newline at end of file
+[124](https://leetcode.com/problems/binary-tree-maximum-path-sum/) | [Binary Tree Maximum Path Sum](/src/Q124BinaryTreeMaximumPathSum.java) | Tree,递归 | :star: :star: :star:
+[146](https://leetcode.com/problems/lru-cache/) | [LRU Cache](/src/Q146LRUCache.java) | LRU,HashMap,LinkedHashMap | :star: :star: :star: | ByteDance
+[188](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/) | [Best Time to Buy and Sell Stock IV](/src/Q188BestTimetoBuyandSellStockIV.java) | DP | :star: :star: :star:
+[297](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/) | [Serialize and Deserialize Binary Tree](/src/Q297SerializeandDeserializeBinaryTree.java) | Tree | :star: :star: :star:
\ No newline at end of file
diff --git a/java.gitignore b/java.gitignore
new file mode 100644
index 0000000..4eecc56
--- /dev/null
+++ b/java.gitignore
@@ -0,0 +1,26 @@
+*.idea/workspace.xml
+*.out/
+
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
\ No newline at end of file
diff --git a/src/DynamicProgramming/KnapsackProblem/Fibonacci.java b/src/DynamicProgramming/KnapsackProblem/Fibonacci.java
deleted file mode 100644
index 2fa826a..0000000
--- a/src/DynamicProgramming/KnapsackProblem/Fibonacci.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package DynamicProgramming.KnapsackProblem;
-
-/**
- * 斐波那契问题是经典的动态规划问题,可以从这里面学到动态规划的思想
- *
- * 补充1:走台阶,每次可以走1步,或者两步,问有多少种可能
- *
- * 补充2:母牛生产问题,成熟母牛每年生一个小牛小牛三年之后成熟又可以生小牛。第一年有一头牛,
- * 第二年开始生小牛,给定整数N,求N年后牛的数量
- * @author ahscuml
- * @date 19-3-20
- * @time 下午3:14
- */
-public class Fibonacci {
- public static void main(String[] args) {
- System.out.println(fib1(8));
- System.out.println(fib2(8));
- System.out.println(cow(5));
- }
-
- /**
- * 递归的方法来做这个提,从上往下
- * */
- private static int fib1(int n) {
- if(n < 1) {
- return 0;
- } else if(n == 1 || n == 2) {
- return 1;
- }
- return fib1(n - 1) + fib1( n - 2);
- }
-
- /**
- * 动态规划的方法,O(N)的时间复杂度
- * */
- private static int fib2(int n) {
- if (n < 1) {
- return 0;
- } else if (n == 1 || n == 2) {
- return 1;
- }
- int res = 1, pre = 1;
- for (int i = 3; i <= n; i++) {
- res += pre;
- pre = res - pre;
- }
- return res;
- }
-
- /**
- * 小牛问题
- * 重点是找到递推的关系式
- * */
- private static int cow(int n) {
- if(n < 1) {
- return 0;
- } else if(n == 1 || n == 2 || n == 3) {
- return n;
- }
- // 前1年
- int n_1 = 3;
- // 前2年
- int n_2 = 2;
- // 前3年
- int n_3 = 1;
- for(int i = 4; i <= n; i++) {
- n_1 = n_1 + n_3;
- int temp = n_2;
- n_2 = n_1 - n_3;
- n_3 = temp;
- }
- return n_1;
- }
-}
diff --git a/src/DynamicProgramming/KnapsackProblem/Knapsack01.java b/src/DynamicProgramming/KnapsackProblem/Knapsack01.java
deleted file mode 100644
index 4c3bcc3..0000000
--- a/src/DynamicProgramming/KnapsackProblem/Knapsack01.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package DynamicProgramming.KnapsackProblem;
-
-import java.util.concurrent.atomic.AtomicIntegerArray;
-
-/**
- * @author ahscuml
- * @date 2018/11/28
- * @time 20:13
- */
-public class Knapsack01 {
- public static void main(String[] args) {
-
- }
-}
diff --git a/src/DynamicProgramming/KnapsackProblem/MaxPathSum.java b/src/DynamicProgramming/KnapsackProblem/MaxPathSum.java
deleted file mode 100644
index 2b582de..0000000
--- a/src/DynamicProgramming/KnapsackProblem/MaxPathSum.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package DynamicProgramming.KnapsackProblem;
-
-/**
- * 矩阵的最小路径和(左上角走到右下角,只能向右和向下走)
- *
- * @author ahscuml
- * @date 19-3-20
- * @time 下午3:53
- */
-public class MaxPathSum {
- public static void main(String[] args) {
- int[][] matrix = {{1,3,5,9},{8,1,3,4},{5,0,6,1},{8,8,4,0}};
- System.out.println(maxPathSum1(matrix));
- System.out.println(maxPathSum1(matrix));
- }
-
- /**
- * 创建一个二维数组来存储内容,dp[i][j]代表到达当前节点的最小路径值
- * 时间复杂度O(M * N),空间复杂度O(M * N)
- * */
- public static int maxPathSum1(int[][] matrix) {
- if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) {
- return 0;
- }
- int[][] dp = new int[matrix.length][matrix[0].length];
- dp[0][0] = matrix[0][0];
- for (int i = 1; i < matrix.length; i++) {
- dp[i][0] = dp[i - 1][0] + matrix[i][0];
- }
- for (int j = 1; j < matrix[0].length; j++) {
- dp[0][j] = dp[0][j - 1] + matrix[0][j];
- }
- for (int i = 1; i < matrix.length; i++) {
- for (int j = 1; j < matrix[0].length; j++) {
- dp[i][j] = Math.min(dp[i - 1][j],dp[i][j - 1]) + matrix[i][j];
- }
- }
- return dp[matrix.length - 1][matrix[0].length - 1];
- }
-
- /**
- * 对于上面的方法的优化,时间复杂度不变,但是空间复杂度变为O(mni(M,N))
- * */
- public static int maxPathSum2(int[][] matrix) {
- if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) {
- return 0;
- }
- int col = matrix.length;
- int row = matrix[0].length;
- int more = Math.max(col, row);
- int less = Math.min(col, row);
- // 判断是行更多一些,还是列更多一些
- boolean rowmore = more == col;
- int[] dp = new int[less];
- dp[0] = matrix[0][0];
- for (int i = 1; i < less; i++) {
- dp[i] = dp[i - 1] + (rowmore ? matrix[0][i] : matrix[i][0]);
- }
- for (int i = 1; i < more; i++) {
- dp[0] = dp[0] + (rowmore ? matrix[i][0] : matrix[0][i]);
- for (int j = 1; j < less; j++) {
- dp[j] = Math.min(dp[j - 1], dp[j]) + (rowmore ? matrix[i][j] : matrix[j][i]);
- }
- }
- return dp[less - 1];
- }
-}
diff --git a/src/DynamicProgramming/KnapsackProblem/MinCoin.java b/src/DynamicProgramming/KnapsackProblem/MinCoin.java
deleted file mode 100644
index 9bfd070..0000000
--- a/src/DynamicProgramming/KnapsackProblem/MinCoin.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package DynamicProgramming.KnapsackProblem;
-
-/**
- * @author ahscuml
- * @date 19-3-20
- * @time 下午4:33
- */
-public class MinCoin {
- public static void main(String[] args) {
- int[] coins = {1,2,5};
- int target = 11;
- System.out.println(minCoin1(coins, target));
- }
-
- /**
- * 首先要找到递推的关系式
- * dp[j]就是凑成j最少有多少种方法
- * */
- public static int minCoin1(int[] num, int target) {
- int[] dp = new int[target + 1];
- dp[0] = 0;
- for (int i = 1; i <= target; i++) {
- int min = -1;
- for (int coin : num) {
- if (i >= coin) {
- int temp = dp[i - coin];
- if (temp != -1) {
- min = min == -1 ? temp + 1 : (min > temp + 1 ? temp + 1 : min);
- }
- }
- }
- dp[i] = min;
- }
- return dp[target];
- }
-}
diff --git a/src/Q100SameTree.java b/src/Q100SameTree.java
index f431c58..8ba2f7d 100644
--- a/src/Q100SameTree.java
+++ b/src/Q100SameTree.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.LinkedList;
import java.util.Queue;
@@ -9,7 +11,7 @@
public class Q100SameTree {
/**
* 测试函数
- * */
+ */
public static void main(String[] args) {
TreeNode p1 = new TreeNode(1);
TreeNode p2 = new TreeNode(2);
@@ -23,13 +25,13 @@ public static void main(String[] args) {
q1.left = q2;
q1.right = q3;
- System.out.println(isSameTreeRec(p1,q1));
- System.out.println(isSameTreeIte(p1,q1));
+ System.out.println(isSameTreeRec(p1, q1));
+ System.out.println(isSameTreeIte(p1, q1));
}
/**
* 递归的方法遍历这两个树
- * */
+ */
public static boolean isSameTreeRec(TreeNode p, TreeNode q) {
if (p == null && q == null) return true;
if (p == null && q != null || p != null && q == null) return false;
@@ -39,17 +41,17 @@ public static boolean isSameTreeRec(TreeNode p, TreeNode q) {
/**
* 循环的方法来遍历树,同时只使用一个queue非常简洁,但是对于null的判断会增加时间复杂度。
- * */
+ */
public static boolean isSameTreeIte(TreeNode p, TreeNode q) {
Queue queue = new LinkedList<>();
queue.add(p);
queue.add(q);
- while(!queue.isEmpty()){
+ while (!queue.isEmpty()) {
TreeNode f = queue.poll();
TreeNode s = queue.poll();
- if(f == null && s == null){
+ if (f == null && s == null) {
continue;
- }else if(f == null || s == null || f.val != s.val){
+ } else if (f == null || s == null || f.val != s.val) {
return false;
}
queue.add(f.left);
@@ -59,14 +61,4 @@ public static boolean isSameTreeIte(TreeNode p, TreeNode q) {
}
return true;
}
-
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q101SymmetricTree.java b/src/Q101SymmetricTree.java
index ec98303..34447f4 100644
--- a/src/Q101SymmetricTree.java
+++ b/src/Q101SymmetricTree.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.Stack;
/**
@@ -114,14 +116,4 @@ private static boolean isSymmetricIte(TreeNode root) {
}
return true;
}
-
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q102BinaryTreeLevelOrderTraversal.java b/src/Q102BinaryTreeLevelOrderTraversal.java
index 052ad23..08efe95 100644
--- a/src/Q102BinaryTreeLevelOrderTraversal.java
+++ b/src/Q102BinaryTreeLevelOrderTraversal.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
@@ -89,23 +91,10 @@ private static void depth(TreeNode root, int depth, ArrayList
if (depth > list.size()) {
list.add(new ArrayList<>());
}
- // 获取之前添加的ArrayList然后添加数据;
+ // 获取之前添加的ArrayList然后添加数据;主要depth要减一
list.get(depth - 1).add(root.val);
depth(root.left, depth + 1, list);
depth(root.right, depth + 1, list);
}
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q103BinaryTreeZigzagLevelOrderTraversal.java b/src/Q103BinaryTreeZigzagLevelOrderTraversal.java
index 73fe2f6..f4ad8c3 100644
--- a/src/Q103BinaryTreeZigzagLevelOrderTraversal.java
+++ b/src/Q103BinaryTreeZigzagLevelOrderTraversal.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.*;
/**
@@ -27,52 +29,6 @@ public static void main(String[] args) {
System.out.println(Helper(treeNode1));
}
- /**
- * 通过翻转来实现,循环算法
- */
- public static List> zigzagLevelOrderIte(TreeNode root) {
- List> res = new ArrayList();
- List curRes = new ArrayList();
- if (root == null) {
- return res;
- }
- Queue queue = new LinkedList();
- queue.offer(root);
- TreeNode cur;
- int level = 1;
- // 当前层的元素数量
- int A = 1;
- // 下一层的元素数量
- int next = 0;
- while (!queue.isEmpty()) {
-
- cur = queue.poll();
- // 当前行减1;
- A--;
- curRes.add(cur.val);
- if (cur.left != null) {
- queue.offer(cur.left);
- next++;
- }
- if (cur.right != null) {
- queue.offer(cur.right);
- next++;
- }
- if (A == 0) {
- if (level % 2 == 0) {
- Collections.reverse(curRes);
- }
- res.add(curRes);
- curRes = new ArrayList();
- A = next;
- next = 0;
- level++;
- }
- }
- return res;
- }
-
-
/**
* 递归的算法
*/
@@ -92,6 +48,7 @@ private static void travel(TreeNode curr, List> sol, int level) {
List collection = sol.get(level);
if (level % 2 == 0) collection.add(curr.val);
+ // 不一样的地方,利用ArrayList 的特点,从头添加的时候会把后面的往后移动
else collection.add(0, curr.val);
travel(curr.left, sol, level + 1);
@@ -99,7 +56,7 @@ private static void travel(TreeNode curr, List> sol, int level) {
}
/**
- * 使用一个栈与一个队列来实现,因为栈弹出的过程就是翻转的过程
+ * 使用两个栈来实现,因为栈弹出的过程就是翻转的过程
*/
private static List> Helper(TreeNode root) {
TreeNode cur;
@@ -108,12 +65,12 @@ private static List> Helper(TreeNode root) {
return res;
}
Stack stack = new Stack<>();
- Queue queue = new LinkedList<>();
- queue.offer(root);
+ Stack queue = new Stack<>();
+ queue.push(root);
while (!queue.isEmpty() || !stack.isEmpty()) {
List temp = new ArrayList<>();
while (!queue.isEmpty()) {
- cur = queue.poll();
+ cur = queue.pop();
temp.add(cur.val);
if (cur.left != null) {
stack.push(cur.left);
@@ -127,11 +84,11 @@ private static List> Helper(TreeNode root) {
while (!stack.isEmpty()) {
cur = stack.pop();
temp.add(cur.val);
- if (cur.left != null) {
- queue.offer(cur.left);
- }
if (cur.right != null) {
- queue.offer(cur.right);
+ queue.push(cur.right);
+ }
+ if (cur.left != null) {
+ queue.push(cur.left);
}
}
if (!temp.isEmpty()) {
@@ -142,15 +99,38 @@ private static List> Helper(TreeNode root) {
}
/**
- * 树结构的定义
+ * 利用Collection.reverse函数来实现
*/
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
+ public static List> zigzagLevelOrderIte(TreeNode root) {
+ List> res = new ArrayList<>();
+ if (root == null) {
+ return res;
+ }
+ List curList = new ArrayList();
+ Queue queue = new LinkedList();
+ queue.offer(root);
+ TreeNode cur = null;
+ boolean iszigzag = false;
+ while (!queue.isEmpty()) {
+ int size = queue.size();
+ ArrayList list = new ArrayList();
+ while (size != 0) {
+ cur = queue.poll();
+ list.add(cur.val);
+ if (cur.left != null) {
+ queue.offer(cur.left);
+ }
+ if (cur.right != null) {
+ queue.offer(cur.right);
+ }
+ size--;
+ }
+ if (iszigzag) {
+ Collections.reverse(list);
+ }
+ res.add(list);
+ iszigzag = !iszigzag;
}
+ return res;
}
}
diff --git a/src/Q104MaximumDepthofBinaryTree.java b/src/Q104MaximumDepthofBinaryTree.java
index 39a780f..f6c5818 100644
--- a/src/Q104MaximumDepthofBinaryTree.java
+++ b/src/Q104MaximumDepthofBinaryTree.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.LinkedList;
import java.util.Queue;
@@ -86,14 +88,4 @@ private static int maxDepthIte(TreeNode root) {
}
return level;
}
-
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q105ConstructBinaryTreefromPreorderandInorderTraversal.java b/src/Q105ConstructBinaryTreefromPreorderandInorderTraversal.java
index c3c59f4..8fdf60b 100644
--- a/src/Q105ConstructBinaryTreefromPreorderandInorderTraversal.java
+++ b/src/Q105ConstructBinaryTreefromPreorderandInorderTraversal.java
@@ -1,4 +1,4 @@
-import TEST.InOrder;
+import util.TreeNode;
import java.util.HashMap;
import java.util.Map;
@@ -16,7 +16,7 @@ public static void main(String[] args) {
int[] preorder = {3, 9, 20, 15, 7};
int[] inorder = {9, 3, 15, 20, 7};
- preorderRec(buildTree(preorder,inorder));
+ preorderRec(buildTree(preorder, inorder));
}
/**
@@ -37,7 +37,7 @@ public static TreeNode buildTree(int[] preorder, int[] inorder) {
public static TreeNode buildTree(int[] preorder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd,
- Map inMap) {
+ Map inMap) {
if (preStart > preEnd || inStart > inEnd) {
return null;
}
@@ -63,17 +63,4 @@ public static void preorderRec(TreeNode root) {
preorderRec(root.right);
}
}
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q107BinaryTreeLevelOrderTraversalII.java b/src/Q107BinaryTreeLevelOrderTraversalII.java
new file mode 100644
index 0000000..4da0a5e
--- /dev/null
+++ b/src/Q107BinaryTreeLevelOrderTraversalII.java
@@ -0,0 +1,75 @@
+import util.TreeNode;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+/**
+ * 倒着层序遍历二叉树
+ *
+ * @author ahscuml
+ * @date 2019/4/29
+ * @time 12:09
+ */
+public class Q107BinaryTreeLevelOrderTraversalII {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+ // TODO
+ }
+
+ /**
+ * 后序遍历的递归实现,记录层数,确定添加元素的位置
+ */
+ public static List> levelOrderBottomII(TreeNode root) {
+ List> wrapList = new LinkedList>();
+ levelMaker(wrapList, root, 0);
+ return wrapList;
+ }
+
+ public static void levelMaker(List> list, TreeNode root, int level) {
+ if (root == null) return;
+ if (level >= list.size()) {
+ list.add(0, new LinkedList());
+ }
+ levelMaker(list, root.left, level + 1);
+ levelMaker(list, root.right, level + 1);
+ list.get(list.size() - level - 1).add(root.val);
+ }
+
+ /**
+ * 层序遍历循环方法
+ * 最后将结果逆序有两种方法,一种是规定好插入的位置,在第一个,另外一种是使用Collections.reverse()函数
+ */
+ public List> levelOrderBottom(TreeNode root) {
+ List> list = new ArrayList();
+ if (root == null) {
+ return list;
+ }
+ Queue queue = new LinkedList<>();
+ TreeNode cur = null;
+ queue.offer(root);
+ while (!queue.isEmpty()) {
+ List templist = new ArrayList();
+ int count = queue.size();
+ while (count > 0) {
+ cur = queue.poll();
+ templist.add(cur.val);
+ if (cur.left != null) {
+ queue.offer(cur.left);
+ }
+ if (cur.right != null) {
+ queue.offer(cur.right);
+ }
+ count--;
+ }
+ if (templist != null)
+ list.add(0, templist);
+ }
+ return list;
+ }
+}
+
+
diff --git a/src/Q108ConvertSortedArraytoBinarySearchTree.java b/src/Q108ConvertSortedArraytoBinarySearchTree.java
index f7ac3d7..98a68c7 100644
--- a/src/Q108ConvertSortedArraytoBinarySearchTree.java
+++ b/src/Q108ConvertSortedArraytoBinarySearchTree.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
/**
* @author ahscuml
* @date 2019/1/4
@@ -6,16 +8,16 @@
public class Q108ConvertSortedArraytoBinarySearchTree {
/**
* 测试函数
- * */
+ */
public static void main(String[] args) {
}
/**
* 利用递归的方法来说实现
- * */
+ */
public TreeNode sortedArrayToBST(int[] nums) {
- if(nums == null || nums.length == 0) {
+ if (nums == null || nums.length == 0) {
return null;
}
// 节点个数可能是奇数或者偶数,需要进行判断
@@ -23,8 +25,8 @@ public TreeNode sortedArrayToBST(int[] nums) {
return helper(nums, 0, n - 1);
}
- public TreeNode helper(int[] nums, int left ,int right) {
- if(right < left) {
+ public TreeNode helper(int[] nums, int left, int right) {
+ if (right < left) {
return null;
}
int mid = (right + left) / 2;
@@ -33,17 +35,4 @@ public TreeNode helper(int[] nums, int left ,int right) {
root.right = helper(nums, mid + 1, right);
return root;
}
-
- /**
- * 树结构的定义
- * */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q109ConvertSortedListtoBinarySearchTree.java b/src/Q109ConvertSortedListtoBinarySearchTree.java
new file mode 100644
index 0000000..0966fe7
--- /dev/null
+++ b/src/Q109ConvertSortedListtoBinarySearchTree.java
@@ -0,0 +1,70 @@
+import util.ListNode;
+import util.TreeNode;
+
+/**
+ * 把一个有序链表变成二叉查找树
+ *
+ * @author ahscuml
+ * @date 2019/5/18
+ * @time 1:00
+ */
+public class Q109ConvertSortedListtoBinarySearchTree {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+
+ }
+
+ /**
+ * 思路很简单和108题对应,但是108题中的array可以用index来找到中间值,list只能使用双指针这个方法
+ * 同样这个里面有很多的细节
+ */
+ public TreeNode sortedListToBST(ListNode head) {
+ if (head == null) {
+ return null;
+ }
+ if (head.next == null) {
+ return new TreeNode(head.val);
+ }
+ ListNode fast = head, slow = head, last = slow;
+ // 利用这种判断方法可以保障fast不是空
+ while (fast.next != null && fast.next.next != null) {
+ fast = fast.next.next;
+ last = slow;
+ slow = slow.next;
+ }
+ // 分裂为两个list
+ fast = slow.next;
+ last.next = null;
+ TreeNode cur = new TreeNode(slow.val);
+ if (head != slow) {
+ cur.left = sortedListToBST(head);
+ }
+ cur.right = sortedListToBST(fast);
+ return cur;
+ }
+
+ /**
+ * 跟上面的思路是一样的,但是分成了两个方法,更加好理解
+ */
+ public TreeNode sortedListToBSTII(ListNode head) {
+ if (head == null) return null;
+ return toBST(head, null);
+ }
+
+ public TreeNode toBST(ListNode head, ListNode tail) {
+ ListNode slow = head;
+ ListNode fast = head;
+ if (head == tail) return null;
+
+ while (fast != tail && fast.next != tail) {
+ fast = fast.next.next;
+ slow = slow.next;
+ }
+ TreeNode thead = new TreeNode(slow.val);
+ thead.left = toBST(head, slow);
+ thead.right = toBST(slow.next, tail);
+ return thead;
+ }
+}
diff --git a/src/Q10RegularExpressionMatching.java b/src/Q10RegularExpressionMatching.java
new file mode 100644
index 0000000..dd43a09
--- /dev/null
+++ b/src/Q10RegularExpressionMatching.java
@@ -0,0 +1,46 @@
+/**
+ * @author ahscuml
+ * @date 2019/4/7
+ * @time 0:04
+ */
+public class Q10RegularExpressionMatching {
+ public static void main(String[] args) {
+ // TODO 测试用例
+ }
+
+ public static boolean isMatch(String s, String p) {
+ boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];
+ // 初始化,当模式串为0的时候,除了0,0为true,其余都为false
+ dp[0][0] = true;
+ // 当s为0的时候,如果模式串带有*还可能为空,保证前面一个不是*
+ for(int j = 2; j <= p.length(); j++) {
+ if(p.charAt(j - 1) == '*' && j > 1 && p.charAt(j - 2) != '*') {
+ dp[0][j] = dp[0][j - 2];
+ }
+ }
+
+ for(int i = 1; i <= s.length(); i++) {
+ for(int j = 1; j <= p.length(); j++) {
+ // 首先确定如果相等的情况
+ if(s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.') {
+ // 匹配的情况
+ dp[i][j] = dp[i - 1][j - 1];
+ }
+ // 不匹配的情况,1. 真的不匹配,不用管,因为默认是false
+ // 2. 出现'*'
+ if(p.charAt(j - 1) == '*') {
+ if(s.charAt(i - 1) != p.charAt(j - 2) && p.charAt(j - 2) != '.') {
+ // 不匹配任何内容,那么x*只能为空
+ dp[i][j] = dp[i][j - 2];
+ } else {
+ // 2.1 x*不匹配任何内容,直接跳过
+ // 2.2 x*匹配一个内容
+ // 2.3 x*匹配很多个内容
+ dp[i][j] = dp[i][j - 2] || dp[i][j - 1] || dp[i - 1][j];
+ }
+ }
+ }
+ }
+ return dp[s.length()][p.length()];
+ }
+}
diff --git a/src/Q110BalancedBinaryTree.java b/src/Q110BalancedBinaryTree.java
new file mode 100644
index 0000000..6e2addf
--- /dev/null
+++ b/src/Q110BalancedBinaryTree.java
@@ -0,0 +1,68 @@
+import util.TreeNode;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/13
+ * @time 17:07
+ */
+public class Q110BalancedBinaryTree {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+ // TODO
+ }
+
+ /**
+ * 自底向上的方法,计算深度,然后返回。
+ * 时间复杂度O(nlogn)
+ */
+ public boolean isBalanced(TreeNode root) {
+ if (root == null) {
+ return true;
+ }
+ int left = depth(root.left);
+ int right = depth(root.right);
+ // 针对每一个深度都得符合要求
+ if (Math.abs(left - right) <= 1) {
+ return isBalanced(root.left) && isBalanced(root.right);
+ }
+ return false;
+ }
+
+ public int depth(TreeNode root) {
+ if (root == null) {
+ return 0;
+ }
+ return Math.max(depth(root.left), depth(root.right)) + 1;
+ }
+
+ /**
+ * 自顶向下的方法
+ * 时间复杂度O(n)
+ */
+ public boolean isBalancedII(TreeNode root) {
+ return height(root) != -1;
+ }
+
+ public int height(TreeNode node) {
+ if (node == null) {
+ return 0;
+ }
+ // 递归调用,计算深度
+ int lH = height(node.left);
+ if (lH == -1) {
+ return -1;
+ }
+ // 右边递归调用,计算深度
+ int rH = height(node.right);
+ if (rH == -1) {
+ return -1;
+ }
+ // 判断当前行是否满足要求,不满足要求直接返回-1
+ if (lH - rH < -1 || lH - rH > 1) {
+ return -1;
+ }
+ return Math.max(lH, rH) + 1;
+ }
+}
diff --git a/src/Q112PathSum.java b/src/Q112PathSum.java
index 86194d0..59e6d0c 100644
--- a/src/Q112PathSum.java
+++ b/src/Q112PathSum.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.Stack;
/**
@@ -38,12 +40,12 @@ public static boolean hasPathSumRec(TreeNode root, int sum) {
/**
* 采用循环的方法,可以避免堆栈的溢出,但是代码量很大,而且需要一个栈存储当前节点的和
+ * 其实就是前序遍历,只不过存储的是值而已,通过一个判断来完成题目要求。
*/
public static boolean hasPathSumIte(TreeNode root, int sum) {
if (root == null) {
return false;
}
-
Stack stack = new Stack<>();
Stack SumForNode = new Stack<>();
int curSum = 0;
@@ -68,17 +70,4 @@ public static boolean hasPathSumIte(TreeNode root, int sum) {
}
return false;
}
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q113PathSumII.java b/src/Q113PathSumII.java
index 18e70fe..ce6789b 100644
--- a/src/Q113PathSumII.java
+++ b/src/Q113PathSumII.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
@@ -96,20 +98,6 @@ public static List> pathSumIte(TreeNode root, int sum) {
curSum -= cur.val;
cur = null;
}
-
return res;
}
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q114FlattenBinaryTreetoLinkedList.java b/src/Q114FlattenBinaryTreetoLinkedList.java
index e973153..d34051e 100644
--- a/src/Q114FlattenBinaryTreetoLinkedList.java
+++ b/src/Q114FlattenBinaryTreetoLinkedList.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.Stack;
/**
@@ -8,6 +10,11 @@
* @time 9:40
*/
public class Q114FlattenBinaryTreetoLinkedList {
+ /**
+ * 和我的思路一样,但是非常简单的写法
+ */
+ private TreeNode prev = null;
+
// TODO 增加测试用例;
public static void main(String[] args) {
@@ -24,6 +31,7 @@ public void flatten(TreeNode root) {
if (root == null) {
return;
}
+ // 这样递归调用保证是从后面往前面进行后面的操作的
flatten(root.right);
flatten(root.left);
// 如果左面空,那么不用处理,直接返回
@@ -44,10 +52,6 @@ public void flatten(TreeNode root) {
}
}
- /**
- * 和我的思路一样,但是非常简单的写法
- */
- private TreeNode prev = null;
public void flattenEasy(TreeNode root) {
if (root == null)
return;
@@ -59,7 +63,7 @@ public void flattenEasy(TreeNode root) {
}
/**
- * 迭代方法
+ * 迭代方法,先存右节点,再存左节点。
*/
public void flattenIte(TreeNode root) {
if (root == null) {
@@ -79,20 +83,6 @@ public void flattenIte(TreeNode root) {
cur.right = stack.peek();
}
cur.left = null;
-
- }
- }
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
}
}
}
diff --git a/src/Q124BinaryTreeMaximumPathSum.java b/src/Q124BinaryTreeMaximumPathSum.java
new file mode 100644
index 0000000..e67e48b
--- /dev/null
+++ b/src/Q124BinaryTreeMaximumPathSum.java
@@ -0,0 +1,48 @@
+import util.TreeNode;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/1
+ * @time 12:09
+ */
+public class Q124BinaryTreeMaximumPathSum {
+ /**
+ * 还是利用了递归的思想,以当前节点为中心,找到左右两边最大的子树,然后加起来
+ */
+ public static int max = Integer.MIN_VALUE;
+
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+ TreeNode t1 = new TreeNode(1);
+ TreeNode t2 = new TreeNode(2);
+ TreeNode t3 = new TreeNode(3);
+ t1.left = t2;
+ t1.right = t3;
+ System.out.println(maxPathSum(t1));
+ }
+
+ /**
+ * 返回这个最大值
+ * */
+ public static int maxPathSum(TreeNode root) {
+ helper(root);
+ return max;
+ }
+
+ /**
+ * 返回以当前节点为中心的最大的左节点或者右节点
+ */
+ private static int helper(TreeNode node) {
+ if (node == null) {
+ return 0;
+ }
+ int left = Math.max(0, helper(node.left));
+ int right = Math.max(0, helper(node.right));
+ // 最大值的判断
+ max = Math.max(max, left + right + node.val);
+ // 这是要返回的内容,最大的左或右,别忘了加上val
+ return Math.max(left, right) + node.val;
+ }
+}
diff --git a/src/Q138CopyListwithRandomPointer.java b/src/Q138CopyListwithRandomPointer.java
new file mode 100644
index 0000000..e9a8423
--- /dev/null
+++ b/src/Q138CopyListwithRandomPointer.java
@@ -0,0 +1,51 @@
+import util.RandomNode;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/17
+ * @time 21:37
+ */
+public class Q138CopyListwithRandomPointer {
+ /**
+ * 测试函数
+ * */
+ public static void main(String[] args) {
+ // TODO
+ }
+
+ /**
+ *
+ * */
+ public RandomNode copyRandomList(RandomNode head) {
+ if(head == null) {
+ return null;
+ }
+ RandomNode cur = head;
+ // 创建新的链表
+ while(cur != null) {
+ RandomNode newNode = new RandomNode();
+ newNode.val = cur.val;
+ newNode.next = cur.next;
+ cur.next = newNode;
+ cur = cur.next.next;
+ }
+
+ cur = head;
+ // 复制random节点
+ while(cur != null) {
+ cur.next.random = cur.random == null ? null : cur.random.next;
+ cur = cur.next.next;
+ }
+ cur = head;
+ RandomNode dummyHead = cur.next;
+ // 按照奇偶拆分成两个链表
+ while(cur != null) {
+ RandomNode newNode = cur.next;
+ cur.next = newNode.next;
+ newNode.next = cur.next == null ? null : newNode.next.next;
+ cur = cur.next;
+ }
+ return dummyHead;
+
+ }
+}
diff --git a/src/Q144BinaryTreePreorderTraversal.java b/src/Q144BinaryTreePreorderTraversal.java
new file mode 100644
index 0000000..a6080e6
--- /dev/null
+++ b/src/Q144BinaryTreePreorderTraversal.java
@@ -0,0 +1,17 @@
+/**
+ * @author ahscuml
+ * @date 2019/4/8
+ * @time 18:38
+ */
+public class Q144BinaryTreePreorderTraversal {
+ /**
+ *测试函数
+ * */
+ public static void main(String[] args) {
+ // TODO
+ }
+
+ /**
+ * 树的前序遍历,没那么复杂
+ * */
+}
diff --git a/src/Q146LRUCache.java b/src/Q146LRUCache.java
new file mode 100644
index 0000000..d7feb6f
--- /dev/null
+++ b/src/Q146LRUCache.java
@@ -0,0 +1,107 @@
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/8
+ * @time 23:58
+ */
+class LRUCache {
+ // 定义LRUCache的一些常量参数
+ final Node head = new Node(0, 0);
+ final Node tail = new Node(0, 0);
+ final HashMap map;
+ final int capacity;
+
+ // 对于LRU初始化
+ public LRUCache(int capacity) {
+ this.capacity = capacity;
+ map = new HashMap(capacity);
+ head.next = tail;
+ tail.pre = head;
+ }
+
+ // 插入一个元素到队列的头结点
+ private void insertToHead(Node node) {
+ node.next = head.next;
+ node.next.pre = node;
+ head.next = node;
+ node.pre = head;
+ }
+
+ // 从队列里删除一个节点
+ private void remove(Node node) {
+ node.pre.next = node.next;
+ node.next.pre = node.pre;
+ }
+
+ public int get(int key) {
+ if (map.containsKey(key)) {
+ Node node = map.get(key);
+ remove(node);
+ insertToHead(node);
+ return node.val;
+ } else {
+ return -1;
+ }
+ }
+
+ public void put(int key, int value) {
+ if (map.containsKey(key)) {
+ Node node = map.get(key);
+ remove(node);
+ node.val = value;
+ insertToHead(node);
+ } else {
+ if (map.size() == capacity) {
+ map.remove(tail.pre.key);
+ // 只有到达容量的时候才移动
+ remove(tail.pre);
+ }
+ Node node = new Node(key, value);
+ map.put(key, node);
+ insertToHead(node);
+ }
+ }
+
+ // 创建一个node对象,方便进行插入删除
+ // 这一一个双端队列
+ class Node {
+ Node pre, next;
+ int key, val;
+
+ Node(int key, int val) {
+ this.key = key;
+ this.val = val;
+ }
+ }
+}
+
+
+
+
+/**
+ * 采用LinkedHashMap的方式,非常简单。
+ * */
+class LRUCacheII {
+ private final int CAPACITY;
+ private LinkedHashMap map;
+
+ public LRUCacheII(int capacity) {
+ CAPACITY = capacity;
+ map = new LinkedHashMap(capacity, 0.75f, true) {
+ protected boolean removeEldestEntry(Map.Entry eldest) {
+ return size() > CAPACITY;
+ }
+ };
+ }
+
+ public int get(int key) {
+ return map.getOrDefault(key, -1);
+ }
+
+ public void put(int key, int value) {
+ map.put(key, value);
+ }
+}
\ No newline at end of file
diff --git a/src/Q148SortList.java b/src/Q148SortList.java
index 9607ed4..5a2c4aa 100644
--- a/src/Q148SortList.java
+++ b/src/Q148SortList.java
@@ -79,19 +79,19 @@ public static ListNode sortList(ListNode head) {
* 递归调用,两个节点,一个快,一个慢,快的到达末尾,慢的就到达中间
*/
public static ListNode sortListRec(ListNode head) {
- if (head == null || head.next == null)
+ if(head == null || head.next == null) {
return head;
- ListNode f = head.next.next;
- ListNode p = head;
- while (f != null && f.next != null) {
- p = p.next;
- f = f.next.next;
}
- // 递归调用 p在链表的中部
- ListNode h2 = sortListRec(p.next);
- // 将一个链表从中间分为两部分 一个是head,一个是h2
- p.next = null;
- return merge(sortListRec(head), h2);
+ ListNode slow = head,fast = head,pre = null;
+ while(fast != null && fast.next != null) {
+ pre = slow;
+ slow = slow.next;
+ fast = fast.next.next;
+ }
+ pre.next = null;
+ ListNode l1 = sortList(head);
+ ListNode l2 = sortList(slow);
+ return merge(l1, l2);
}
/**
diff --git a/src/Q160IntersectionofTwoLinkedLists.java b/src/Q160IntersectionofTwoLinkedLists.java
index de76548..2579847 100644
--- a/src/Q160IntersectionofTwoLinkedLists.java
+++ b/src/Q160IntersectionofTwoLinkedLists.java
@@ -14,6 +14,7 @@ public static void main(String[] args) {
listNode2.next = listNode3;
listNode3.next = listNode4;
System.out.println(getIntersectionNode(listNode1, listNode2).val);
+ System.out.println(getIntersectionNodeII(listNode1, listNode2).val);
}
/**
@@ -35,10 +36,43 @@ public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
a = a == null ? headB : a.next;
b = b == null ? headA : b.next;
}
-
return a;
}
+ /**
+ * 另外一种循环的方法就是首先求出两个链表的长度,然后调整到一样长的地方在走,直到找到相同的那个节点
+ */
+ public static ListNode getIntersectionNodeII(ListNode headA, ListNode headB) {
+ if (headA == null || headB == null) {
+ return null;
+ }
+ int alen = len(headA);
+ int blen = len(headB);
+ while (alen > blen) {
+ headA = headA.next;
+ alen--;
+ }
+ while (blen > alen) {
+ headB = headB.next;
+ blen--;
+ }
+
+ while (headA != headB) {
+ headA = headA.next;
+ headB = headB.next;
+ }
+ return headA;
+ }
+
+ public static int len(ListNode node) {
+ int count = 0;
+ while (node != null) {
+ count++;
+ node = node.next;
+ }
+ return count;
+ }
+
static class ListNode {
int val;
ListNode next;
diff --git a/src/Q173BinarySearchTreeIterator.java b/src/Q173BinarySearchTreeIterator.java
new file mode 100644
index 0000000..d17d4b2
--- /dev/null
+++ b/src/Q173BinarySearchTreeIterator.java
@@ -0,0 +1,95 @@
+import util.TreeNode;
+
+import java.util.ArrayDeque;
+import java.util.LinkedList;
+import java.util.Queue;
+
+/**
+ * @author ahscuml
+ * @date 2019/5/18
+ * @time 0:04
+ */
+public class Q173BinarySearchTreeIterator {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+
+ }
+
+ /**
+ * 把按照顺序遍历的过程通过三个函数展现出来,里面有很多细节的处理
+ */
+ class BSTIterator {
+ private ArrayDeque stack = new ArrayDeque<>();
+
+ public BSTIterator(TreeNode root) {
+ // 先到达最小的子节点
+ while (root != null) {
+ stack.push(root);
+ root = root.left;
+ }
+ }
+
+ /**
+ * @return the next smallest number
+ */
+ public int next() {
+ TreeNode n = stack.peek();
+ stack.pop();
+ int res = n.val;
+ if (n.right != null) {
+ n = n.right;
+ while (n != null) {
+ stack.push(n);
+ n = n.left;
+ }
+ }
+ return res;
+ }
+
+ /**
+ * @return whether we have a next smallest number
+ */
+ public boolean hasNext() {
+ return !stack.isEmpty();
+ }
+ }
+
+
+ /**
+ * 题目很简单,这个解法是相对笨一点的解法
+ */
+ class BSTIteratorII {
+ Queue queue = new LinkedList();
+
+ public void BSTIteratorII(TreeNode root) {
+ helper(root);
+ }
+
+ void helper(TreeNode root) {
+ if (root == null) {
+ return;
+ }
+ helper(root.left);
+ queue.offer(root.val);
+ helper(root.right);
+ }
+
+ /**
+ * @return the next smallest number
+ */
+ public int next() {
+ if (hasNext())
+ return queue.poll();
+ return -1;
+ }
+
+ /**
+ * @return whether we have a next smallest number
+ */
+ public boolean hasNext() {
+ return !queue.isEmpty();
+ }
+ }
+}
diff --git a/src/Q199BinaryTreeRightSideView.java b/src/Q199BinaryTreeRightSideView.java
new file mode 100644
index 0000000..b16e0c4
--- /dev/null
+++ b/src/Q199BinaryTreeRightSideView.java
@@ -0,0 +1,71 @@
+import util.TreeNode;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/1
+ * @time 17:00
+ */
+public class Q199BinaryTreeRightSideView {
+ /**
+ * 测试函数
+ * */
+ public static void main(String[] args) {
+ //TODO
+ }
+
+ /**
+ * 循环的方式,相当于层序遍历
+ * */
+ public List rightSideView(TreeNode root) {
+ // 从右往左看就是将层序遍历的最后一个元素放入这个list中
+ Queue queue = new LinkedList();
+ List list = new ArrayList();
+ if(root == null) {
+ return list;
+ }
+ queue.offer(root);
+ while(queue.size() != 0) {
+ int n = queue.size();
+ for(int i = 0; i < n; i++) {
+ TreeNode cur = queue.poll();
+ if(i == 0) {
+ list.add(cur.val);
+ }
+ if(cur.right != null) {
+ queue.offer(cur.right);
+ }
+ if(cur.left != null) {
+ queue.offer(cur.left);
+ }
+ }
+ }
+ return list;
+ }
+
+ /**
+ * 递归的方法
+ * */
+ public List rightSideViewII(TreeNode root) {
+ List result = new ArrayList();
+ rightView(root, result, 0);
+ return result;
+ }
+
+ public void rightView(TreeNode curr, List result, int currDepth){
+ if(curr == null){
+ return;
+ }
+ if(currDepth == result.size()){
+ result.add(curr.val);
+ }
+
+ rightView(curr.right, result, currDepth + 1);
+ rightView(curr.left, result, currDepth + 1);
+
+ }
+}
diff --git a/src/Q206ReverseLinkedList.java b/src/Q206ReverseLinkedList.java
index fa0c12f..4d3240d 100644
--- a/src/Q206ReverseLinkedList.java
+++ b/src/Q206ReverseLinkedList.java
@@ -52,23 +52,23 @@ public static ListNode ReverseList(ListNode head) {
return null;
}
HashMap map = new HashMap();
- ListNode pointer = new ListNode(0);
- pointer.next = head;
+ ListNode dummyHead = new ListNode(0);
+ dummyHead.next = head;
int n = 0;
- while(pointer.next != null) {
- pointer = pointer.next;
- map.put(n,pointer);
+ while(dummyHead.next != null) {
+ dummyHead = dummyHead.next;
+ map.put(n,dummyHead);
n++;
}
n--;
head = map.get(n);
- pointer = head;
+ dummyHead = head;
while(n > 0) {
n--;
- pointer.next = map.get(n);
- pointer = pointer.next;
+ dummyHead.next = map.get(n);
+ dummyHead = dummyHead.next;
}
- pointer.next = null;
+ dummyHead.next = null;
return head;
}
diff --git a/src/Q215KthLargestElementinanArray.java b/src/Q215KthLargestElementinanArray.java
index 07f55c0..c33ac42 100644
--- a/src/Q215KthLargestElementinanArray.java
+++ b/src/Q215KthLargestElementinanArray.java
@@ -1,6 +1,8 @@
import java.util.Arrays;
+import java.util.PriorityQueue;
/**
+ * 非常重点的题,主要考察Quick Select方法(https://www.jianshu.com/p/52f90fe2b141)
* @author ahscuml
* @date 2018/10/8
* @time 19:56
@@ -20,6 +22,7 @@ public static void main(String[] args) {
System.out.println(findKthLargestIII(nums5, 1));
System.out.println(findKthLargestIV(nums3, 4));
System.out.println(findKthLargestV(nums3, 4));
+ System.out.println(findKthLargestVI(nums3, 4));
}
/**
@@ -122,32 +125,32 @@ public static int quickSelect(int[] nums, int k, int left, int right) {
/**
* 同样的快速选择算法 但是在paartition操作中使用了双指针技术,所以会更快一点
- * */
+ */
public static int findKthLargestV(int[] nums, int k) {
- return quickSelectII(nums, nums.length-k, 0, nums.length-1);
+ return quickSelectII(nums, nums.length - k, 0, nums.length - 1);
}
- private static int quickSelectII(int[] nums, int k, int left, int right){
+ private static int quickSelectII(int[] nums, int k, int left, int right) {
// 递归的终止条件,同样也是
- if(left>=right){
+ if (left >= right) {
return nums[left];
}
- // 随机化
- int index = (left+right)/2;
+ // 随机化, 取中点的值,其实也不是最好的,应该是三点法
+ int index = (left + right) / 2;
int pivot = nums[index];
int low = left, high = right;
// partition 操作
- while(low<=high){
+ while (low <= high) {
// 如果左边比pivot小,左边不断增加,直到大于pivot
- while(low<=high && nums[low]pivot){
+ while (low <= high && nums[high] > pivot) {
high--;
}
// 交换high与low
- if(low<=high){
+ if (low <= high) {
int tmp = nums[low];
nums[low] = nums[high];
nums[high] = tmp;
@@ -156,17 +159,28 @@ private static int quickSelectII(int[] nums, int k, int left, int right){
}
}
// 针对K进行递归,由于K是对nums的下标来说的,所以K不用变
- if(k>=low && k<=right){
+ if (k >= low && k <= right) {
return quickSelectII(nums, k, low, right);
- }
- else if(k>=left && k<=high){
+ } else if (k >= left && k <= high) {
return quickSelectII(nums, k, left, high);
- }
- else{
+ } else {
return nums[k];
}
}
+ /**
+ * 这个问题非常适合利用堆来完成,使用一个小顶堆,在Java中就是priority queue
+ * */
+ public static int findKthLargestVI(int[] nums, int k) {
+ PriorityQueue priorityQueue = new PriorityQueue<>(k);
+ for(int el : nums) {
+ priorityQueue.add(el);
+ if (priorityQueue.size() > k) {
+ priorityQueue.poll();
+ }
+ }
+ return priorityQueue.peek();
+ }
private static void swap(int[] nums, int i, int j) {
int temp = nums[i];
diff --git a/src/Q21MergeTwoSortedLists.java b/src/Q21MergeTwoSortedLists.java
index 1a7645a..2a7e25c 100644
--- a/src/Q21MergeTwoSortedLists.java
+++ b/src/Q21MergeTwoSortedLists.java
@@ -1,5 +1,6 @@
/**
* 21. Merge Two Sorted Lists
+ *
* @author ahscuml
* @date 2018/9/29
* @time 15:16
@@ -7,7 +8,7 @@
public class Q21MergeTwoSortedLists {
/**
* 测试函数
- * */
+ */
public static void main(String[] args) {
ListNode listNode1 = new ListNode(1);
ListNode listNode2 = new ListNode(2);
@@ -26,24 +27,52 @@ public static void main(String[] args) {
result = result.next;
}
}
+
/**
* 递归,相当优秀
- * */
- public static ListNode mergeTwoLists(ListNode l1, ListNode l2){
- if(l1 == null) {
+ */
+ public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
+ if (l1 == null) {
return l2;
}
- if(l2 == null) {
+ if (l2 == null) {
return l1;
}
- if(l1.val < l2.val){
+ if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
- } else{
+ } else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
+
+ /**
+ * 循环的方法,同样也很优秀,只不过长了一点
+ * 创建一个dummyHead节点,这是惯用的方法
+ */
+ public ListNode mergeTwoListsII(ListNode l1, ListNode l2) {
+ ListNode dummyHead = new ListNode(-1);
+ ListNode cur = dummyHead;
+ while (l1 != null && l2 != null) {
+ if (l1.val < l2.val) {
+ cur.next = l1;
+ l1 = l1.next;
+ } else {
+ cur.next = l2;
+ l2 = l2.next;
+ }
+ cur = cur.next;
+ }
+ if (l1 != null) {
+ cur.next = l1;
+ }
+ if (l2 != null) {
+ cur.next = l2;
+ }
+ return dummyHead.next;
+ }
+
/**
* 链表的定义
*/
diff --git a/src/Q226InvertBinaryTree.java b/src/Q226InvertBinaryTree.java
index a3d4c6e..15c7de1 100644
--- a/src/Q226InvertBinaryTree.java
+++ b/src/Q226InvertBinaryTree.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.LinkedList;
import java.util.Queue;
@@ -91,14 +93,4 @@ private static TreeNode invertTreeIte(TreeNode root) {
}
return root;
}
-
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q230KthSmallestElementinaBST.java b/src/Q230KthSmallestElementinaBST.java
new file mode 100644
index 0000000..5d0945a
--- /dev/null
+++ b/src/Q230KthSmallestElementinaBST.java
@@ -0,0 +1,79 @@
+import util.TreeNode;
+
+import java.util.ArrayDeque;
+
+/**
+ * @author ahscuml
+ * @date 2019/5/17
+ * @time 23:14
+ */
+public class Q230KthSmallestElementinaBST {
+ /**
+ * 测试函数
+ * */
+ public static void main(String[] args) {
+
+ }
+
+ /**
+ * BST的特点就是中序遍历就是顺序的数组
+ * 按照中序遍历的结构来完成
+ * */
+ int count = 0;
+ int res = -1;
+ public int kthSmallest(TreeNode root, int k) {
+ helper(root, k);
+ return res;
+ }
+
+ void helper(TreeNode root, int k) {
+ if(root != null) {
+ kthSmallest(root.left, k);
+ if(++count == k) {
+ res = root.val;
+ }
+ kthSmallest(root.right, k);
+ }
+ }
+
+ /**
+ * 利用循环的方法
+ * */
+ public int kthSmallestIte(TreeNode root, int k) {
+ TreeNode cur = root;
+ ArrayDeque stack = new ArrayDeque();
+ while(!stack.isEmpty() || cur != null) {
+ if(cur != null) {
+ stack.push(cur);
+ cur = cur.left;
+ } else {
+ cur = stack.pop();
+ if(--k == 0) {
+ return cur.val;
+ }
+ cur = cur.right;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * 另外一种,利用二分查找,分别统计这个节点的左右节点各有多少个节点,直到找到K个
+ * */
+ public int kthSmallestIII(TreeNode root, int k) {
+ int cnt = count(root.left);
+ if(k <= cnt) {
+ return kthSmallestIII(root.left, k);
+ } else if(k > cnt + 1) {
+ return kthSmallestIII(root.right, k - cnt - 1);
+ }
+ return root.val;
+ }
+
+ int count(TreeNode root) {
+ if(root == null) {
+ return 0;
+ }
+ return 1 + count(root.left) + count(root.right);
+ }
+}
diff --git a/src/Q235LowestCommonAncestorofaBinarySearchTree.java b/src/Q235LowestCommonAncestorofaBinarySearchTree.java
new file mode 100644
index 0000000..df4a6fa
--- /dev/null
+++ b/src/Q235LowestCommonAncestorofaBinarySearchTree.java
@@ -0,0 +1,48 @@
+import util.TreeNode;
+
+/**
+ * 二叉搜索树的公共祖先
+ *
+ * @author ahscuml
+ * @date 2019/4/8
+ * @time 20:19
+ */
+public class Q235LowestCommonAncestorofaBinarySearchTree {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+ // TODO
+ }
+
+ /**
+ * 利用BST的特点
+ * 利用树递归的性质
+ */
+ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
+ if (root == null) {
+ return null;
+ }
+ if (p.val < root.val && q.val < root.val) {
+ return lowestCommonAncestor(root.left, p, q);
+ } else if (p.val > root.val && q.val > root.val) {
+ return lowestCommonAncestor(root.right, p, q);
+ } else {
+ return root;
+ }
+ }
+
+ /**
+ * 利用循环的方法
+ */
+ public TreeNode lowestCommonAncestorIte(TreeNode root, TreeNode p, TreeNode q) {
+ while (true) {
+ if (root == null || (root.val - p.val) * (root.val - q.val) <= 0) return root;
+ if (p.val < root.val) {
+ root = root.left;
+ } else {
+ root = root.right;
+ }
+ }
+ }
+}
diff --git a/src/Q236LowestCommonAncestorofaBinaryTree.java b/src/Q236LowestCommonAncestorofaBinaryTree.java
new file mode 100644
index 0000000..2268a94
--- /dev/null
+++ b/src/Q236LowestCommonAncestorofaBinaryTree.java
@@ -0,0 +1,67 @@
+import util.TreeNode;
+
+import java.util.*;
+
+/**
+ * 二叉树最近公共祖先
+ *
+ * @author ahscuml
+ * @date 2019/4/8
+ * @time 19:44
+ */
+public class Q236LowestCommonAncestorofaBinaryTree {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+ // TODO
+ }
+
+ /**
+ * 循环的方法,记录祖先
+ */
+ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
+ Map parent = new HashMap<>();
+ Deque stack = new ArrayDeque<>();
+ parent.put(root, null);
+ stack.push(root);
+
+ while (!parent.containsKey(p) || !parent.containsKey(q)) {
+ TreeNode node = stack.pop();
+ if (node.left != null) {
+ parent.put(node.left, node);
+ stack.push(node.left);
+ }
+ if (node.right != null) {
+ parent.put(node.right, node);
+ stack.push(node.right);
+ }
+ }
+ Set ancestors = new HashSet<>();
+ while (p != null) {
+ ancestors.add(p);
+ p = parent.get(p);
+ }
+ while (!ancestors.contains(q))
+ q = parent.get(q);
+ return q;
+ }
+
+ /**
+ * 递归的方法
+ */
+ public TreeNode lowestCommonAncestorRec(TreeNode root, TreeNode p, TreeNode q) {
+ if (root == null || root == p || root == q) {
+ return root;
+ }
+ TreeNode left = lowestCommonAncestorRec(root.left, p, q);
+ TreeNode right = lowestCommonAncestorRec(root.right, p, q);
+ if (left == null) {
+ return right;
+ }
+ if (right == null) {
+ return left;
+ }
+ return root;
+ }
+}
diff --git a/src/Q23MergekSortedLists.java b/src/Q23MergekSortedLists.java
new file mode 100644
index 0000000..5911b52
--- /dev/null
+++ b/src/Q23MergekSortedLists.java
@@ -0,0 +1,111 @@
+import util.ListNode;
+
+import java.util.*;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/1
+ * @time 18:19
+ */
+public class Q23MergekSortedLists {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+ //TODO
+ }
+
+ /**
+ * 看到了merge最先想到的就应该是mergesort,针对链表进行mergesort
+ */
+ public ListNode mergeKLists(ListNode[] lists) {
+ if (lists.length == 0) {
+ return null;
+ }
+ return sort(lists, 0, lists.length - 1);
+ }
+
+ public ListNode sort(ListNode[] lists, int start, int end) {
+ if (start == end) {
+ return lists[start];
+ }
+ int mid = start + (end - start) / 2;
+ ListNode l1 = sort(lists, start, mid);
+ ListNode l2 = sort(lists, mid + 1, end);
+ return merge(l1, l2);
+ }
+
+ public ListNode merge(ListNode a, ListNode b) {
+ if (a == null) {
+ return b;
+ }
+ if (b == null) {
+ return a;
+ }
+ if (a.val < b.val) {
+ a.next = merge(a.next, b);
+ return a;
+ } else {
+ b.next = merge(b.next, a);
+ return b;
+ }
+ }
+
+ /**
+ * 对于很对元素排序的题还可以应用优先队列,应用优先队列的特性,让优先队列去排序
+ * */
+ public ListNode mergeKLists(List lists) {
+ if (lists == null || lists.size() == 0) {
+ return null;
+ }
+ // 优先队列的构造函数,确定大小和初始化构造器,通过构造器来完成排序的工作
+ PriorityQueue queue = new PriorityQueue(lists.size(), new Comparator() {
+ @Override
+ public int compare(ListNode o1, ListNode o2) {
+ return o1.val - o2.val;
+ }
+ });
+
+ ListNode dummy = new ListNode(0);
+ ListNode tail = dummy;
+ for (ListNode node : lists) {
+ if (node != null) {
+ queue.add(node);
+ }
+ while (!queue.isEmpty()) {
+ tail.next = queue.poll();
+ tail = tail.next;
+ // lists里面的ListNode只是一个节点,如果当前节点后面还有节点,那么在放入队列的时候将这个节点之后的节点添加进queue
+ if (tail.next != null) {
+ queue.add(tail.next);
+ }
+ }
+ }
+ return dummy.next;
+ }
+
+ /**
+ * 还有一种方法,可以把所有的ListNode的值读出来,读到一个list里,然后进行排序,最后从头到尾进行建立ListNode的操作
+ * 这种方法竟然打败了
+ * */
+ public ListNode mergeKListsIII(ListNode[] lists) {
+ ArrayList list = new ArrayList();
+ for(int i = 0; i < lists.length; i++) {
+ ListNode cur = lists[i];
+ while(cur != null) {
+ list.add(cur.val);
+ cur = cur.next;
+ }
+ }
+ Collections.sort(list);
+ ListNode dummyHead = new ListNode(0);
+ ListNode cur = dummyHead;
+ for(int i = 0; i < list.size(); i++) {
+
+ cur.next = new ListNode(list.get(i));
+ cur = cur.next;
+ //cur = null;
+ }
+ return dummyHead.next;
+ }
+}
diff --git a/src/Q257BinaryTreePaths.java b/src/Q257BinaryTreePaths.java
new file mode 100644
index 0000000..afaf10e
--- /dev/null
+++ b/src/Q257BinaryTreePaths.java
@@ -0,0 +1,47 @@
+import util.TreeNode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 二叉树从头到尾的路径
+ * @author ahscuml
+ * @date 2019/4/29
+ * @time 13:00
+ */
+public class Q257BinaryTreePaths {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+
+ }
+
+ /**
+ * 将StringBuilder作为传递资源完成内容。
+ * setLength函数设置长度
+ * 最后一个不用加上->,所以需要判断当前节点的左右子节点是否是null
+ * */
+ public List binaryTreePaths(TreeNode root) {
+ List res = new ArrayList<>();
+ StringBuilder sb = new StringBuilder();
+ helper(res, root, sb);
+ return res;
+ }
+
+ private void helper(List res, TreeNode root, StringBuilder sb) {
+ if (root == null) {
+ return;
+ }
+ int len = sb.length();
+ sb.append(root.val);
+ if (root.left == null && root.right == null) {
+ res.add(sb.toString());
+ } else {
+ sb.append("->");
+ helper(res, root.left, sb);
+ helper(res, root.right, sb);
+ }
+ sb.setLength(len);
+ }
+}
diff --git a/src/Q279PerfectSquares.java b/src/Q279PerfectSquares.java
index aa4425d..20f0a41 100644
--- a/src/Q279PerfectSquares.java
+++ b/src/Q279PerfectSquares.java
@@ -18,14 +18,14 @@ public static void main(String[] args) {
* 动态规划方法
* */
public static int numSquares(int n) {
- int count[] = new int[n + 1];
- Arrays.fill(count, Integer.MAX_VALUE);
- count[0] = 0;
+ int dp[] = new int[n + 1];
+ Arrays.fill(dp, Integer.MAX_VALUE);
+ dp[0] = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j * j <=i; j++) {
- count[i] = Math.min(count[i],count[i - j * j] + 1);
+ dp[i] = Math.min(dp[i],dp[i - j * j] + 1);
}
}
- return count[n];
+ return dp[n];
}
}
diff --git a/src/Q297SerializeandDeserializeBinaryTree.java b/src/Q297SerializeandDeserializeBinaryTree.java
new file mode 100644
index 0000000..5177f90
--- /dev/null
+++ b/src/Q297SerializeandDeserializeBinaryTree.java
@@ -0,0 +1,57 @@
+/**
+ * @author ahscuml
+ * @date 2019/5/13
+ * @time 23:32
+ */
+
+import util.TreeNode;
+
+public class Q297SerializeandDeserializeBinaryTree {
+ int index = -1;
+
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+
+ }
+
+ /**
+ * 序列化和反序列化,这是一个运行时间相对优秀的答案
+ * 主要利用前序遍历,将一棵树组装成一个String
+ * 反序列化同理,同样要注意反序列化的顺序
+ * */
+ private void serializeNode(TreeNode node, StringBuilder sb) {
+ if (node == null) {
+ sb.append('#').append(",");
+ return;
+ }
+ sb.append(node.val).append(',');
+ serializeNode(node.left, sb);
+ serializeNode(node.right, sb);
+ }
+
+ // Encodes a tree to a single string.
+ public String serialize(TreeNode root) {
+ StringBuilder sb = new StringBuilder();
+ serializeNode(root, sb);
+ return sb.substring(0, sb.length() - 1);
+ }
+
+ // Decodes your encoded data to tree.
+ public TreeNode deserialize(String data) {
+ String[] val = data.split(",");
+ return buildTree(val);
+ }
+
+ private TreeNode buildTree(String[] val) {
+ index++;
+ TreeNode cur = null;
+ if (!val[index].equals("#")) {
+ cur = new TreeNode(Integer.valueOf(val[index]));
+ cur.left = buildTree(val);
+ cur.right = buildTree(val);
+ }
+ return cur;
+ }
+}
diff --git a/src/Q322CoinChange.java b/src/Q322CoinChange.java
new file mode 100644
index 0000000..f404ffb
--- /dev/null
+++ b/src/Q322CoinChange.java
@@ -0,0 +1,112 @@
+/**
+ * @author ahscuml
+ * @date 2019/3/20
+ * @time 17:58
+ */
+public class Q322CoinChange {
+ public static void main(String[] args) {
+ int[] coins = {1, 2, 5};
+ int amount = 11;
+ System.out.println(coinChange(coins, amount));
+ int[] coins1 = {2};
+ int amount1 = 3;
+ System.out.println(coinChange(coins1, amount1));
+ int[] coins2 = {2, 5, 10, 1};
+ int amount2 = 27;
+ System.out.println(coinChange(coins2, amount2));
+ }
+
+ /**
+ * 自己写的方法
+ * 带最字的都是动态规划的问题,所以可以从动态规划的角度考虑
+ * 首先动态规划是划分成子问题,首先找出子问题
+ * dp[i][j] 用 coins[0...j]的硬币,完成价格J的最少个数
+ */
+ public static int coinChange(int[] coins, int target) {
+ if (coins == null || coins.length < 1 || target < 1) {
+ return 0;
+ }
+
+ int[][] dp = new int[coins.length][target + 1];
+ for (int i = 0; i < coins.length; i++) {
+ dp[i][0] = 0;
+ }
+
+ for (int i = 1; i < target + 1; i++) {
+ if (i % coins[0] == 0) {
+ dp[0][i] = i / coins[0];
+ } else {
+ dp[0][i] = Integer.MAX_VALUE;
+ }
+ }
+
+ for (int i = 1; i < coins.length; i++) {
+ for (int j = 1; j < target + 1; j++) {
+ // 还要处理j - coins[i] < 0的问题
+ if (j - coins[i] < 0) {
+ dp[i][j] = dp[i - 1][j];
+ } else {
+ // 还要处理Integer.MAX_VALUE的问题
+ dp[i][j] = dp[i][j - coins[i]] == Integer.MAX_VALUE
+ ? dp[i - 1][j] : Math.min(dp[i - 1][j], dp[i][j - coins[i]] + 1);
+ }
+ }
+ }
+ return dp[coins.length - 1][target] == Integer.MAX_VALUE ? -1 : dp[coins.length - 1][target];
+ }
+
+ /**
+ * 循环的方式
+ */
+ public int coinChange1(int[] coins, int amount) {
+ if (amount < 1) return 0;
+ return helper(coins, amount, new int[amount]);
+ }
+
+ /**
+ * 递归的方法,自上而下
+ *
+ * @param coins coins we have
+ * @param rem remainint to change
+ * @param count the number of coins
+ */
+ private int helper(int[] coins, int rem, int[] count) {
+ if (rem < 0) return -1; // not valid
+ if (rem == 0) return 0; // completed
+ // already computed, so reuse
+ if (count[rem - 1] != 0) return count[rem - 1];
+ int min = Integer.MAX_VALUE;
+ for (int coin : coins) {
+ int res = helper(coins, rem - coin, count);
+ if (res >= 0 && res < min)
+ min = res + 1;
+ }
+ count[rem - 1] = (min == Integer.MAX_VALUE) ? -1 : min;
+ return count[rem - 1];
+ }
+
+ /**
+ * 循环的方法,就是我的方法的改版,不过用了空间压缩的方法,只用一个一维数组就搞定了
+ * 当前金额sum的最小值是金额为sum - coin的最小值加1
+ */
+ public int coinChange2(int[] coins, int amount) {
+ if (amount < 1) return 0;
+ // 当前amount所需的最少的coin次数,长度是amount + 1
+ int[] dp = new int[amount + 1];
+ // 当前金额
+ int sum = 0;
+
+ while (++sum <= amount) {
+ // 最少的次数,对于一个数值,遍历完一遍coins才知道min
+ int min = -1;
+ for (int coin : coins) {
+ if (sum >= coin && dp[sum - coin] != -1) {
+ int temp = dp[sum - coin] + 1;
+ min = min < 0 ? temp : (temp < min ? temp : min);
+ }
+ }
+ dp[sum] = min;
+ }
+ return dp[amount];
+ }
+}
diff --git a/src/Q328OddEvenLinkedList.java b/src/Q328OddEvenLinkedList.java
new file mode 100644
index 0000000..f681dde
--- /dev/null
+++ b/src/Q328OddEvenLinkedList.java
@@ -0,0 +1,66 @@
+import util.ListNode;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/13
+ * @time 10:49
+ */
+public class Q328OddEvenLinkedList {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+ // TODO
+ }
+
+ /**
+ * 重点是循环条件的判断
+ * */
+ public static ListNode oddEvenListII(ListNode head) {
+ // 先找到odd和even的开头??
+ if(head == null || head.next == null) {
+ return head;
+ }
+ ListNode even = head.next, curOdd = head, curEven = head.next;
+ while(curEven != null && curEven.next != null) {
+ curOdd.next = curEven.next;
+ curOdd = curOdd.next;
+ curEven.next = curOdd.next;
+ curEven = curEven.next;
+ }
+ curOdd.next = even;
+ return head;
+ }
+
+
+ /**
+ * 这个不是这道题的答案,这个是这个题的变种,关注的是listnode中的值
+ */
+ public ListNode oddEvenList(ListNode head) {
+ if (head == null || head.next == null) {
+ return head;
+ }
+ boolean isSwaped = false;
+ ListNode dummyHead = new ListNode(-1);
+ dummyHead.next = head;
+ ListNode cur = dummyHead;
+ do {
+ isSwaped = false;
+ cur = dummyHead;
+ while (cur.next.next != null) {
+ if (cur.next.val % 2 == 0 && cur.next.next.val % 2 == 1) {
+ swapNode(cur, cur.next, cur.next.next);
+ isSwaped = true;
+ }
+ cur = cur.next;
+ }
+ } while (isSwaped);
+ return dummyHead.next;
+ }
+
+ private void swapNode(ListNode pre, ListNode left, ListNode right) {
+ left.next = right.next;
+ right.next = left;
+ pre.next = right;
+ }
+}
diff --git a/src/Q343IntegerBreak.java b/src/Q343IntegerBreak.java
new file mode 100644
index 0000000..661f8bc
--- /dev/null
+++ b/src/Q343IntegerBreak.java
@@ -0,0 +1,28 @@
+/**
+ * @author ahscuml
+ * @date 2019/4/9
+ * @time 0:27
+ */
+public class Q343IntegerBreak {
+ public static void main(String[] args) {
+ integerBreak(10);
+ }
+
+ /**
+ * 需要特殊考虑2和3
+ * */
+ public static int integerBreak(int n) {
+ // 这个一看就是动态规划的问题
+ // 行就是数字n,列就是最大的乘积
+ int[] dp = new int[n + 1];
+ dp[0] = 1;
+ dp[1] = 1;
+ for (int i = 2; i <= n; i++) {
+ for (int j = 1; j <= i / 2; j++) {
+ dp[i] = Math.max(Math.max(dp[i], dp[j] * dp[i - j]), i);
+ }
+ System.out.print(dp[i] + " ");
+ }
+ return dp[n];
+ }
+}
diff --git a/src/Q347TopKFrequentElements.java b/src/Q347TopKFrequentElements.java
index 4180f43..e9e2924 100644
--- a/src/Q347TopKFrequentElements.java
+++ b/src/Q347TopKFrequentElements.java
@@ -1,7 +1,4 @@
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.*;
/**
* @author ahscuml
@@ -19,6 +16,7 @@ public static void main(String[] args) {
}
/**
+ * 使用桶排序来做这件事情
* 利用HashMap统计频次
* 利用List的数组存储结果
*/
@@ -31,6 +29,7 @@ public static List topKFrequent(int[] nums, int k) {
}
// 遍历存有频率的HashMap,利用存有list的数组bucket 按照频率将元素存储到bucket里
+ // 如何遍历HashMap也是一个重点
List[] bucket = new List[nums.length + 1];
for (int i : map.keySet()) {
int fre = map.get(i);
@@ -49,4 +48,56 @@ public static List topKFrequent(int[] nums, int k) {
}
return res;
}
+
+ /**
+ * 使用堆来完成任务,也就是PriorityQueue
+ * */
+ public static List topKFrequentII(int[] nums, int k) {
+ // 利用HahsMap来存储频次
+ Map map = new HashMap<>();
+ for(int n: nums){
+ map.put(n, map.getOrDefault(n,0)+1);
+ }
+
+ // 优先队列的使用
+ PriorityQueue> maxHeap =
+ new PriorityQueue<>((a,b)->(b.getValue()-a.getValue()));
+ for(Map.Entry entry: map.entrySet()){
+ maxHeap.add(entry);
+ }
+
+ List res = new ArrayList<>();
+ while(res.size() entry = maxHeap.poll();
+ res.add(entry.getKey());
+ }
+ return res;
+ }
+
+ /**
+ * 使用TreeMap来完成这个任务
+ * */
+ public static List topKFrequentIII(int[] nums, int k) {
+ Map map = new HashMap<>();
+ for(int n: nums){
+ map.put(n, map.getOrDefault(n,0)+1);
+ }
+
+ TreeMap> freqMap = new TreeMap<>();
+ for(int num : map.keySet()){
+ int freq = map.get(num);
+ if(!freqMap.containsKey(freq)){
+ freqMap.put(freq, new LinkedList<>());
+ }
+ freqMap.get(freq).add(num);
+ }
+
+ // 对于TreeMap的使用
+ List res = new ArrayList<>();
+ while(res.size()> entry = freqMap.pollLastEntry();
+ res.addAll(entry.getValue());
+ }
+ return res;
+ }
}
diff --git a/src/Q416PartitionEqualSubsetSum.java b/src/Q416PartitionEqualSubsetSum.java
new file mode 100644
index 0000000..a9ccef6
--- /dev/null
+++ b/src/Q416PartitionEqualSubsetSum.java
@@ -0,0 +1,87 @@
+import java.util.Arrays;
+
+/**
+ * Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets
+ * such that the sum of elements in both subsets is equal.
+ *
+ * @author ahscuml
+ * @date 2019/3/20
+ * @time 20:02
+ */
+public class Q416PartitionEqualSubsetSum {
+ public static void main(String[] args) {
+ int[] nums = {1, 5, 11, 5};
+ System.out.println(canPartition(nums));
+ System.out.println(canPartition1(nums));
+ }
+
+ /**
+ * 0-1背包问题的变形 类似于coins问题???
+ * dp[i][j] means whether the specific sum j can be gotten from the first i numbers.
+ */
+ public static boolean canPartition(int[] nums) {
+ int sum = 0;
+ for (int num : nums) {
+ sum += num;
+ }
+ // sum的末位不能是奇数,因为奇数不可能分成两个相等的内容
+ if ((sum & 1) == 1) {
+ return false;
+ }
+ sum /= 2;
+ int n = nums.length;
+ boolean[][] dp = new boolean[n + 1][sum + 1];
+ /**
+ * ii的地方全填成false?
+ * */
+ for (int i = 0; i < dp.length; i++) {
+ Arrays.fill(dp[i], false);
+ }
+ dp[0][0] = true;
+ // 和为0的
+ for (int i = 1; i < n + 1; i++) {
+ dp[i][0] = true;
+ }
+ // 不使用元素的
+ for (int j = 1; j < sum + 1; j++) {
+ dp[0][j] = false;
+ }
+ for (int i = 1; i < n + 1; i++) {
+ for (int j = 1; j < sum + 1; j++) {
+ // 不用当前这个元素
+ dp[i][j] = dp[i - 1][j];
+ // j是sum,
+ if (j >= nums[i - 1]) {
+ dp[i][j] = (dp[i][j] || dp[i - 1][j - nums[i - 1]]);
+ }
+ }
+ }
+ return dp[n][sum];
+ }
+
+ /**
+ * 上面方法的优化,使用一维数组
+ * */
+ public static boolean canPartition1(int[] nums) {
+ int sum = 0;
+ for (int num : nums) {
+ sum += num;
+ }
+ if ((sum & 1) == 1) {
+ return false;
+ }
+ sum /= 2;
+ boolean[] dp = new boolean[sum + 1];
+ // 数组的初始化
+ Arrays.fill(dp, false);
+ dp[0] = true;
+ for (int num : nums) {
+ for (int i = sum; i > 0; i--) {
+ if (i >= num) {
+ dp[i] = dp[i] || dp[i - num];
+ }
+ }
+ }
+ return dp[sum];
+ }
+}
diff --git a/src/Q437PathSumIII.java b/src/Q437PathSumIII.java
index e2719f5..49e5b3c 100644
--- a/src/Q437PathSumIII.java
+++ b/src/Q437PathSumIII.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.HashMap;
/**
@@ -45,14 +47,4 @@ public static int helper(TreeNode root, int currSum, int target, HashMap spiralOrder(int[][] matrix) {
+ List res = new ArrayList();
+ if (matrix.length == 0) {
+ return res;
+ }
+ int rowBegin = 0, rowEnd = matrix.length - 1, colBegin = 0, colEnd = matrix[0].length - 1;
+ while (rowBegin <= rowEnd && colBegin <= colEnd) {
+ // 打印rowBegin行,从colBegin到colEnd
+ for (int i = colBegin; i <= colEnd; i++) {
+ res.add(matrix[rowBegin][i]);
+ }
+ rowBegin++;
+ // 打印colEnd列
+ // 这里值变换了rowBegin而且后面还是比较row,所以不用判断
+ for (int i = rowBegin; i <= rowEnd; i++) {
+ res.add(matrix[i][colEnd]);
+ }
+ colEnd--;
+
+ // 打印 rowEnd行
+ // 这里要比较row
+ if (rowBegin <= rowEnd) {
+ for (int i = colEnd; i >= colBegin; i--) {
+ res.add(matrix[rowEnd][i]);
+ }
+ }
+ rowEnd--;
+
+ // 打印colBegin列
+ // 这里要比较col,因为前面改过col
+ if (colBegin <= colEnd) {
+ for (int i = rowEnd; i >= rowBegin; i--) {
+ res.add(matrix[i][colBegin]);
+ }
+ }
+ colBegin++;
+ }
+ return res;
+ }
+
+ /**
+ * 第二种方法,可能更加方便记忆
+ */
+ public static List spiralOrderII(int[][] matrix) {
+ List res = new ArrayList();
+ if (matrix.length == 0 || matrix[0].length == 0) return res;
+
+ int top = 0;
+ int bottom = matrix.length - 1;
+ int left = 0;
+ int right = matrix[0].length - 1;
+
+ while (true) {
+ for (int i = left; i <= right; i++) res.add(matrix[top][i]);
+ top++;
+ if (left > right || top > bottom) break;
+
+ for (int i = top; i <= bottom; i++) res.add(matrix[i][right]);
+ right--;
+ if (left > right || top > bottom) break;
+
+ for (int i = right; i >= left; i--) res.add(matrix[bottom][i]);
+ bottom--;
+ if (left > right || top > bottom) break;
+
+ for (int i = bottom; i >= top; i--) res.add(matrix[i][left]);
+ left++;
+ if (left > right || top > bottom) break;
+ }
+
+ return res;
+ }
+}
diff --git a/src/Q572SubtreeofAnotherTree.java b/src/Q572SubtreeofAnotherTree.java
index d512e24..d82a579 100644
--- a/src/Q572SubtreeofAnotherTree.java
+++ b/src/Q572SubtreeofAnotherTree.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.LinkedList;
import java.util.Queue;
@@ -74,17 +76,4 @@ private static boolean check(TreeNode s, TreeNode t) {
}
return false;
}
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q617MergeTwoBinaryTrees.java b/src/Q617MergeTwoBinaryTrees.java
index cde7740..ed0e1bf 100644
--- a/src/Q617MergeTwoBinaryTrees.java
+++ b/src/Q617MergeTwoBinaryTrees.java
@@ -1,4 +1,8 @@
+import util.TreeNode;
+
/**
+ * TODO 循环的方法
+ *
* @author ahscuml
* @date 2018/11/26
* @time 15:09
@@ -49,7 +53,6 @@ public static TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
return newNode;
}
-
/**
* 中序遍历, 递归 打印这个树
*/
@@ -63,15 +66,18 @@ private static void inOrderRec(TreeNode root) {
}
/**
- * 树结构的定义
+ * 自己写的递归方法,时间复杂度O(n)
*/
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
+ public TreeNode mergeTreesII(TreeNode t1, TreeNode t2) {
+ if (t1 == null) {
+ return t2;
+ }
+ if (t2 == null) {
+ return t1;
}
+ t1.val = t1.val + t2.val;
+ t1.left = mergeTrees(t1.left, t2.left);
+ t1.right = mergeTrees(t1.right, t2.right);
+ return t1;
}
}
diff --git a/src/Q637AverageofLevelsinBinaryTree.java b/src/Q637AverageofLevelsinBinaryTree.java
new file mode 100644
index 0000000..a4f0dd6
--- /dev/null
+++ b/src/Q637AverageofLevelsinBinaryTree.java
@@ -0,0 +1,50 @@
+import util.TreeNode;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/29
+ * @time 12:22
+ */
+public class Q637AverageofLevelsinBinaryTree {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+
+ }
+
+ /**
+ * 层序遍历,统计这一层的值,除就可以了
+ */
+ public List averageOfLevels(TreeNode root) {
+ List list = new LinkedList();
+ if (root == null) {
+ return list;
+ }
+ Queue queue = new LinkedList<>();
+ TreeNode cur = null;
+ queue.offer(root);
+ while (!queue.isEmpty()) {
+ int count = queue.size();
+ int n = count;
+ double sum = 0;
+ while (count > 0) {
+ cur = queue.poll();
+ sum += cur.val;
+ if (cur.left != null) {
+ queue.offer(cur.left);
+ }
+ if (cur.right != null) {
+ queue.offer(cur.right);
+ }
+ count--;
+ }
+ list.add(sum / n);
+ }
+ return list;
+ }
+}
diff --git a/src/Q64MinimumPathSum.java b/src/Q64MinimumPathSum.java
index a84c9b3..70743ee 100644
--- a/src/Q64MinimumPathSum.java
+++ b/src/Q64MinimumPathSum.java
@@ -9,20 +9,21 @@ public static void main(String[] args) {
{1, 5, 1},
{4, 2, 1}};
System.out.println(minPathSum(nums));
+ System.out.println(minPathSumII(nums));
}
/**
* 依旧使用动态规划,和62,63一样的想法。
* 可以不使用额外的存储空间,直接将内容存储到matrix中,可以试试这个想法。
- * */
+ */
public static int minPathSum(int[][] matrix) {
int n = matrix[0].length;
int[] aux = new int[n];
- for(int i = 0; i < matrix.length; i++) {
- for(int j = 0; j < n; j++) {
+ for (int i = 0; i < matrix.length; i++) {
+ for (int j = 0; j < n; j++) {
if (j == 0) {
aux[j] = aux[j] + matrix[i][j];
- } else if(i == 0){
+ } else if (i == 0) {
aux[j] = aux[j - 1] + matrix[i][j];
} else {
aux[j] = matrix[i][j] + Math.min(aux[j - 1], aux[j]);
@@ -31,4 +32,28 @@ public static int minPathSum(int[][] matrix) {
}
return aux[n - 1];
}
+
+ /**
+ * 动态规划的方法,只不过采用的是二维的数组,最基本的想法
+ * 注意创建辅助数组的时候的长度以及创建完成以后首先对00赋值
+ */
+ public static int minPathSumII(int[][] grid) {
+ if (grid.length == 0 || grid[0].length == 0) {
+ return 0;
+ }
+ int[][] dp = new int[grid.length][grid[0].length];
+ dp[0][0] = grid[0][0];
+ for (int i = 1; i < grid.length; i++) {
+ dp[i][0] = grid[i][0] + dp[i - 1][0];
+ }
+ for (int i = 1; i < grid[0].length; i++) {
+ dp[0][i] = grid[0][i] + dp[0][i - 1];
+ }
+ for (int i = 1; i < grid.length; i++) {
+ for (int j = 1; j < grid[0].length; j++) {
+ dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
+ }
+ }
+ return dp[grid.length - 1][grid[0].length - 1];
+ }
}
diff --git a/src/Q718MaximumLengthofRepeatedSubarray.java b/src/Q718MaximumLengthofRepeatedSubarray.java
new file mode 100644
index 0000000..472ebfe
--- /dev/null
+++ b/src/Q718MaximumLengthofRepeatedSubarray.java
@@ -0,0 +1,34 @@
+/**
+ * @author ahscuml
+ * @date 2019/4/9
+ * @time 0:54
+ */
+public class Q718MaximumLengthofRepeatedSubarray {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+ int[] A = {1, 2, 3, 2, 1};
+ int[] B = {3, 2, 1, 4, 7};
+ System.out.println(findLength(A, B));
+ }
+
+ /**
+ * 动态规划
+ * 找到规律,也就是递推关系式很好处理
+ */
+ public static int findLength(int[] A, int[] B) {
+ int res = 0;
+ // DP问题
+ int[][] dp = new int[A.length + 1][B.length + 1];
+ for (int i = 1; i < dp.length; i++) {
+ for (int j = 1; j < dp[0].length; j++) {
+ if (A[i - 1] == B[j - 1]) {
+ dp[i][j] = dp[i - 1][j - 1] + 1;
+ res = Math.max(res, dp[i][j]);
+ }
+ }
+ }
+ return res;
+ }
+}
diff --git a/src/Q83RemoveDuplicatesfromSortedList.java b/src/Q83RemoveDuplicatesfromSortedList.java
new file mode 100644
index 0000000..6508961
--- /dev/null
+++ b/src/Q83RemoveDuplicatesfromSortedList.java
@@ -0,0 +1,53 @@
+import util.ListNode;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/1
+ * @time 0:09
+ */
+public class Q83RemoveDuplicatesfromSortedList {
+ /**
+ * 测试函数
+ */
+ public static void main(String[] args) {
+ ListNode l1 = new ListNode(1);
+ ListNode l2 = new ListNode(1);
+ ListNode l3 = new ListNode(2);
+ ListNode l4 = new ListNode(3);
+ ListNode l5 = new ListNode(3);
+ l1.next = l2;
+ l2.next = l3;
+ l3.next = l4;
+ l4.next = l5;
+ ListNode cur = deleteDuplicatesII(l1);
+ while (cur != null) {
+ System.out.print(cur.val + " ");
+ cur = cur.next;
+ }
+
+ }
+
+ /**
+ * 递归的方法,非常不建议使用,因为会产生栈的溢出
+ */
+ public static ListNode deleteDuplicates(ListNode head) {
+ if (head == null || head.next == null) return head;
+ head.next = deleteDuplicates(head.next);
+ return head.val == head.next.val ? head.next : head;
+ }
+
+ /**
+ * 常规的解法,时间复杂度O(n),空间复杂度O(1)
+ */
+ public static ListNode deleteDuplicatesII(ListNode head) {
+ ListNode cur = head;
+ while (cur != null && cur.next != null) {
+ if (cur.val == cur.next.val) {
+ cur.next = cur.next.next;
+ } else {
+ cur = cur.next;
+ }
+ }
+ return head;
+ }
+}
diff --git a/src/Q86PartitionList.java b/src/Q86PartitionList.java
index 2ad888f..6381319 100644
--- a/src/Q86PartitionList.java
+++ b/src/Q86PartitionList.java
@@ -50,6 +50,45 @@ public static ListNode partition(ListNode head, int x) {
return smallHead.next;
}
+ /**
+ * 空间复杂度O(1),时间复杂度O(n)
+ * 在链表内部调整,找到一个小的,就把这个小的放到前面。
+ * */
+ public ListNode partitionII(ListNode head, int x) {
+ // 循环的方法
+ // 存3个节点,一个是pre,一个cur,还有一个小数字的尾节点
+ if(head == null) {
+ return head;
+ }
+ ListNode dummyHead = new ListNode(-1);
+ dummyHead.next = head;
+ ListNode cur = head;
+ ListNode pre = dummyHead;
+ ListNode tail = dummyHead;
+ while(cur != null) {
+ if(cur.val < x) {
+ if(tail == pre) {
+ cur = cur.next;
+ pre = pre.next;
+ tail = tail.next;
+ } else {
+ // 摘链
+ pre.next = cur.next;
+ // 插入
+ cur.next = tail.next;
+ tail.next = cur;
+ tail = cur;
+ cur = pre.next;
+ }
+
+ } else {
+ cur = cur.next;
+ pre = pre.next;
+ }
+ }
+ return dummyHead.next;
+ }
+
public static class ListNode {
int val;
ListNode next;
diff --git a/src/Q946ValidateStackSequences.java b/src/Q946ValidateStackSequences.java
new file mode 100644
index 0000000..0663f19
--- /dev/null
+++ b/src/Q946ValidateStackSequences.java
@@ -0,0 +1,36 @@
+import java.util.Stack;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/13
+ * @time 18:52
+ */
+public class Q946ValidateStackSequences {
+ /**
+ *
+ * */
+ public static void main(String[] args) {
+ int[] pushed = {1, 2, 3, 4, 5};
+ int[] popped = {4, 5, 3, 2, 1};
+ System.out.println(validateStackSequences(pushed, popped));
+ }
+
+ /**
+ * 很简单的思想,不过记得stack要先push
+ * */
+ public static boolean validateStackSequences(int[] pushA, int[] popA) {
+ Stack stack = new Stack();
+ int j = 0;
+ for (int i = 0; i < pushA.length; i++) {
+ stack.push(pushA[i]);
+ while (!stack.isEmpty() && stack.peek() == popA[j]) {
+ j++;
+ stack.pop();
+ }
+ }
+ if (stack.isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/src/Q94BinaryTreeInorderTraversal.java b/src/Q94BinaryTreeInorderTraversal.java
index 6f076d9..7232cb3 100644
--- a/src/Q94BinaryTreeInorderTraversal.java
+++ b/src/Q94BinaryTreeInorderTraversal.java
@@ -1,3 +1,5 @@
+import util.TreeNode;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
@@ -64,14 +66,4 @@ public static List inorderTraversal2(TreeNode root) {
}
return res;
}
-
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/Q95UniqueBinarySearchTreesII.java b/src/Q95UniqueBinarySearchTreesII.java
new file mode 100644
index 0000000..593398b
--- /dev/null
+++ b/src/Q95UniqueBinarySearchTreesII.java
@@ -0,0 +1,95 @@
+import util.TreeNode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/5
+ * @time 15:46
+ */
+public class Q95UniqueBinarySearchTreesII {
+ public static void main(String[] args) {
+ //TODO 测试用例
+ }
+
+ /**
+ * 优化后的方法,也就是利用动态规划的特性,用空间换时间,将之前的内容存储起来
+ * 同时应用了一个小trick,左子树可以直接从之前的子树移动过来。
+ */
+ public static List generateTreesII(int n) {
+ List[] res = new List[n + 1];
+ res[0] = new ArrayList<>();
+ if (n == 0) {
+ return res[0];
+ }
+ // 赋值空
+ res[0].add(null);
+ // 1-i产生的结果
+ for (int i = 1; i <= n; i++) {
+ res[i] = new ArrayList();
+ // j是左子树的元素个数
+ for (int j = 0; j < i; j++) {
+ for (TreeNode left : res[j]) {
+ for (TreeNode right : res[i - j - 1]) {
+ // 根节点的值
+ TreeNode root = new TreeNode(j + 1);
+ root.left = left;
+ root.right = clone(right, j + 1);
+ res[i].add(root);
+ }
+ }
+ }
+ }
+ return res[n];
+ }
+
+ /**
+ * 节省空间,将从1开始的子树通过加上offset拷贝过来。因为右子树是从 offset + 1 开始的
+ */
+ public static TreeNode clone(TreeNode n, int offset) {
+ if (n == null) {
+ return null;
+ }
+ TreeNode node = new TreeNode(n.val + offset);
+ node.left = clone(n.left, offset);
+ node.right = clone(n.right, offset);
+ return node;
+ }
+
+ /**
+ * 暴力解法:通过辅助函数来完成(依然打败了63%)
+ * 缺点是没有利用之前存储的内容来进行计算
+ */
+ public List generateTrees(int n) {
+ List res = new ArrayList<>();
+ if (n == 0) {
+ return res;
+ }
+ return generateHelper(1, n);
+ }
+
+ /**
+ * 辅助函数的主要思路是分别得出左右子树的可能性,然后将这些子树拼接到一起,加入结果集
+ */
+ public List generateHelper(int s, int e) {
+ List res = new ArrayList<>();
+ if (s > e) {
+ res.add(null);
+ return res;
+ }
+ for (int i = s; i <= e; i++) {
+ List left = generateHelper(s, i - 1);
+ List right = generateHelper(i + 1, e);
+ for (TreeNode l : left) {
+ for (TreeNode r : right) {
+ TreeNode root = new TreeNode(i);
+ root.left = l;
+ root.right = r;
+ res.add(root);
+ }
+ }
+ }
+ return res;
+ }
+}
diff --git a/src/Q96UniqueBinarySearchTrees.java b/src/Q96UniqueBinarySearchTrees.java
index 9cd7299..7b35601 100644
--- a/src/Q96UniqueBinarySearchTrees.java
+++ b/src/Q96UniqueBinarySearchTrees.java
@@ -15,6 +15,7 @@ public static void main(String[] args) {
/**
* 空间换时间,记录之前的结果
+ * 卡塔兰数的一个例子
*/
public int numTrees(int n) {
// 二叉搜索树要满足左小右大的条件
diff --git a/src/Q97InterleavingString.java b/src/Q97InterleavingString.java
new file mode 100644
index 0000000..f957861
--- /dev/null
+++ b/src/Q97InterleavingString.java
@@ -0,0 +1,37 @@
+/**
+ * @author ahscuml
+ * @date 2019/3/16
+ * @time 9:00
+ */
+public class Q97InterleavingString {
+
+ /**
+ * DP的方法
+ * 首先要明白子问题是什么
+ * 空间换时间,空间的意义是什么
+ */
+ public boolean isInterleave(String s1, String s2, String s3) {
+ if ((s1.length() + s2.length()) != s3.length()) {
+ return false;
+ }
+ // 需要存储的空间
+ boolean[][] matrix = new boolean[s2.length() + 1][s1.length() + 1];
+ matrix[0][0] = true;
+ // 初始化第一行
+ for (int i = 1; i < matrix[0].length; i++) {
+ matrix[0][i] = matrix[0][i - 1] && (s1.charAt(i - 1) == s3.charAt(i - 1));
+ }
+ // 初始化第一列
+ for (int i = 1; i < matrix.length; i++) {
+ matrix[i][0] = matrix[i - 1][0] && (s2.charAt(i - 1) == s3.charAt(i - 1));
+ }
+ // 利用之前的计算填充二维数组
+ for (int i = 1; i < matrix.length; i++) {
+ for (int j = 1; j < matrix[0].length; j++) {
+ matrix[i][j] = (matrix[i - 1][j] && (s2.charAt(i - 1) == s3.charAt(i + j - 1)))
+ || (matrix[i][j - 1] && (s1.charAt(j - 1) == s3.charAt(i + j - 1)));
+ }
+ }
+ return matrix[s2.length()][s1.length()];
+ }
+}
diff --git a/src/Q98ValidateBinarySearchTree.java b/src/Q98ValidateBinarySearchTree.java
index 6685824..c78e278 100644
--- a/src/Q98ValidateBinarySearchTree.java
+++ b/src/Q98ValidateBinarySearchTree.java
@@ -1,7 +1,10 @@
+import util.TreeNode;
+
import java.util.Stack;
/**
* 二叉搜索树是不是合理的
+ *
* @author ahscuml
* @date 2018/12/28
* @time 16:34
@@ -54,17 +57,4 @@ public boolean isValidBSTIte(TreeNode root) {
}
return true;
}
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/TEST/InOrder.java b/src/TEST/InOrder.java
index f5c0651..76ef4f6 100644
--- a/src/TEST/InOrder.java
+++ b/src/TEST/InOrder.java
@@ -1,5 +1,7 @@
package TEST;
+import util.TreeNode;
+
import java.util.Stack;
/**
@@ -71,17 +73,4 @@ private static void inOrderIte(TreeNode root) {
}
}
}
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/TEST/LevelOrder.java b/src/TEST/LevelOrder.java
index 03bee31..70957d1 100644
--- a/src/TEST/LevelOrder.java
+++ b/src/TEST/LevelOrder.java
@@ -1,5 +1,7 @@
package TEST;
+import util.TreeNode;
+
import java.util.LinkedList;
import java.util.Queue;
@@ -153,18 +155,4 @@ public static void levelOrderIte(TreeNode root) {
}
}
}
-
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/TEST/PostOrder.java b/src/TEST/PostOrder.java
index 69b86ff..b40595c 100644
--- a/src/TEST/PostOrder.java
+++ b/src/TEST/PostOrder.java
@@ -1,5 +1,7 @@
package TEST;
+import util.TreeNode;
+
import java.util.Stack;
/**
@@ -42,7 +44,7 @@ private static void postOrderRec(TreeNode root) {
/*if (root == null) {
return;
}*/
- if(root!=null){
+ if (root != null) {
postOrderRec(root.left);
postOrderRec(root.right);
System.out.print(root.val);
@@ -63,9 +65,9 @@ private static void postOrderIte(TreeNode root) {
Stack output = new Stack<>();
TreeNode cur = root;
- while (cur != null || !stack.isEmpty()) {
+ while (cur != null || !stack.isEmpty()) {
if (cur != null) {
- output.push(cur);
+ output.push(cur);
stack.push(cur);
// 先进后出,所以先是右边
cur = cur.right;
@@ -80,17 +82,4 @@ private static void postOrderIte(TreeNode root) {
System.out.print(output.pop().val);
}
}
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/TEST/PreOrder.java b/src/TEST/PreOrder.java
index 15604d1..1d2ed9d 100644
--- a/src/TEST/PreOrder.java
+++ b/src/TEST/PreOrder.java
@@ -1,5 +1,7 @@
package TEST;
+import util.TreeNode;
+
import java.util.Stack;
/**
@@ -73,17 +75,4 @@ public static void preorderIte(TreeNode root) {
}
}
}
-
- /**
- * 树结构的定义
- */
- public static class TreeNode {
- int val;
- TreeNode left;
- TreeNode right;
-
- TreeNode(int x) {
- val = x;
- }
- }
}
diff --git a/src/util/ListNode.java b/src/util/ListNode.java
new file mode 100644
index 0000000..d529e10
--- /dev/null
+++ b/src/util/ListNode.java
@@ -0,0 +1,15 @@
+package util;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/1
+ * @time 0:10
+ */
+public class ListNode {
+ public int val;
+ public ListNode next;
+
+ public ListNode(int x) {
+ val = x;
+ }
+}
diff --git a/src/util/RandomNode.java b/src/util/RandomNode.java
new file mode 100644
index 0000000..ab84fd6
--- /dev/null
+++ b/src/util/RandomNode.java
@@ -0,0 +1,20 @@
+package util;
+
+/**
+ * @author ahscuml
+ * @date 2019/4/17
+ * @time 21:40
+ */
+public class RandomNode {
+ public int val;
+ public RandomNode next;
+ public RandomNode random;
+
+ public RandomNode() {}
+
+ public RandomNode(int _val,RandomNode _next,RandomNode _random) {
+ val = _val;
+ next = _next;
+ random = _random;
+ }
+}