├── .gitignore ├── README.md ├── algorithms-algs4 ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── brianway │ │ └── learning │ │ └── algorithms │ │ └── algs4utils │ │ ├── AVLTreeST.java │ │ ├── Accumulator.java │ │ ├── AcyclicLP.java │ │ ├── AcyclicSP.java │ │ ├── AdjMatrixEdgeWeightedDigraph.java │ │ ├── Alphabet.java │ │ ├── Arbitrage.java │ │ ├── AssignmentProblem.java │ │ ├── Average.java │ │ ├── BST.java │ │ ├── BTree.java │ │ ├── Bag.java │ │ ├── BellmanFordSP.java │ │ ├── BinaryDump.java │ │ ├── BinaryIn.java │ │ ├── BinaryInsertion.java │ │ ├── BinaryOut.java │ │ ├── BinarySearch.java │ │ ├── BinarySearchST.java │ │ ├── BinaryStdIn.java │ │ ├── BinaryStdOut.java │ │ ├── BinomialMinPQ.java │ │ ├── Bipartite.java │ │ ├── BipartiteMatching.java │ │ ├── BipartiteX.java │ │ ├── BlackFilter.java │ │ ├── BoruvkaMST.java │ │ ├── BoyerMoore.java │ │ ├── BreadthFirstDirectedPaths.java │ │ ├── BreadthFirstPaths.java │ │ ├── CC.java │ │ ├── CPM.java │ │ ├── Cat.java │ │ ├── ClosestPair.java │ │ ├── CollisionSystem.java │ │ ├── Complex.java │ │ ├── Count.java │ │ ├── Counter.java │ │ ├── Cycle.java │ │ ├── Date.java │ │ ├── DeDup.java │ │ ├── DegreesOfSeparation.java │ │ ├── DepthFirstDirectedPaths.java │ │ ├── DepthFirstOrder.java │ │ ├── DepthFirstPaths.java │ │ ├── DepthFirstSearch.java │ │ ├── Digraph.java │ │ ├── DigraphGenerator.java │ │ ├── DijkstraAllPairsSP.java │ │ ├── DijkstraSP.java │ │ ├── DijkstraUndirectedSP.java │ │ ├── DirectedCycle.java │ │ ├── DirectedCycleX.java │ │ ├── DirectedDFS.java │ │ ├── DirectedEdge.java │ │ ├── DirectedEulerianCycle.java │ │ ├── DirectedEulerianPath.java │ │ ├── DoublingRatio.java │ │ ├── DoublingTest.java │ │ ├── Draw.java │ │ ├── DrawListener.java │ │ ├── Edge.java │ │ ├── EdgeWeightedDigraph.java │ │ ├── EdgeWeightedDirectedCycle.java │ │ ├── EdgeWeightedGraph.java │ │ ├── EulerianCycle.java │ │ ├── EulerianPath.java │ │ ├── FFT.java │ │ ├── FarthestPair.java │ │ ├── FenwickTree.java │ │ ├── FibonacciMinPQ.java │ │ ├── FileIndex.java │ │ ├── FlowEdge.java │ │ ├── FlowNetwork.java │ │ ├── FloydWarshall.java │ │ ├── FordFulkerson.java │ │ ├── FrequencyCounter.java │ │ ├── GREP.java │ │ ├── GabowSCC.java │ │ ├── GaussJordanElimination.java │ │ ├── GaussianElimination.java │ │ ├── Genome.java │ │ ├── GrahamScan.java │ │ ├── Graph.java │ │ ├── GraphGenerator.java │ │ ├── Heap.java │ │ ├── HexDump.java │ │ ├── HopcroftKarp.java │ │ ├── Huffman.java │ │ ├── In.java │ │ ├── IndexBinomialMinPQ.java │ │ ├── IndexFibonacciMinPQ.java │ │ ├── IndexMaxPQ.java │ │ ├── IndexMinPQ.java │ │ ├── IndexMultiwayMinPQ.java │ │ ├── Insertion.java │ │ ├── InsertionX.java │ │ ├── Interval1D.java │ │ ├── Interval2D.java │ │ ├── KMP.java │ │ ├── KWIK.java │ │ ├── Knuth.java │ │ ├── KosarajuSharirSCC.java │ │ ├── KruskalMST.java │ │ ├── LSD.java │ │ ├── LZW.java │ │ ├── LazyPrimMST.java │ │ ├── LinearProbingHashST.java │ │ ├── LinearProgramming.java │ │ ├── LinearRegression.java │ │ ├── LinkedBag.java │ │ ├── LinkedQueue.java │ │ ├── LinkedStack.java │ │ ├── LongestCommonSubstring.java │ │ ├── LongestRepeatedSubstring.java │ │ ├── LookupCSV.java │ │ ├── LookupIndex.java │ │ ├── MSD.java │ │ ├── MaxPQ.java │ │ ├── Merge.java │ │ ├── MergeBU.java │ │ ├── MergeX.java │ │ ├── MinPQ.java │ │ ├── Multiway.java │ │ ├── MultiwayMinPQ.java │ │ ├── NFA.java │ │ ├── NonrecursiveDFS.java │ │ ├── NonrecursiveDirectedDFS.java │ │ ├── Out.java │ │ ├── Particle.java │ │ ├── PatriciaSET.java │ │ ├── PatriciaST.java │ │ ├── Picture.java │ │ ├── PictureDump.java │ │ ├── Point2D.java │ │ ├── PrimMST.java │ │ ├── Queue.java │ │ ├── Quick.java │ │ ├── Quick3string.java │ │ ├── Quick3way.java │ │ ├── QuickFindUF.java │ │ ├── QuickUnionUF.java │ │ ├── QuickX.java │ │ ├── RabinKarp.java │ │ ├── RandomSeq.java │ │ ├── RectHV.java │ │ ├── RedBlackBST.java │ │ ├── ResizingArrayBag.java │ │ ├── ResizingArrayQueue.java │ │ ├── ResizingArrayStack.java │ │ ├── RunLength.java │ │ ├── SET.java │ │ ├── ST.java │ │ ├── SegmentTree.java │ │ ├── Selection.java │ │ ├── SeparateChainingHashST.java │ │ ├── SequentialSearchST.java │ │ ├── Shell.java │ │ ├── SparseVector.java │ │ ├── Stack.java │ │ ├── StaticSETofInts.java │ │ ├── StdArrayIO.java │ │ ├── StdAudio.java │ │ ├── StdDraw.java │ │ ├── StdIn.java │ │ ├── StdOut.java │ │ ├── StdRandom.java │ │ ├── StdStats.java │ │ ├── Stopwatch.java │ │ ├── StopwatchCPU.java │ │ ├── SuffixArray.java │ │ ├── SuffixArrayX.java │ │ ├── SymbolDigraph.java │ │ ├── SymbolGraph.java │ │ ├── TST.java │ │ ├── TarjanSCC.java │ │ ├── ThreeSum.java │ │ ├── ThreeSumFast.java │ │ ├── TopM.java │ │ ├── Topological.java │ │ ├── TopologicalX.java │ │ ├── Transaction.java │ │ ├── TransitiveClosure.java │ │ ├── TrieSET.java │ │ ├── TrieST.java │ │ ├── TwoPersonZeroSumGame.java │ │ ├── UF.java │ │ ├── Vector.java │ │ ├── WeightedQuickUnionUF.java │ │ ├── WhiteFilter.java │ │ └── Whitelist.java │ └── resources │ └── algs4.jar ├── algorithms-lecture ├── README.md ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── brianway │ └── learning │ └── algorithms │ └── lectures │ ├── arithmetic │ ├── Ants.java │ ├── Bag.java │ ├── Calculator.java │ ├── Championship.java │ ├── CombineByMistake.java │ ├── Distribution.java │ ├── LonelyA.java │ ├── Parenthesis.java │ ├── Random01.java │ ├── Random7.java │ ├── RandomPrint.java │ ├── RandomSeg.java │ ├── Robot.java │ └── StandInLine.java │ ├── binarysearch │ ├── CountNodes.java │ ├── Find.java │ ├── LeftMostAppearance.java │ ├── LocalMin.java │ ├── MinValue.java │ └── QuickPower.java │ ├── binarytree │ ├── CheckBalance.java │ ├── CheckCompletion.java │ ├── FindErrorNode.java │ ├── FoldPaper.java │ ├── LongestDistance.java │ ├── MaxSubtree.java │ ├── TreeNode.java │ ├── TreePrinter.java │ ├── TreeToSequence.java │ ├── TreeToSequence2.java │ └── TreeToString.java │ ├── bit │ ├── Compare.java │ ├── OddAppearance.java │ ├── OddAppearance2.java │ └── Swap.java │ ├── dp │ ├── Backpack.java │ ├── Exchange.java │ ├── GoUpstairs.java │ ├── LCS.java │ ├── LongestIncreasingSubsequence.java │ ├── MinCost.java │ └── MinimumPath.java │ ├── linkedlist │ ├── CheckIntersect.java │ ├── ChkIntersection.java │ ├── ChkIntersection2.java │ ├── ChkLoop.java │ ├── ClearValue.java │ ├── Common.java │ ├── CopyList.java │ ├── Divide.java │ ├── InsertValue.java │ ├── KInverse.java │ ├── ListNode.java │ ├── Palindrome.java │ └── Remove.java │ ├── sort │ ├── BubbleSort.java │ ├── Checker.java │ ├── CountingSort.java │ ├── Finder.java │ ├── Gap.java │ ├── HeapSort.java │ ├── InsertionSort.java │ ├── Merge.java │ ├── MergeSort.java │ ├── QuickSort.java │ ├── RadixSort.java │ ├── ScaleSort.java │ ├── SelectionSort.java │ ├── ShellSort.java │ ├── Subsequence.java │ └── ThreeColor.java │ ├── stack │ ├── MaxTree.java │ ├── SlideWindow.java │ ├── StackMin.java │ ├── StackReverse.java │ ├── TwoStack.java │ └── TwoStacks.java │ └── string │ ├── DistinctSubstring.java │ ├── IdenticalTree.java │ ├── Parenthesis.java │ ├── Prior.java │ ├── Replacement.java │ ├── Reverse.java │ ├── Rotation.java │ ├── Transform.java │ └── Translation.java ├── algorithms-leetcode ├── README.md ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── brianway │ │ └── learning │ │ └── algorithms │ │ ├── company │ │ ├── bytedance │ │ │ └── TmpClz.java │ │ └── huawei │ │ │ └── Huawei.java │ │ └── leetcode │ │ ├── common │ │ ├── ListNode.java │ │ └── TreeNode.java │ │ ├── easy │ │ ├── AssignCookies.java │ │ ├── AverageOfLevelsInBinaryTree.java │ │ ├── BalancedBinaryTree.java │ │ ├── BestTimeToBuyAndSellStock.java │ │ ├── BinarySearch.java │ │ ├── BinaryTreeInorderTraversal.java │ │ ├── BinaryTreePaths.java │ │ ├── BinaryTreePreorderTraversal.java │ │ ├── ClimbingStairs.java │ │ ├── FindModeInBinarySearchTree.java │ │ ├── HappyNumber.java │ │ ├── IntersectionofTwoArrays.java │ │ ├── IntersectionofTwoLinkedLists.java │ │ ├── InvertBinaryTree.java │ │ ├── IsSubsequence.java │ │ ├── LinkedListCycle.java │ │ ├── LongestContinuousIncreasingSubsequence.java │ │ ├── MajorityElement.java │ │ ├── MaximumDepthOfBinaryTree.java │ │ ├── MergeTwoBinaryTrees.java │ │ ├── MergeTwoSortedLists.java │ │ ├── MinimumAbsoluteDifferenceInBST.java │ │ ├── MinimumDepthOfBinaryTree.java │ │ ├── MissingNumber.java │ │ ├── PathSum.java │ │ ├── PowerOfTwo.java │ │ ├── RemoveDuplicatesfromSortedArray.java │ │ ├── RemoveElement.java │ │ ├── ReverseLinkedList.java │ │ ├── ReverseString.java │ │ ├── ReverseStringII.java │ │ ├── SearchInBinarySearchTree.java │ │ ├── SearchInsertPosition.java │ │ ├── SumOfLeftLeaves.java │ │ ├── SymmetricTree.java │ │ ├── TwoSum.java │ │ └── ValidParentheses.java │ │ ├── hard │ │ ├── DistinctSubsequences.java │ │ ├── EditDistance.java │ │ ├── FirstMissingPositive.java │ │ ├── MergeKSortedLists.java │ │ ├── RegularExpressionMatching.java │ │ ├── RussianDollEnvelopes.java │ │ ├── SlidingWindowMaximum.java │ │ └── TrappingRainWater.java │ │ └── medium │ │ ├── AddTwoNumbers.java │ │ ├── BestTimeToBuyAndSellStockII.java │ │ ├── BinaryTreeLevelOrderTraversal.java │ │ ├── BinaryTreeLevelOrderTraversalII.java │ │ ├── BinaryTreeRightSideView.java │ │ ├── CoinChange.java │ │ ├── CoinChange2.java │ │ ├── CombinationSum.java │ │ ├── CombinationSumIII.java │ │ ├── Combinations.java │ │ ├── ConstructBinaryTreeFromInorderAndPostorderTraversal.java │ │ ├── ConstructBinaryTreeFromPreorderAndInorderTraversal.java │ │ ├── ContainerWithMostWater.java │ │ ├── CopyListWithRandomPointer.java │ │ ├── CountCompleteTreeNodes.java │ │ ├── DeleteOperationForTwoStrings.java │ │ ├── EvaluateReversePolishNotation.java │ │ ├── FindBottomLeftTreeValue.java │ │ ├── FindFirstAndLastPositionOfElementInSortedArray.java │ │ ├── FindMinimuminRotatedSortedArray.java │ │ ├── FindPeakElement.java │ │ ├── FlattenBinaryTreeToLinkedList.java │ │ ├── GenerateParentheses.java │ │ ├── GroupAnagrams.java │ │ ├── HouseRobber.java │ │ ├── IntegerBreak.java │ │ ├── JumpGame.java │ │ ├── JumpGameII.java │ │ ├── KthSmallestElementInBST.java │ │ ├── LetterCombinationsOfPhoneNumber.java │ │ ├── LinkedListCycleII.java │ │ ├── LongestCommonSubsequence.java │ │ ├── LongestConsecutiveSequence.java │ │ ├── LongestIncreasingSubsequence.java │ │ ├── LongestPalindromicSubsequence.java │ │ ├── LongestPalindromicSubstring.java │ │ ├── LongestSubstringWithoutRepeatingCharacters.java │ │ ├── LowestCommonAncestorOfBinaryTree.java │ │ ├── MaximalSquare.java │ │ ├── MaximumBinaryTree.java │ │ ├── MaximumLengthOfRepeatedSubarray.java │ │ ├── MaximumProductSubarray.java │ │ ├── MaximumSubarray.java │ │ ├── MergeIntervals.java │ │ ├── MinStack.java │ │ ├── MinimumPathSum.java │ │ ├── MinimumSizeSubarraySum.java │ │ ├── NextPermutation.java │ │ ├── OnesAndZeroes.java │ │ ├── PalindromePartitioning.java │ │ ├── PalindromicSubstrings.java │ │ ├── PartitionEqualSubsetSum.java │ │ ├── PathSumII.java │ │ ├── Permutations.java │ │ ├── RemoveNthNodeFromEndOfList.java │ │ ├── RotateImage.java │ │ ├── Search2DMatrix.java │ │ ├── SearchInRotatedSortedArray.java │ │ ├── SetMatrixZeroes.java │ │ ├── SortColors.java │ │ ├── SortList.java │ │ ├── SpiralMatrix.java │ │ ├── Subsets.java │ │ ├── SwapNodesInPairs.java │ │ ├── TargetSum.java │ │ ├── ThreeSum.java │ │ ├── TopKFrequentElements.java │ │ ├── Triangle.java │ │ ├── UncrossedLines.java │ │ ├── UniqueBinarySearchTrees.java │ │ ├── UniquePaths.java │ │ ├── UniquePathsII.java │ │ ├── ValidateBinarySearchTree.java │ │ ├── WiggleSubsequence.java │ │ ├── WordBreak.java │ │ ├── WordSearch.java │ │ └── ZigzagConversion.java │ └── test │ └── java │ └── com │ └── brianway │ └── learning │ └── algorithms │ └── leetcode │ ├── easy │ ├── HappyNumberTest.java │ ├── MajorityElementTest.java │ ├── MaximumSubarrayTest.java │ ├── PowerOfTwoTest.java │ ├── RemoveDuplicatesfromSortedArrayTest.java │ ├── ReverseStringTest.java │ ├── SearchInsertPositionTest.java │ └── TwoSumTest.java │ ├── hard │ ├── FirstMissingPositiveTest.java │ └── RegularExpressionMatchingTest.java │ └── medium │ ├── FindMinimuminRotatedSortedArrayTest.java │ ├── FindPeakElementTest.java │ ├── LetterCombinationsOfPhoneNumberTest.java │ ├── MinimumSizeSubarraySumTest.java │ ├── SearchRotatedSortedArrayTest.java │ ├── ThreeSumTest.java │ └── TriangleTest.java └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Eclipse 2 | .classpath 3 | .project 4 | .settings/ 5 | 6 | # Intellij 7 | .idea/ 8 | *.iml 9 | *.iws 10 | 11 | # Mac 12 | .DS_Store 13 | 14 | # Maven 15 | log/ 16 | target/ 17 | out/ 18 | 19 | # Others 20 | bin/ 21 | .myeclipse -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 我的算法学习笔记 2 | 3 | 在 coursera 和牛课网上看在线课程学习,顺带在 LeetCode 上刷题。所有算法均用 java 实现,配有思路说明。 4 | 5 | **如果觉得不错,请先在这个仓库上点个 star 吧**,这也是对我的肯定和鼓励,谢谢了。 6 | 7 | 不定时进行调整和补充,需要关注更新的请 Watch、Star、Fork 8 | 9 | 10 | ----- 11 | 12 | # 仓库目录 13 | 14 | 15 | - [algorithms-lecture](/algorithms-lecture):牛课网算法课程上涉及到的源码 16 | - [algorithms-leetcode](/algorithms-leetcode):leetcode 的 java 题解,源码+注释 17 | - [algorithms-algs4](/algorithms-algs4):《算法》(第四版)的官网配套源码,copy到该模块了 18 | 19 | ----- 20 | 21 | 22 | # 博文列表 23 | 24 | - [常见数据结构(一)-栈,队列,堆,哈希表](http://blog.csdn.net/h3243212/article/details/52811969) 25 | - [常见数据结构(二)-树(二叉树,红黑树,B树)](http://blog.csdn.net/h3243212/article/details/52819734) 26 | - [常见算法基础题思路简析(一)-排序篇](http://blog.csdn.net/h3243212/article/details/78128651) 27 | - [常见算法基础题思路简析(二)-链表篇](http://blog.csdn.net/h3243212/article/details/78128666) 28 | - [常见算法基础题思路简析(三)-二叉树篇](http://blog.csdn.net/h3243212/article/details/78128683) 29 | - [常见算法基础题思路简析(四)-二分搜索篇](http://blog.csdn.net/h3243212/article/details/78128699) 30 | - [常见算法基础题思路简析(五)-队列和栈篇](http://blog.csdn.net/h3243212/article/details/78128717) 31 | - [常见算法基础题思路简析(六)-字符串篇](http://blog.csdn.net/h3243212/article/details/78128729) 32 | 33 | 34 | ---- 35 | 36 | # TODO 37 | 38 | 计划逐步完善这个仓库,扩充并实现下面的功能 39 | 40 | * [ ] algorithms-lecture 模块记录牛课网的[《算法面试精品课》](http://www.nowcoder.com/courses/1)练习题(进行中) 41 | * [ ] LeetCode 的题目使用 algorithms-leetcode 模块(进行中) 42 | * [ ] 《剑指 offer》的练习题使用 algorithms-swordoffer 模块 43 | 44 | 45 | ----- 46 | 47 | # 联系作者 48 | 49 | - [Brian's Personal Website](http://brianway.github.io/) 50 | - [CSDN](http://blog.csdn.net/h3243212/) 51 | - [oschina](http://my.oschina.net/brianway) 52 | 53 | 54 | ----- 55 | 56 | # Lisence 57 | 58 | Lisenced under [Apache 2.0 lisence](http://opensource.org/licenses/Apache-2.0) 59 | -------------------------------------------------------------------------------- /algorithms-algs4/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | algorithms-learning 7 | com.brianway.learning.algorithms 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | algorithms-algs4 13 | 14 | 15 | 16 | junit 17 | junit 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /algorithms-algs4/src/main/resources/algs4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brianway/algorithms-learning/b63160671b799327e0cdc709b844d2c64d836b5a/algorithms-algs4/src/main/resources/algs4.jar -------------------------------------------------------------------------------- /algorithms-lecture/README.md: -------------------------------------------------------------------------------- 1 | # 牛客网算法精品课题解 2 | 3 | 暂时记录复习情况 4 | 5 | ## sort 包下 6 | 7 | - Gap: F1 8 | - Subsequence: M1 9 | 10 | ## linkedlist 包 11 | 12 | - ChkLoop: M1 13 | - ClearValue: M1 14 | 15 | ## binarytree 包 16 | 17 | - FindErrorNode: F1 18 | - TreeToSequence2: M1 19 | 20 | ## binarysearch 包 21 | 22 | - LovalMin: M1 23 | - QuickPower: F1 24 | 25 | ## stack 包 26 | 27 | - MaxTree: F1 28 | 29 | ## string 包 30 | 31 | - DistinctSubstring: F1 32 | - IdenticalTree: M1 (KMP 复习) 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /algorithms-lecture/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | algorithms-learning 7 | com.brianway.learning.algorithms 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | algorithms-lectures 13 | 14 | 15 | 16 | junit 17 | junit 18 | 19 | 20 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/Ants.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | /** 4 | * Created by brian on 16/11/19. 5 | * 6 | * n只蚂蚁从正n边形的n个定点沿着边移动,速度是相同的,问它们碰头的概率是多少? 7 | * 给定一个正整数n,请返回一个数组,其中两个元素分别为结果的分子和分母,请化为最简分数。 8 | * 9 | * 测试样例: 10 | * 3 11 | * 返回:[3,4] 12 | */ 13 | public class Ants { 14 | public int[] collision(int n) { 15 | int total = 1 << n; 16 | //int meet = total - 2; 17 | total /= 2; 18 | return new int[] {total - 1, total}; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/Bag.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Created by brian on 16/11/19. 7 | * 8 | * 有一个机器按自然数序列的方式吐出球,1号球,2号球,3号球等等。 9 | * 你有一个袋子,袋子里最多只能装下K个球,并且除袋子以外, 10 | * 你没有更多的空间,一个球一旦扔掉,就再也不可拿回。 11 | * 设计一种选择方式,使得当机器吐出第N号球的时候,你袋子中的球数是K个, 12 | * 同时可以保证从1号球到N号球中的每一个,被选进袋子的概率都是K/N。 13 | * 14 | * 举一个更具体的例子,有一个只能装下10个球的袋子,当吐出100个球时,袋子里有10 球, 15 | * 并且1~100号中的每一个球被选中的概率都是10/100。 16 | * 然后继续吐球,当吐出1000个球时,袋子里有 10 个球, 17 | * 并且1~1000号中的每一个球被选中的概率都是10/1000。继续吐球, 18 | * 当吐出i个球时,袋子里有10个球,并且1~i号中的每一个球被选中的概率都是10/i。 19 | * 也就是随着N的变化,1~N号球被选中的概率动态变化成k/N。 20 | * 请将吐出第N个球时袋子中的球的编号返回。 21 | */ 22 | public class Bag { 23 | 24 | private int[] selected = null; 25 | private static Random rand = new Random(12345); 26 | 27 | // 每次拿一个球都会调用这个函数,N表示第i次调用 28 | public int[] carryBalls(int N, int k) { 29 | if (selected == null) { 30 | selected = new int[k]; 31 | } 32 | if (N < k) { 33 | selected[N - 1] = N; 34 | } else { 35 | if (rand.nextInt(N) < k) { 36 | selected[rand.nextInt(k)] = N; 37 | } 38 | } 39 | 40 | return selected; 41 | } 42 | } -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/Calculator.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | /** 4 | * Created by brian on 16/11/19. 5 | * 6 | * 计算排列组合的类 7 | */ 8 | public class Calculator { 9 | public static int A(int n, int k) { 10 | int result = 1; 11 | for (int i = n; i > n - k; i--) { 12 | result *= i; 13 | } 14 | 15 | return result; 16 | } 17 | 18 | public static int C(int n, int m) { 19 | int result = 1; 20 | for (int i = n; i > n - m; i--) { 21 | result *= i; 22 | } 23 | for (int i = 1; i <= m; i++) { 24 | result /= i; 25 | } 26 | 27 | return result; 28 | } 29 | 30 | //greatest common divisors 31 | public static int gcd(int x, int y) { 32 | int t; 33 | while (y > 0) { 34 | t = y; 35 | y = x % y; 36 | x = t; 37 | } 38 | return x; 39 | } 40 | 41 | public static void main(String[] args) { 42 | int a = Calculator.A(8, 4); 43 | int c = Calculator.C(8, 2); 44 | 45 | System.out.println(a); 46 | System.out.println(c); 47 | 48 | int n = 10; 49 | int m = 4; 50 | System.out.println(C(n, m) == (A(n, n) / A(m, m) / A(n - m, n - m))); 51 | 52 | System.out.println(gcd(6, 9)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/Championship.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | import static com.brianway.learning.algorithms.lectures.arithmetic.Calculator.A; 4 | import static com.brianway.learning.algorithms.lectures.arithmetic.Calculator.C; 5 | import static com.brianway.learning.algorithms.lectures.arithmetic.Calculator.gcd; 6 | 7 | /** 8 | * Created by brian on 16/11/19. 9 | * 10 | * 有2k只球队,有k-1个强队,其余都是弱队,随机把它们分成k组比赛,每组两个队,问两强相遇的概率是多大? 11 | * 给定一个数k,请返回一个数组,其中有两个元素,分别为最终结果的分子和分母,请化成最简分数 12 | * 13 | * 测试样例: 14 | * 4 15 | * 返回:[3,7] 16 | */ 17 | public class Championship { 18 | public int[] calc(int k) { 19 | int total = 1; 20 | for (int i = 2 * k - 1; i > 2; i = i - 2) { 21 | total *= i; 22 | } 23 | 24 | int qr = C(k + 1, k - 1) * A(k - 1, k - 1); 25 | int qq = total - qr; 26 | int g = gcd(total, qq); 27 | return new int[] {qq / g, total / g}; 28 | } 29 | 30 | public static void main(String[] args) { 31 | Championship c = new Championship(); 32 | int[] res = c.calc(4); 33 | System.out.println(res[0]); 34 | System.out.println(res[1]); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/CombineByMistake.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | /** 4 | * Created by brian on 16/11/19. 5 | * 6 | * 有n个信封,包含n封信,现在把信拿出来,再装回去,要求每封信不能装回它原来的信封,问有多少种装法? 7 | * 给定一个整数n,请返回装发个数,为了防止溢出,请返回结果Mod 1000000007的值。保证n的大小小于等于300。 8 | * 9 | * 测试样例: 10 | * 2 11 | * 返回:1 12 | */ 13 | public class CombineByMistake { 14 | public int countWays(int n) { 15 | if (n == 1) { 16 | return 0; 17 | } 18 | if (n == 2) { 19 | return 1; 20 | } 21 | int mod = 1000000007; 22 | int pre = 0; 23 | int last = 1; 24 | long tmp = 0; 25 | for (int i = 3; i <= n; i++) { 26 | tmp = (long) (i - 1) * (pre + last) % mod; 27 | pre = last; 28 | last = (int) tmp; 29 | } 30 | return last; 31 | 32 | } 33 | 34 | public static void main(String[] args) { 35 | CombineByMistake cbm = new CombineByMistake(); 36 | System.out.println(cbm.countWays(4)); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/Distribution.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | /** 4 | * Created by brian on 16/11/18. 5 | * 6 | * n颗相同的糖果,分给m个人,每人至少一颗,问有多少种分法。 7 | * 给定n和m,请返回方案数,保证n小于等于12,且m小于等于n。 8 | * 测试样例: 9 | * 10 | * 10,3 11 | * 返回:36 12 | */ 13 | public class Distribution { 14 | public int getWays(int n, int m) { 15 | n--; 16 | m--; 17 | int r = 1; 18 | for (int i = n; i > n - m; i--) { 19 | r *= i; 20 | } 21 | for (int i = 1; i <= m; i++) { 22 | r /= i; 23 | } 24 | 25 | return r; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/LonelyA.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | /** 4 | * Created by brian on 16/11/18. 5 | * 6 | * A(A也是他的编号)是一个孤傲的人,在一个n个人(其中编号依次为1到n)的队列中, 7 | * 他于其中的标号为b和标号c的人都有矛盾,所以他不会和他们站在相邻的位置。 8 | * 现在问你满足A的要求的对列有多少种? 9 | * 给定人数n和三个人的标号A,b和c,请返回所求答案,保证人数小于等于11且大于等于3。 10 | * 11 | * 测试样例: 12 | * 6,1,2,3 13 | * 288 14 | */ 15 | public class LonelyA { 16 | public int getWays(int n, int A, int b, int c) { 17 | int all = 1; 18 | for (int i = 1; i <= n; i++) { 19 | all *= i; 20 | } 21 | 22 | int ab = 2; 23 | for (int i = 1; i <= n - 1; i++) { 24 | ab *= i; 25 | } 26 | int ac = ab; 27 | 28 | int abc = 2; 29 | for (int i = 1; i <= n - 2; i++) { 30 | abc *= i; 31 | } 32 | 33 | return all - ab - ac + abc; 34 | 35 | } 36 | 37 | public static void main(String[] args) { 38 | LonelyA la = new LonelyA(); 39 | System.out.println(la.getWays(6, 1, 2, 3)); 40 | System.out.println(la.getWays(3, 1, 2, 3)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/Parenthesis.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | /** 4 | * Created by brian on 16/11/19. 5 | * 6 | * 问题1: 7 | * 假设有n对左右括号,请求出合法的排列有多少个? 8 | * 合法是指每一个括号都可以找到与之配对的括号,比如n=1时,()是合法的,但是)(为不合法。 9 | * 给定一个整数n,请返回所求的合法排列数。保证结果在int范围内。 10 | * 11 | * 问题2: 12 | * n个数进出栈的顺序有多少种?假设栈的容量无限大。 13 | * 给定一个整数n,请返回所求的进出栈顺序个数。保证结果在int范围内。 14 | * 15 | * 问题3: 16 | * 2n个人排队买票,n个人拿5块钱,n个人拿10块钱,票价是5块钱1张, 17 | * 每个人买一张票,售票员手里没有零钱,问有多少种排队方法让售票员可以顺利卖票。 18 | * 给定一个整数n,请返回所求的排队方案个数。保证结果在int范围内。 19 | * 20 | * 问题4: 21 | * 求n个无差别的节点构成的二叉树有多少种不同的结构? 22 | * 给定一个整数n,请返回不同结构的二叉树的个数。保证结果在int范围内。 23 | * 24 | * 问题5: 25 | * 12个高矮不同的人,排成两排,每排必须是从矮到高排列, 26 | * 而且第二排比对应的第一排的人高,问排列方式有多少种? 27 | * 给定一个偶数n,请返回所求的排列方式个数。保证结果在int范围内。 28 | * 29 | * 12个高矮不同的人,排成两排,每排必须是从矮到高排列, 30 | * 而且第二排比对应的第一排的人高,问排列方式有多少种? 31 | * 给定一个偶数n,请返回所求的排列方式个数。保证结果在int范围内。 32 | * (答案稍有改动:n = n/2,再代入下面的代码中) 33 | * 34 | * 测试样例: 35 | * 1 36 | * 返回:1 37 | */ 38 | public class Parenthesis { 39 | public int countLegalWays(int n) { 40 | int a = 1; 41 | for (int i = 2 * n; i > n; i--) { 42 | a *= i; 43 | } 44 | for (int i = 1; i <= n; i++) { 45 | a /= i; 46 | } 47 | return a / (n + 1); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/Random01.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Created by brian on 16/11/19. 7 | * 8 | * 给定一个以p概率产生0,以1-p概率产生1的随机函数RandomP::f(),p是固定的值,但你并不知道是多少。 9 | * 除此之外也不能使用任何额外的随机机制,请用RandomP::f()实现等概率随机产生0和1的随机函数。 10 | */ 11 | public class Random01 { 12 | private static double p = new Random().nextFloat(); 13 | 14 | // 随机概率p 15 | public static int f() { 16 | return new Random().nextFloat() < p ? 0 : 1; 17 | } 18 | 19 | public int random01() { 20 | // 通过f函数实现01等概率返回 21 | int first; 22 | int second; 23 | while (true) { 24 | first = f(); 25 | second = f(); 26 | if (first != second) { 27 | break; 28 | } 29 | } 30 | 31 | return first; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/Random7.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Created by brian on 16/11/19. 7 | * 8 | * 给定一个等概率随机产生1~5的随机函数,除此之外,不能使用任何额外的随机机制, 9 | * 请实现等概率随机产生1~7的随机函数。 10 | * (给定一个可调用的Random5::random()方法,可以等概率地随机产生1~5的随机函数) 11 | */ 12 | public class Random7 { 13 | private static Random rand = new Random(123456); 14 | 15 | // 随机产生[1,5] 16 | private int rand5() { 17 | return 1 + rand.nextInt(5); 18 | } 19 | 20 | // 通过rand5实现rand7 21 | public int randomNumber() { 22 | int f = 21; 23 | while (f > 20) { 24 | f = (rand5() - 1) * 5 + rand5() - 1; 25 | } 26 | //f : 0,1,...,20 27 | return f % 7 + 1; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/RandomPrint.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Created by brian on 16/11/19. 7 | * 8 | * 给定一个长度为N且没有重复元素的数组arr和一个整数M,实现函数等概率随机打印arr中的M个数。 9 | */ 10 | public class RandomPrint { 11 | public int[] print(int[] arr, int N, int M) { 12 | if (arr == null || M > N || N == 0) { 13 | throw new RuntimeException("error param"); 14 | } 15 | 16 | int[] res = new int[M]; 17 | Random rand = new Random(); 18 | int m = 0; 19 | for (int i = 0; i < M; i++) { 20 | m = rand.nextInt(N - i); 21 | 22 | res[i] = arr[m]; 23 | arr[m] = arr[N - 1 - i]; 24 | arr[N - 1 - i] = res[i]; 25 | } 26 | 27 | return res; 28 | 29 | } 30 | 31 | public static void main(String[] args) { 32 | RandomPrint rp = new RandomPrint(); 33 | int[] a = {29, 24, 17, 1, 3, 11, 8, 19, 12, 15, 10, 28, 20, 18, 2, 26, 14, 7, 22, 27, 23, 5, 6, 9, 21, 16, 25, 4, 13}; 34 | int[] b = rp.print(a, a.length, 10); 35 | for (int i : b) { 36 | System.out.print(i + ","); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/RandomSeg.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Created by brian on 16/11/19. 7 | * 8 | * 假设函数f()等概率随机返回一个在[0,1)范围上的浮点数,那么我们知道,在[0,x)区间上的数出现的概率为x(0 x + y - m; i--) { 21 | k = k * i; 22 | } 23 | for (int i = 1; i <= m; i++) { 24 | k = k / i; 25 | } 26 | 27 | return k; 28 | } 29 | 30 | public static void main(String[] args) { 31 | Robot r = new Robot(); 32 | System.out.println(r.countWays(3, 4)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/arithmetic/StandInLine.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.arithmetic; 2 | 3 | /** 4 | * Created by brian on 16/11/18. 5 | * 6 | * n个人站队,他们的编号依次从1到n,要求编号为a的人必须在编号为b的人的左边, 7 | * 但不要求一定相邻,请问共有多少种排法? 8 | * 第二问如果要求a必须在b的左边,并且一定要相邻,请问一共有多少种排法? 9 | * 给定人数n及两个人的编号a和b,请返回一个两个元素的数组, 10 | * 其中两个元素依次为两个问题的答案。保证人数小于等于10。 11 | * 12 | * 测试样例: 13 | * 7,1,2 14 | * 返回:[2520,720] 15 | */ 16 | public class StandInLine { 17 | public int[] getWays(int n, int a, int b) { 18 | int first = 1; 19 | for (int i = 1; i <= n; i++) { 20 | first *= i; 21 | } 22 | first /= 2; 23 | 24 | int second = first * 2 / n; 25 | 26 | return new int[] {first, second}; 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarysearch/CountNodes.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarysearch; 2 | 3 | /** 4 | * Created by brian on 16/11/15. 5 | * 6 | * 给定一棵完全二叉树的根节点root,返回这棵树的节点个数。 7 | * 如果完全二叉树的节点数为N,请实现时间复杂度低于O(N)的解法。 8 | * 给定树的根结点root,请返回树的大小。 9 | */ 10 | public class CountNodes { 11 | private static class TreeNode { 12 | int val = 0; 13 | TreeNode left = null; 14 | TreeNode right = null; 15 | 16 | public TreeNode(int val) { 17 | this.val = val; 18 | } 19 | } 20 | 21 | public int count(TreeNode root) { 22 | if (root == null) { 23 | return 0; 24 | } 25 | 26 | int height = 0; 27 | TreeNode current = root; 28 | while (current != null) { 29 | current = current.left; 30 | height++; 31 | } 32 | int rightHeight = 1; 33 | current = root.right; 34 | while (current != null) { 35 | current = current.left; 36 | rightHeight++; 37 | } 38 | int count = 0; 39 | if (height > rightHeight) { 40 | count = (1 << (height - 2)) + count(root.left); 41 | } else { 42 | count = (1 << (height - 1)) + count(root.right); 43 | } 44 | return count; 45 | 46 | } 47 | 48 | public static void main(String[] args) { 49 | TreeNode t1 = new TreeNode(1); 50 | TreeNode t2 = new TreeNode(2); 51 | TreeNode t3 = new TreeNode(3); 52 | t1.left = t2; 53 | t1.right = t3; 54 | CountNodes cn = new CountNodes(); 55 | int count = cn.count(t1); 56 | System.out.println(count); 57 | System.out.println(cn.count(t2)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarysearch/Find.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarysearch; 2 | 3 | /** 4 | * Created by brian on 16/11/15. 5 | * 6 | * 有一个有序数组arr,其中不含有重复元素,请找到满足arr[i]==i条件的最左的位置。 7 | * 如果所有位置上的数都不满足条件,返回-1。 8 | * 给定有序数组arr及它的大小n,请返回所求值。 9 | * 10 | * 测试样例: 11 | * [-1,0,2,3],4 12 | * 返回:2 13 | */ 14 | public class Find { 15 | public int findPos(int[] arr, int n) { 16 | if (arr == null || n == 0) { 17 | return -1; 18 | } 19 | 20 | if (arr[0] > n - 1 || arr[n - 1] < 0) { 21 | return -1; 22 | } 23 | 24 | int res = -1; 25 | int lo = 0; 26 | int hi = n - 1; 27 | int mid = 0; 28 | while (lo <= hi) { 29 | mid = lo + (hi - lo) / 2; 30 | if (arr[mid] > mid) { 31 | hi = mid - 1; 32 | } else if (arr[mid] < mid) { 33 | lo = mid + 1; 34 | } else { 35 | res = mid; 36 | hi = mid - 1; 37 | } 38 | } 39 | 40 | return res; 41 | } 42 | 43 | public static void main(String[] args) { 44 | int[] arr = {-1, 1, 2, 3, 4, 5}; 45 | Find find = new Find(); 46 | System.out.println(find.findPos(arr, arr.length)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarysearch/LeftMostAppearance.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarysearch; 2 | 3 | /** 4 | * Created by brian on 16/11/15. 5 | * 6 | * 对于一个有序数组arr,再给定一个整数num,请在arr中找到num这个数出现的最左边的位置。 7 | * 给定一个数组arr及它的大小n,同时给定num。请返回所求位置。 8 | * 若该元素在数组中未出现,请返回-1。 9 | * 10 | * 测试样例: 11 | * [1,2,3,3,4],5,3 12 | * 返回:2 13 | */ 14 | public class LeftMostAppearance { 15 | public int findPos(int[] arr, int n, int num) { 16 | if (arr == null || n == 0) { 17 | return -1; 18 | } 19 | int lo = 0; 20 | int hi = n - 1; 21 | int mid = 0; 22 | int res = -1; 23 | while (lo <= hi) { 24 | mid = lo + (hi - lo) / 2; 25 | if (arr[mid] > num) { 26 | hi = mid - 1; 27 | } else if (arr[mid] < num) { 28 | lo = mid + 1; 29 | } else { 30 | res = mid; 31 | hi = mid - 1; 32 | } 33 | } 34 | return res; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarysearch/LocalMin.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarysearch; 2 | 3 | /** 4 | * Created by brian on 16/11/15. 5 | * 6 | * 定义局部最小的概念。arr长度为1时,arr[0]是局部最小。 7 | * arr的长度为N(N>1)时,如果arr[0] arr[mid - 1]) { 33 | hi = mid - 1; 34 | } else if (arr[mid] > arr[mid + 1]) { 35 | lo = mid + 1; 36 | } else { 37 | return mid; 38 | } 39 | } 40 | return lo; 41 | } 42 | 43 | public static void main(String[] args) { 44 | int[] a = {5, 4, 1, 3, 6, 7, 8, 9}; 45 | LocalMin lm = new LocalMin(); 46 | int index = lm.getLessIndex(a); 47 | System.out.println("a[" + index + "]=" + a[index]); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarysearch/QuickPower.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarysearch; 2 | 3 | /** 4 | * Created by brian on 16/11/15. 5 | * 6 | * 如果更快的求一个整数k的n次方。如果两个整数相乘并得到结果的时间复杂度为O(1), 7 | * 得到整数k的N次方的过程请实现时间复杂度为O(logN)的方法。 8 | * 给定k和n,请返回k的n次方,为了防止溢出,请返回结果Mod 1000000007的值。 9 | * 10 | * 测试样例: 11 | * 2,3 12 | * 返回:8 13 | */ 14 | public class QuickPower { 15 | public int getPower(int k, int N) { 16 | long tmp = k; 17 | long res = 1; 18 | long divisor = 1000000007; 19 | for (; N != 0; N >>= 1) { 20 | if ((N & 1) != 0) { 21 | res = res * tmp % divisor; 22 | } 23 | 24 | tmp = tmp * tmp % divisor; 25 | 26 | } 27 | 28 | return (int) res; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarytree/CheckBalance.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarytree; 2 | 3 | /** 4 | * Created by brian on 16/11/16. 5 | * 6 | * 有一棵二叉树,请设计一个算法判断这棵二叉树是否为平衡二叉树。 7 | * 给定二叉树的根结点root,请返回一个bool值,代表这棵树是否为平衡二叉树。 8 | */ 9 | public class CheckBalance { 10 | public boolean check(TreeNode root) { 11 | return post(root) >= 0; 12 | } 13 | 14 | private int post(TreeNode root) { 15 | if (root == null) { 16 | return 0; 17 | } 18 | 19 | int leftHeight = post(root.left); 20 | if (leftHeight == -1) { 21 | return -1; 22 | } 23 | int rightHeight = post(root.right); 24 | if (rightHeight == -1) { 25 | return -1; 26 | } 27 | 28 | if (Math.abs(leftHeight - rightHeight) > 1) { 29 | return -1; 30 | } 31 | 32 | return Math.max(leftHeight, rightHeight) + 1; 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarytree/CheckCompletion.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarytree; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | /** 7 | * Created by brian on 16/11/16. 8 | * 9 | * 有一棵二叉树,请设计一个算法判断它是否是完全二叉树。 10 | * 给定二叉树的根结点root,请返回一个bool值代表它是否为完全二叉树。 11 | * 树的结点个数小于等于500。 12 | */ 13 | public class CheckCompletion { 14 | public boolean chk(TreeNode root) { 15 | if (root == null) { 16 | return false; 17 | } 18 | Queue queue = new LinkedList(); 19 | queue.add(root); 20 | TreeNode current = null; 21 | boolean lastParent = false; 22 | while (!queue.isEmpty()) { 23 | current = queue.poll(); 24 | if (current.right != null && current.left == null) { 25 | return false; 26 | } 27 | if (lastParent && !isLeaf(current)) { 28 | return false; 29 | } 30 | if (current.left != null) { 31 | queue.add(current.left); 32 | } 33 | 34 | if (current.right != null) { 35 | queue.add(current.right); 36 | } else { 37 | lastParent = true; 38 | } 39 | 40 | } 41 | return true; 42 | } 43 | 44 | private boolean isLeaf(TreeNode leaf) { 45 | return leaf.left == null && leaf.right == null; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarytree/FindErrorNode.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarytree; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * Created by brian on 16/11/16. 7 | * 8 | * 一棵二叉树原本是搜索二叉树,但是其中有两个节点调换了位置, 9 | * 使得这棵二叉树不再是搜索二叉树,请找到这两个错误节点并返回他们的值。 10 | * 保证二叉树中结点的值各不相同。 11 | * 给定一棵树的根结点,请返回两个调换了位置的值,其中小的值在前。 12 | */ 13 | public class FindErrorNode { 14 | public int[] findError(TreeNode root) { 15 | int[] error = new int[2]; 16 | Stack stack = new Stack(); 17 | if (root == null) { 18 | return null; 19 | } 20 | TreeNode current = root; 21 | stack.push(root); 22 | int last = 0; 23 | boolean hasSet = false; 24 | boolean hasLast = false; 25 | while (!stack.isEmpty()) { 26 | if (current == null || current.left == null) { 27 | current = stack.pop(); 28 | 29 | if (!hasLast) { 30 | last = current.val; 31 | hasLast = true; 32 | } 33 | if (current.val < last) { 34 | error[0] = current.val; 35 | if (!hasSet) { 36 | error[1] = last; 37 | hasSet = true; 38 | } 39 | } 40 | last = current.val; 41 | 42 | if (current.right != null) { 43 | stack.push(current.right); 44 | } 45 | current = current.right; 46 | } else { 47 | stack.push(current.left); 48 | current = current.left; 49 | } 50 | } 51 | 52 | return error; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarytree/FoldPaper.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarytree; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | /** 7 | * Created by brian on 16/11/16. 8 | * 9 | * 请把纸条竖着放在桌⼦上,然后从纸条的下边向上⽅对折,压出折痕后再展开。 10 | * 此时有1条折痕,突起的⽅向指向纸条的背⾯,这条折痕叫做“下”折痕 ; 11 | * 突起的⽅向指向纸条正⾯的折痕叫做“上”折痕。如果每次都从下边向上⽅ 对折,对折N次。请从上到下计算出所有折痕的⽅向。 12 | * 给定折的次数n,请返回从上到下的折痕的数组,若为下折痕则对应元素为"down",若为上折痕则为"up". 13 | * 14 | * 测试样例: 15 | * 1 16 | * 返回:["down"] 17 | */ 18 | public class FoldPaper { 19 | public String[] foldPaper(int n) { 20 | String[] res = new String[(1 << n) - 1]; 21 | Queue queue = new LinkedList(); 22 | 23 | fold(1, n, true, queue); 24 | 25 | for (int i = 0; i < (1 << n) - 1; i++) { 26 | res[i] = queue.poll(); 27 | } 28 | return res; 29 | } 30 | 31 | /** 32 | * 33 | * @param i 第几次折 34 | * @param n 一共折叠几次 35 | * @param down 折痕方向 36 | * @param queue 结果队列 37 | */ 38 | private void fold(int i, int n, boolean down, Queue queue) { 39 | if (i > n) { 40 | return; 41 | } 42 | fold(i + 1, n, true, queue); 43 | String s = down ? "down" : "up"; 44 | queue.add(s); 45 | fold(i + 1, n, false, queue); 46 | } 47 | 48 | public static void main(String[] args) { 49 | String[] res = new FoldPaper().foldPaper(3); 50 | for (String s : res) { 51 | System.out.print(s + " "); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarytree/LongestDistance.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarytree; 2 | 3 | /** 4 | * Created by brian on 16/11/16. 5 | * 6 | * 从二叉树的节点A出发,可以向上或者向下走,但沿途的节点只能经过一次, 7 | * 当到达节点B时,路径上的节点数叫作A到B的距离。 8 | * 对于给定的一棵二叉树,求整棵树上节点间的最大距离。 9 | * 给定一个二叉树的头结点root,请返回最大距离。保证点数大于等于2小于等于500. 10 | */ 11 | public class LongestDistance { 12 | public int findLongest(TreeNode root) { 13 | int[] info = find(root); 14 | return info[0]; 15 | } 16 | 17 | // info[0]:MaxLength; 18 | // info[1]:MaxToRoot; 19 | private int[] find(TreeNode root) { 20 | int[] info = new int[2]; 21 | if (root == null) { 22 | return info; 23 | } 24 | 25 | int[] left = find(root.left); 26 | int[] right = find(root.right); 27 | 28 | info[1] = Math.max(left[1], right[1]) + 1; 29 | int oneSide = Math.max(left[0], right[0]); 30 | int twoSides = left[1] + right[1] + 1; 31 | info[0] = Math.max(oneSide, twoSides); 32 | 33 | return info; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarytree/TreeNode.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarytree; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedList; 5 | 6 | /** 7 | * Created by brian on 16/11/15. 8 | * 9 | * 自定义的辅助类,用于快速创建测试用例 10 | */ 11 | public class TreeNode { 12 | int val = 0; 13 | TreeNode left = null; 14 | TreeNode right = null; 15 | 16 | public TreeNode(int val) { 17 | this.val = val; 18 | } 19 | 20 | public static TreeNode createTree(String[] sequence) { 21 | LinkedList list = new LinkedList(); 22 | list.addAll(Arrays.asList(sequence)); 23 | return create(list); 24 | } 25 | 26 | private static TreeNode create(LinkedList list) { 27 | if (list.isEmpty()) { 28 | return null; 29 | } 30 | String s = list.poll(); 31 | if (s.equals("#")) { 32 | return null; 33 | } 34 | 35 | TreeNode root = new TreeNode(Integer.parseInt(s)); 36 | root.left = create(list); 37 | root.right = create(list); 38 | 39 | return root; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/binarytree/TreeToString.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.binarytree; 2 | 3 | /** 4 | * Created by brian on 16/11/16. 5 | * 6 | * 首先我们介绍二叉树先序序列化的方式,假设序列化的结果字符串为str,初始时str等于空字符串。 7 | * 先序遍历二叉树,如果遇到空节点,就在str的末尾加上“#!”,“#”表示这个节点为空, 8 | * 节点值不存在,当然你也可以用其他的特殊字符,“!”表示一个值的结束。 9 | * 如果遇到不为空的节点,假设节点值为3,就在str的末尾加上“3!”。 10 | * 现在请你实现树的先序序列化。 11 | * 给定树的根结点root,请返回二叉树序列化后的字符串。 12 | */ 13 | public class TreeToString { 14 | public String toString(TreeNode root) { 15 | String seq = ""; 16 | return pre(root); 17 | } 18 | 19 | private String pre(TreeNode root) { 20 | if (root == null) { 21 | return "#!"; 22 | } 23 | 24 | String seq = root.val + "!"; 25 | seq += pre(root.left); 26 | seq += pre(root.right); 27 | 28 | return seq; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/bit/Compare.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.bit; 2 | 3 | /** 4 | * Created by brian on 16/11/18. 5 | * 6 | * 对于两个32位整数a和b,请设计一个算法返回a和b中较大的。但是不能用任何比较判断。 7 | * 若两数相同,返回任意一个。给定两个整数a和b,请返回较大的数。 8 | * 9 | * 测试样例: 10 | * 1,2 11 | * 返回:2 12 | */ 13 | public class Compare { 14 | public int getMax(int a, int b) { 15 | int sa = sign(a); 16 | int sb = sign(b); 17 | int sc = sign(a - b); 18 | 19 | int difsign = sa ^ sb; 20 | int samesign = flip(difsign); 21 | 22 | int ra = difsign * a + samesign * sc; 23 | int rb = flip(ra); 24 | 25 | return ra * a + rb * b; 26 | } 27 | 28 | private int sign(int num) { 29 | return flip((num >> 31) & 1); 30 | } 31 | 32 | private int flip(int i) { 33 | return i ^ 1; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/bit/OddAppearance.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.bit; 2 | 3 | /** 4 | * Created by brian on 16/11/18. 5 | * 6 | * 有一个整型数组A,其中只有一个数出现了奇数次,其他的数都出现了偶数次,请打印这个数。 7 | * 要求时间复杂度为O(N),额外空间复杂度为O(1)。 8 | * 给定整形数组A及它的大小n,请返回题目所求数字。 9 | * 10 | * 测试样例: 11 | * [1,2,3,2,1],5 12 | * 返回:3 13 | */ 14 | public class OddAppearance { 15 | public int findOdd(int[] A, int n) { 16 | if (A == null || n % 2 != 1) { 17 | throw new RuntimeException("error param"); 18 | } 19 | int base = 0; 20 | for (int i = 0; i < n; i++) { 21 | base = base ^ A[i]; 22 | } 23 | 24 | return base; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/bit/OddAppearance2.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.bit; 2 | 3 | /** 4 | * Created by brian on 16/11/18. 5 | * 6 | * 给定一个整型数组arr,其中有两个数出现了奇数次,其他的数都出现了偶数次,找到这两个数。 7 | * 要求时间复杂度为O(N),额外空间复杂度为O(1)。 8 | * 给定一个整形数组arr及它的大小n,请返回一个数组,其中两个元素为两个出现了奇数次的元素,请将他们按从小到大排列。 9 | * 10 | * 测试样例: 11 | * [1,2,4,4,2,1,3,5],8 12 | * 返回:[3,5] 13 | */ 14 | public class OddAppearance2 { 15 | public int[] findOdds(int[] arr, int n) { 16 | if (arr == null || n % 2 != 0) { 17 | throw new RuntimeException("error param"); 18 | } 19 | 20 | int base = 0; 21 | for (int i = 0; i < n; i++) { 22 | base = base ^ arr[i]; 23 | } 24 | int p = 0; 25 | while (((base >> p) & 1) != 1) { 26 | p++; 27 | } 28 | int one = 0; 29 | for (int i = 0; i < n; i++) { 30 | //if (((arr[i] >> p) & 1) != 0) { 31 | if (((1 << p) & arr[i]) != 0) { 32 | one = one ^ arr[i]; 33 | } 34 | } 35 | 36 | int two = one ^ base; 37 | 38 | return one < two ? new int[] {one, two} : new int[] {two, one}; 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/bit/Swap.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.bit; 2 | 3 | /** 4 | * Created by brian on 16/11/18. 5 | * 请编写一个算法,不用任何额外变量交换两个整数的值。 6 | * 给定一个数组num,其中包含两个值,请不用任何额外变量交换这两个值,并将交换后的数组返回。 7 | * 8 | * 测试样例: 9 | * [1,2] 10 | * 返回:[2,1] 11 | */ 12 | public class Swap { 13 | public int[] getSwap(int[] num) { 14 | if (num == null || num.length != 2) { 15 | return null; 16 | } 17 | 18 | num[0] = num[0] ^ num[1]; 19 | num[1] = num[0] ^ num[1]; 20 | num[0] = num[0] ^ num[1]; 21 | 22 | return num; 23 | } 24 | 25 | public static void main(String[] args) { 26 | int a = 2; 27 | 28 | System.out.println(a); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/dp/Backpack.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.dp; 2 | 3 | /** 4 | * Created by brian on 16/11/20. 5 | * 6 | * 一个背包有一定的承重cap,有N件物品,每件都有自己的价值,记录在数组v中, 7 | * 也都有自己的重量,记录在数组w中,每件物品只能选择要装入背包还是不装入背包, 8 | * 要求在不超过背包承重的前提下,选出物品的总价值最大。 9 | * 给定物品的重量w价值v及物品数n和承重cap。请返回最大总价值。 10 | * 11 | * 测试样例: 12 | * [1,2,3],[1,2,3],3,6 13 | * 返回:6 14 | */ 15 | public class Backpack { 16 | public int maxValue(int[] w, int[] v, int n, int cap) { 17 | int[] max = new int[cap + 1]; 18 | 19 | for (int i = 0; i < n; i++) { 20 | for (int j = cap; j >= w[i]; j--) { 21 | max[j] = Math.max(max[j], max[j - w[i]] + v[i]); 22 | } 23 | } 24 | 25 | return max[cap]; 26 | } 27 | } 28 | 29 | /** 30 | * 参考链接 31 | * 背包问题九讲:http://love-oriented.com/pack/Index.html 32 | * 01背包:http://love-oriented.com/pack/P01.html 33 | * 34 | * dp[i][j] 表示前 i 件物品达到不超过重量 j 时的最大价值 35 | * 36 | * 如果不放第i件物品,那么问题就转化为“前 i-1 件物品放入容量为 j 的背包中”; 37 | * 如果放第i件物品,那么问题就转化为“前 i-1 件物品放入剩下的容量为 j-w[i]的背包中” 38 | * 39 | * dp[i][j] = max{dp[i-1][j], dp[i-1][j-w[i]] + v[i] } 40 | */ -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/dp/Exchange.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.dp; 2 | 3 | /** 4 | * Created by brian on 16/11/20. 5 | * 6 | * 有数组penny,penny中所有的值都为正数且不重复。 7 | * 每个值代表一种面值的货币,每种面值的货币可以使用任意张, 8 | * 再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法。 9 | * 给定数组penny及它的大小(小于等于50),同时给定一个整数aim, 10 | * 请返回有多少种方法可以凑成aim。 11 | * 12 | * 测试样例: 13 | * [1,2,4],3,3 14 | * 返回:2 15 | */ 16 | public class Exchange { 17 | public int countWays(int[] penny, int n, int aim) { 18 | if (penny == null || aim < 0) { 19 | throw new RuntimeException("error param"); 20 | } 21 | int[] aims = new int[aim + 1]; 22 | aims[0] = 1; 23 | // f[i][j] = f[i][j-penny[i]]; 24 | // aims[j] = f[i-1][j] ---> aims[j] = f[i][j] 25 | for (int i = 0; i < n; i++) { 26 | for (int j = penny[i]; j <= aim; j++) { 27 | aims[j] = aims[j] + aims[j - penny[i]]; 28 | } 29 | } 30 | 31 | return aims[aim]; 32 | } 33 | } 34 | 35 | /* 36 | * 解题: 37 | * 38 | * f[i][j] 表示使用 penny[0]~penny[i] 来凑成钱数 j 的方法数 39 | * 则 第一行f[0][j] 表示使用 penny[0] 凑成钱数 j 的方法数 40 | * 第一列f[i][0] 表示使用 penny[0...i] 凑成钱数 0 的方法数,显然均为 1(即一张不拿) 41 | * 42 | * f[i][j] = f[i-1][j]+f[i-1][j-penny[i]]+f[i-1][j-2*penny[i]]+……+f[i-1][j-k*penny[i]] 43 | * 每次遍历上一行,依次取出使用 0,1,...2 张 penny[i] 后,使用penny[0]~penny[i-1]的方法数 44 | * 45 | * 从计算过程可知,有重复计算累加,简化可得 46 | * f[i][j] = f[i][j-penny[i]]+f[i-1][j] 47 | * 48 | * */ -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/dp/GoUpstairs.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.dp; 2 | 3 | /** 4 | * Created by brian on 16/11/20. 5 | * 6 | * 有n级台阶,一个人每次上一级或者两级,问有多少种走完n级台阶的方法。 7 | * 为了防止溢出,请将结果Mod 1000000007 8 | * 给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。 9 | * 10 | * 测试样例: 11 | * 1 12 | * 返回:1 13 | */ 14 | public class GoUpstairs { 15 | public int countWays(int n) { 16 | int pre = 1; 17 | int last = 2; 18 | if (n == 1 || n == 2) { 19 | return n; 20 | } 21 | int MOD = 1000000007; 22 | int res = 0; 23 | for (int i = 3; i <= n; i++) { 24 | res = (pre + last) % MOD; 25 | pre = last; 26 | last = res; 27 | } 28 | return res; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/dp/LCS.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.dp; 2 | 3 | /** 4 | * Created by brian on 16/11/20. 5 | * 6 | * 给定两个字符串A和B,返回两个字符串的最长公共子序列的长度。 7 | * 例如,A="1A2C3D4B56”,B="B1D23CA45B6A”,”123456"或者"12C4B6"都是最长公共子序列。 8 | * 给定两个字符串A和B,同时给定两个串的长度n和m,请返回最长公共子序列的长度。保证两串长度均小于等于300。 9 | * 10 | * 测试样例: 11 | * "1A2C3D4B56",10,"B1D23CA45B6A",12 12 | * 返回:6 13 | */ 14 | public class LCS { 15 | public int findLCS(String A, int n, String B, int m) { 16 | int[][] common = new int[n + 1][m + 1]; 17 | char[] a = A.toCharArray(); 18 | char[] b = B.toCharArray(); 19 | for (int i = 0; i < n; i++) { 20 | for (int j = 0; j < m; j++) { 21 | if (a[i] == b[j]) { 22 | common[i + 1][j + 1] = common[i][j] + 1; 23 | } else { 24 | common[i + 1][j + 1] = Math.max(common[i + 1][j], common[i][j + 1]); 25 | } 26 | } 27 | } 28 | return common[n][m]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/dp/LongestIncreasingSubsequence.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.dp; 2 | 3 | /** 4 | * Created by brian on 16/11/20. 5 | * 6 | * 这是一个经典的LIS(即最长上升子序列)问题, 7 | * 请设计一个尽量优的解法求出序列的最长上升子序列的长度。 8 | * 给定一个序列A及它的长度n(长度小于等于500),请返回LIS的长度。 9 | * 10 | * 测试样例: 11 | * [1,4,2,5,3],5 12 | * 返回:3 13 | */ 14 | public class LongestIncreasingSubsequence { 15 | public int getLIS(int[] A, int n) { 16 | int[] up = new int[n]; 17 | up[0] = 1; 18 | for (int i = 1; i < n; i++) { 19 | up[i] = 1; 20 | for (int j = 0; j < i; j++) { 21 | if (A[i] > A[j] && up[j] >= up[i]) { 22 | up[i] = up[j] + 1; 23 | } 24 | } 25 | } 26 | 27 | int max = 1; 28 | for (int i = 0; i < n; i++) { 29 | if (up[i] > max) { 30 | max = up[i]; 31 | } 32 | } 33 | return max; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/dp/MinCost.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.dp; 2 | 3 | /** 4 | * Created by brian on 16/11/20. 5 | * 6 | * 对于两个字符串A和B,我们需要进行插入、删除和修改操作将A串变为B串, 7 | * 定义c0,c1,c2分别为三种操作的代价,请设计一个高效算法, 8 | * 求出将A串变为B串所需要的最少代价。 9 | * 给定两个字符串A和B,及它们的长度和三种操作代价,请返回将A串变为B串所需要的最小代价。 10 | * 保证两串长度均小于等于300,且三种代价值均小于等于100。 11 | * 12 | * 测试样例: 13 | * "abc",3,"adc",3,5,3,100 14 | * 返回:8 15 | */ 16 | public class MinCost { 17 | public int findMinCost(String A, int n, String B, int m, int c0, int c1, int c2) { 18 | char[] a = A.toCharArray(); 19 | char[] b = B.toCharArray(); 20 | int[][] min = new int[n + 1][m + 1]; 21 | for (int i = 0; i <= n; i++) { 22 | min[i][0] = c1 * i; 23 | } 24 | for (int j = 0; j <= m; j++) { 25 | min[0][j] = c0 * j; 26 | } 27 | 28 | int tmp = 0; 29 | for (int i = 1; i <= n; i++) { 30 | for (int j = 1; j <= m; j++) { 31 | tmp = Math.min(min[i - 1][j] + c1, min[i][j - 1] + c0); 32 | if (a[i - 1] == b[j - 1]) { 33 | min[i][j] = Math.min(tmp, min[i - 1][j - 1]); 34 | } else { 35 | min[i][j] = Math.min(tmp, min[i - 1][j - 1] + c2); 36 | } 37 | } 38 | } 39 | 40 | return min[n][m]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/dp/MinimumPath.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.dp; 2 | 3 | /** 4 | * Created by brian on 16/11/20. 5 | * 6 | * 有一个矩阵map,它每个格子有一个权值。从左上角的格子开始每次只能向右或者向下走, 7 | * 最后到达右下角的位置,路径上所有的数字累加起来就是路径和,返回所有的路径中最小的路径和。 8 | * 给定一个矩阵map及它的行数n和列数m,请返回最小路径和。保证行列数均小于等于100. 9 | * 10 | * 测试样例: 11 | * [[1,2,3],[1,1,1]],2,3 12 | * 返回:4 13 | */ 14 | public class MinimumPath { 15 | public int getMin(int[][] map, int n, int m) { 16 | int[][] sum = new int[n][m]; 17 | sum[0][0] = map[0][0]; 18 | for (int i = 1; i < n; i++) { 19 | sum[i][0] = sum[i - 1][0] + map[i][0]; 20 | } 21 | for (int j = 1; j < m; j++) { 22 | sum[0][j] = sum[0][j - 1] + map[0][j]; 23 | } 24 | for (int i = 1; i < n; i++) { 25 | for (int j = 1; j < m; j++) { 26 | sum[i][j] = Math.min(sum[i][j - 1], sum[i - 1][j]) + map[i][j]; 27 | } 28 | } 29 | return sum[n - 1][m - 1]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/linkedlist/CheckIntersect.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.linkedlist; 2 | 3 | /** 4 | * Created by brian on 16/11/14. 5 | * 6 | * 现在有两个无环单链表,若两个链表的长度分别为m和n, 7 | * 请设计一个时间复杂度为O(n + m),额外空间复杂度为O(1)的算法,判断这两个链表是否相交。 8 | * 给定两个链表的头结点headA和headB,请返回一个bool值,代表这两个链表是否相交。 9 | * 保证两个链表长度小于等于500。 10 | */ 11 | public class CheckIntersect { 12 | public boolean chkIntersect(ListNode headA, ListNode headB) { 13 | if (headA == null || headB == null) { 14 | return false; 15 | } 16 | 17 | ListNode a = headA; 18 | ListNode b = headB; 19 | int m = 0; 20 | int n = 0; 21 | while (a != null) { 22 | a = a.next; 23 | m++; 24 | } 25 | while (b != null) { 26 | b = b.next; 27 | n++; 28 | } 29 | 30 | a = headA; 31 | b = headB; 32 | if (m >= n) { 33 | for (int i = 0; i < m - n; i++) { 34 | a = a.next; 35 | } 36 | } else { 37 | for (int i = 0; i < n - m; i++) { 38 | b = b.next; 39 | } 40 | } 41 | 42 | while (a != null) { 43 | if (a == b) { 44 | return true; 45 | } 46 | a = a.next; 47 | b = b.next; 48 | } 49 | 50 | return false; 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/linkedlist/ChkIntersection.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.linkedlist; 2 | 3 | /** 4 | * Created by brian on 16/11/14. 5 | * 6 | * 如何判断两个有环单链表是否相交?相交的话返回第一个相交的节点,不想交的话返回空。 7 | * 如果两个链表长度分别为N和M,请做到时间复杂度O(N+M),额外空间复杂度O(1)。 8 | * 给定两个链表的头结点head1和head2(注意,另外两个参数adjust0和adjust1用于调整数据,与本题求解无关)。 9 | * 请返回一个bool值代表它们是否相交。 10 | */ 11 | public class ChkIntersection { 12 | public boolean chkInter(ListNode head1, ListNode head2, int adjust0, int adjust1) { 13 | ListNode node1 = chkLoop(head1); 14 | ListNode node2 = chkLoop(head2); 15 | 16 | if (node1 == null || node2 == null) { 17 | return false; 18 | } 19 | 20 | if (node1 == node2) { 21 | return true; 22 | } 23 | 24 | ListNode current = node1.next; 25 | while (current != node1) { 26 | if (current == node2) { 27 | return true; 28 | } 29 | current = current.next; 30 | } 31 | 32 | return false; 33 | 34 | } 35 | 36 | private ListNode chkLoop(ListNode head) { 37 | if (head == null) { 38 | return null; 39 | } 40 | 41 | ListNode slow = head; 42 | ListNode fast = head; 43 | while (fast.next != null && fast.next.next != null) { 44 | slow = slow.next; 45 | fast = fast.next.next; 46 | if (slow == fast) { 47 | break; 48 | } 49 | } 50 | if (fast == slow) { 51 | slow = head; 52 | while (fast != slow) { 53 | fast = fast.next; 54 | slow = slow.next; 55 | } 56 | return slow; 57 | } 58 | 59 | return null; 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/linkedlist/ChkLoop.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.linkedlist; 2 | 3 | /** 4 | * Created by brian on 16/11/14. 5 | * 6 | * 如何判断一个单链表是否有环? 7 | * 有环的话返回进入环的第一个节点的值,无环的话返回-1。 8 | * 如果链表的长度为N,请做到时间复杂度O(N),额外空间复杂度O(1)。 9 | * 10 | * 给定一个单链表的头结点head(注意另一个参数adjust为加密后的数据调整参数, 11 | * 方便数据设置,与本题求解无关),请返回所求值。 12 | * 13 | * 参考: 14 | * http://blog.csdn.net/wuzhekai1985/article/details/6725263 15 | * http://blog.sina.com.cn/s/blog_6a0e04380101a9o2.html 16 | */ 17 | public class ChkLoop { 18 | public int chkLoop(ListNode head, int adjust) { 19 | if (head == null) { 20 | return -1; 21 | } 22 | 23 | ListNode slow = head; 24 | ListNode fast = head; 25 | while (fast.next != null && fast.next.next != null) { 26 | slow = slow.next; 27 | fast = fast.next.next; 28 | if (slow == fast) { 29 | break; 30 | } 31 | } 32 | if (fast == slow) { 33 | slow = head; 34 | while (fast != slow) { 35 | fast = fast.next; 36 | slow = slow.next; 37 | } 38 | return slow.val; 39 | } 40 | 41 | return -1; 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/linkedlist/ClearValue.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.linkedlist; 2 | 3 | /** 4 | * Created by brian on 16/11/12. 5 | * 6 | * 现在有一个单链表。链表中每个节点保存一个整数,再给定一个值val,把所有等于val的节点删掉。 7 | * 给定一个单链表的头结点head,同时给定一个值val,请返回清除后的链表的头结点,保证链表中有不等于该值的其它值。请保证其他元素的相对顺序。 8 | * 9 | * 测试样例: 10 | * {1,2,3,4,3,2,1},2 11 | * {1,3,4,3,1} 12 | */ 13 | public class ClearValue { 14 | public ListNode clear(ListNode head, int val) { 15 | ListNode newHead = head; 16 | while (newHead != null) { 17 | if (newHead.val != val) { 18 | break; 19 | } 20 | newHead = newHead.next; 21 | } 22 | 23 | ListNode current = newHead; 24 | ListNode pre = newHead; 25 | while (current != null) { 26 | if (current.val == val) { 27 | pre.next = current.next; 28 | } else { 29 | pre = current; 30 | } 31 | current = current.next; 32 | } 33 | 34 | return newHead; 35 | } 36 | 37 | public static void main(String[] args) { 38 | int[] a = {1, 2, 3, 4, 3, 2, 1}; 39 | ListNode head = ListNode.createList(a); 40 | ClearValue cv = new ClearValue(); 41 | ListNode newHead = cv.clear(head, 2); 42 | ListNode.print(newHead); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/linkedlist/Common.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.linkedlist; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * Created by brian on 16/11/11. 7 | * 8 | * 现有两个升序链表,且链表中均无重复元素。请设计一个高效的算法,打印两个链表的公共值部分。 9 | * 给定两个链表的头指针headA和headB,请返回一个vector,元素为两个链表的公共部分。 10 | * 请保证返回数组的升序。两个链表的元素个数均小于等于500。保证一定有公共值 11 | * 12 | * 测试样例: 13 | * {1,2,3,4,5,6,7},{2,4,6,8,10} 14 | * 返回:[2.4.6] 15 | */ 16 | public class Common { 17 | 18 | public int[] findCommonParts(ListNode headA, ListNode headB) { 19 | if (headA == null || headB == null) { 20 | return null; 21 | } 22 | LinkedList list = new LinkedList(); 23 | while (headA != null && headB != null) { 24 | if (headA.val < headB.val) { 25 | headA = headA.next; 26 | } else if (headB.val < headA.val) { 27 | headB = headB.next; 28 | } else { 29 | list.add(headA.val); 30 | headA = headA.next; 31 | headB = headB.next; 32 | } 33 | } 34 | 35 | int[] res = new int[list.size()]; 36 | int i = 0; 37 | for (int val : list) { 38 | res[i++] = val; 39 | } 40 | 41 | return res; 42 | // for(int i =0;i toArrayList(ListNode head) { 27 | ArrayList arrayList = new ArrayList(); 28 | while (head != null) { 29 | //System.out.print(head.val+","); 30 | arrayList.add(head.val); 31 | head = head.next; 32 | } 33 | return arrayList; 34 | } 35 | 36 | public static int[] toArray(ListNode head) { 37 | ArrayList arrayList = toArrayList(head); 38 | int[] arr = new int[arrayList.size()]; 39 | for (int i = 0; i < arrayList.size(); i++) { 40 | arr[i] = arrayList.get(i); 41 | } 42 | return arr; 43 | } 44 | 45 | public static void print(ListNode head) { 46 | ArrayList array = toArrayList(head); 47 | for (int i : array) { 48 | System.out.print(i + ","); 49 | } 50 | System.out.println(); 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/linkedlist/Remove.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.linkedlist; 2 | 3 | /** 4 | * Created by brian on 16/11/10. 5 | * 6 | * 实现一个算法,删除单向链表中间的某个结点,假定你只能访问该结点。 7 | * 给定待删除的节点,请执行删除操作,若该节点为尾节点,返回false,否则返回true 8 | */ 9 | public class Remove { 10 | public boolean removeNode(ListNode pNode) { 11 | if (pNode == null || pNode.next == null) { 12 | return false; 13 | } 14 | 15 | ListNode next = pNode.next; 16 | 17 | pNode.val = next.val; 18 | pNode.next = next.next; 19 | return true; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/3. 5 | * 6 | * 冒泡排序 7 | */ 8 | 9 | public class BubbleSort { 10 | public int[] bubbleSort(int[] A, int n) { 11 | if (n == 0 || A == null) { 12 | return null; 13 | } 14 | for (int i = 0; i < n; i++) { 15 | for (int j = 0; j < n - 1 - i; j++) { 16 | if (A[j] > A[j + 1]) { 17 | swap(A, j, j + 1); 18 | } 19 | } 20 | } 21 | return A; 22 | } 23 | 24 | private void swap(int[] a, int i, int j) { 25 | int tmp = a[i]; 26 | a[i] = a[j]; 27 | a[j] = tmp; 28 | } 29 | } -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/Checker.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * Created by brian on 16/11/7. 7 | * 8 | * 请设计一个高效算法,判断数组中是否有重复值。 9 | * 必须保证额外空间复杂度为O(1)。 10 | * 给定一个int数组A及它的大小n,请返回它是否有重复值。 11 | */ 12 | public class Checker { 13 | 14 | public boolean checkDuplicate(int[] a, int n) { 15 | if (a == null || n == 0) { 16 | return false; 17 | } 18 | 19 | Arrays.sort(a); 20 | for (int i = 1; i < n; i++) { 21 | if (a[i] == a[i - 1]) { 22 | return true; 23 | } 24 | } 25 | return false; 26 | } 27 | 28 | public static void main(String[] args) { 29 | int[] a = {2, 1, 4, 3, 6, 5, 8, 7, 10, 9}; 30 | boolean b = new Checker().checkDuplicate(a, 10); 31 | System.out.println(b); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/CountingSort.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/4. 5 | * 6 | * 计数排序 7 | */ 8 | public class CountingSort { 9 | public int[] countingSort(int[] A, int n) { 10 | if (A == null || n == 0) { 11 | return null; 12 | } 13 | 14 | int min = A[0]; 15 | int max = A[0]; 16 | for (int i = 0; i < n; i++) { 17 | min = Math.min(min, A[i]); 18 | max = Math.max(max, A[i]); 19 | } 20 | 21 | int[] bucket = new int[max - min + 1]; 22 | for (int i = 0; i < n; i++) { 23 | bucket[A[i] - min]++; 24 | } 25 | int i = 0; 26 | for (int j = 0; j <= max - min; j++) { 27 | for (int count = bucket[j]; count > 0; count--) { 28 | A[i++] = j + min; 29 | } 30 | } 31 | 32 | return A; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/Finder.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/7. 5 | * 6 | * 现在有一个行和列都排好序的矩阵,请设计一个高效算法,快速查找矩阵中是否含有值x。 7 | * 给定一个int矩阵mat,同时给定矩阵大小nxm及待查找的数x, 8 | * 请返回一个bool值,代表矩阵中是否存在x。 9 | * 所有矩阵中数字及x均为int范围内整数。保证n和m均小于等于1000。 10 | */ 11 | public class Finder { 12 | public boolean findX(int[][] mat, int n, int m, int x) { 13 | int i = 0; 14 | int j = m - 1; 15 | while (i < n && j >= 0) { 16 | if (mat[i][j] == x) { 17 | return true; 18 | } else if (mat[i][j] > x) { 19 | j--; 20 | } else { 21 | i++; 22 | } 23 | } 24 | return false; 25 | } 26 | 27 | public static void main(String[] args) { 28 | int [][]a ={{1,2,3},{4,5,6},{7,8,9}}; 29 | Finder f = new Finder(); 30 | boolean b = f.findX(a,3,3,10); 31 | System.out.println(b); 32 | b = f.findX(a,3,3,5); 33 | System.out.println(b); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/HeapSort.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/4. 5 | * 6 | * 堆排序 7 | */ 8 | public class HeapSort { 9 | public int[] heapSort(int[] A, int n) { 10 | if (A == null || n == 0) { 11 | return null; 12 | } 13 | for (int i = n / 2 - 1; i >= 0; i--) { 14 | sink(A, i, n); 15 | } 16 | int last = n - 1; 17 | while (last > 0) { 18 | swap(A, 0, last--); 19 | sink(A, 0, last + 1); 20 | } 21 | return A; 22 | } 23 | 24 | public void sink(int[] a, int i, int len) { 25 | while (2 * (i + 1) - 1 < len) { 26 | int child = 2 * (i + 1) - 1; 27 | if (child < len - 1 && a[child] < a[child + 1]) { 28 | child++; 29 | } 30 | if (a[i] >= a[child]) { 31 | break; 32 | } 33 | 34 | swap(a, i, child); 35 | i = child; 36 | } 37 | } 38 | 39 | private void swap(int[] a, int i, int j) { 40 | int tmp = a[i]; 41 | a[i] = a[j]; 42 | a[j] = tmp; 43 | } 44 | 45 | public static void main(String[] args) { 46 | int[] a = {54, 35, 48, 36, 27, 12, 44, 44, 8, 14, 26, 17, 28}; 47 | int[] b = new HeapSort().heapSort(a, 13); 48 | for (int i : b) { 49 | System.out.print(i + ","); 50 | } 51 | System.out.println(); 52 | 53 | int[] c = {32, 103, 24, 88, 95, 70, 97, 15, 102, 6, 79, 46, 51, 37, 93, 108, 9, 58, 53, 58, 79, 36, 58, 91, 78, 58, 61, 81}; 54 | for (int i : new HeapSort().heapSort(c, 28)) { 55 | System.out.print(i + ","); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/InsertionSort.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/3. 5 | * 6 | * 插入排序 7 | */ 8 | public class InsertionSort { 9 | public int[] insertionSort(int[] A, int n) { 10 | if (n == 0 || A == null) { 11 | return null; 12 | } 13 | for (int i = 0; i < n - 1; i++) { 14 | for (int j = i + 1; j > 0 && A[j - 1] > A[j]; j--) { 15 | swap(A, j, j - 1); 16 | } 17 | // 打印中间态 18 | // for (int ii : A) { 19 | // System.out.print(ii + ","); 20 | // } 21 | // System.out.println(); 22 | } 23 | return A; 24 | } 25 | 26 | private void swap(int[] a, int i, int j) { 27 | int tmp = a[i]; 28 | a[i] = a[j]; 29 | a[j] = tmp; 30 | } 31 | 32 | public static void main(String[] args) { 33 | int[] a = {54, 35, 48, 36, 27, 12, 44, 44, 8, 14, 26, 17, 28}; 34 | int[] b = new InsertionSort().insertionSort(a, a.length); 35 | for (int i : b) { 36 | System.out.print(i + ","); 37 | } 38 | System.out.println(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/Merge.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/7. 5 | * 6 | * 有两个从小到大排序以后的数组A和B,其中A的末端有足够的缓冲空容纳B。 7 | * 请编写一个方法,将B合并入A并排序。 8 | * 给定两个有序int数组A和B,A中的缓冲空用0填充, 9 | * 同时给定A和B的真实大小int n和int m,请返回合并后的数组。 10 | */ 11 | public class Merge { 12 | public int[] mergeAB(int[] A, int[] B, int n, int m) { 13 | for (int i = m + n - 1; i >= 0; i--) { 14 | if (m == 0) { 15 | break; 16 | } 17 | if (n > 0 && A[n - 1] > B[m - 1]) { 18 | A[i] = A[n - 1]; 19 | n--; 20 | } else { 21 | A[i] = B[m - 1]; 22 | m--; 23 | } 24 | } 25 | return A; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/MergeSort.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/3. 5 | * 6 | * 归并排序 7 | */ 8 | public class MergeSort { 9 | public int[] mergeSort(int[] A, int n) { 10 | if (n == 0 || A == null) { 11 | return null; 12 | } 13 | int[] help = new int[n]; 14 | int end; 15 | for (int size = 1; size < n; size = size * 2) { 16 | for (int i = 0; i + size < n; i = i + 2 * size) { 17 | end = Math.min(n, i + 2 * size); 18 | merge(A, help, i, i + size, end); 19 | } 20 | } 21 | return A; 22 | } 23 | 24 | private void merge(int[] a, int[] help, int lo, int mid, int hi) { 25 | for (int i = lo; i < hi; i++) { 26 | help[i] = a[i]; 27 | } 28 | int left = lo; 29 | int right = mid; 30 | for (int i = lo; i < hi; i++) { 31 | if (left == mid) { 32 | a[i] = help[right++]; 33 | } else if (right == hi) { 34 | a[i] = help[left++]; 35 | } else if (help[right] < help[left]) { 36 | a[i] = help[right++]; 37 | } else { 38 | a[i] = help[left++]; 39 | } 40 | } 41 | } 42 | 43 | public static void main(String[] args) { 44 | int[] a = {3, 6, 7, 2, 1, 8, 9}; 45 | int[] sort = new MergeSort().mergeSort(a, a.length); 46 | for (int i : sort) { 47 | System.out.print(i + ","); 48 | } 49 | System.out.println(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/RadixSort.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/4. 5 | * 6 | * 基数排序 7 | * 保证元素均小于等于2000 8 | */ 9 | public class RadixSort { 10 | private int[] radix = {1, 10, 100, 1000}; 11 | 12 | public int[] radixSort(int[] A, int n) { 13 | if (A == null || n == 0) { 14 | return null; 15 | } 16 | int total = radix.length; 17 | int[][] bucket = new int[10][n]; 18 | int[] count = new int[10]; 19 | int number = 0; 20 | 21 | for (int position = 0; position < total; position++) { 22 | for (int i = 0; i < n; i++) { 23 | number = getNumber(A[i], position); 24 | bucket[number][count[number]++] = A[i]; 25 | } 26 | int i = n - 1; 27 | for (int k = 9; k >= 0; k--) { 28 | while (count[k] > 0) { 29 | A[i--] = bucket[k][--count[k]]; 30 | } 31 | 32 | } 33 | } 34 | return A; 35 | } 36 | 37 | private int getNumber(int num, int i) { 38 | num = num / radix[i]; 39 | return num % 10; 40 | } 41 | 42 | public static void main(String[] args) { 43 | int[] a = {1023, 345, 1678, 478, 432, 98, 10, 29, 5}; 44 | int[] b = new RadixSort().radixSort(a, a.length); 45 | for (int i : b) { 46 | System.out.print(i + ","); 47 | } 48 | System.out.println(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/SelectionSort.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/3. 5 | * 6 | * 选择排序 7 | */ 8 | 9 | public class SelectionSort { 10 | public int[] selectionSort(int[] A, int n) { 11 | if (n == 0 || A == null) { 12 | return null; 13 | } 14 | int min = 0; 15 | for (int i = 0; i < n; i++) { 16 | min = i; 17 | for (int j = i; j < n; j++) { 18 | if (A[j] < A[min]) { 19 | min = j; 20 | } 21 | } 22 | swap(A, min, i); 23 | } 24 | 25 | return A; 26 | } 27 | 28 | private void swap(int[] a, int i, int j) { 29 | int tmp = a[i]; 30 | a[i] = a[j]; 31 | a[j] = tmp; 32 | } 33 | } -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/ShellSort.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/4. 5 | * 6 | * 希尔排序 7 | */ 8 | public class ShellSort { 9 | public int[] shellSort(int[] A, int n) { 10 | if (A == null || n == 0) { 11 | return null; 12 | } 13 | int h = 1; 14 | while (h < n / 3) h = 3 * h + 1; 15 | 16 | while (h >= 1) { 17 | for (int i = h; i < n; i++) { 18 | for (int j = i; j >= h && A[j] < A[j - h]; j -= h) { 19 | swap(A, j, j - h); 20 | } 21 | // for (int x : A) { 22 | // System.out.print(x + ","); 23 | // } 24 | // System.out.println(); 25 | } 26 | 27 | h = h / 3; 28 | } 29 | return A; 30 | 31 | } 32 | 33 | private void swap(int[] a, int i, int j) { 34 | int tmp = a[i]; 35 | a[i] = a[j]; 36 | a[j] = tmp; 37 | } 38 | 39 | public static void main(String[] args) { 40 | int[] a = {54, 35, 48, 36, 27, 12, 44, 44, 8, 14, 26, 17, 28}; 41 | int[] b = new ShellSort().shellSort(a, 13); 42 | for (int i : b) { 43 | System.out.print(i + ","); 44 | } 45 | System.out.println(); 46 | 47 | int[] c = {32, 103, 24, 88, 95, 70, 97, 15, 102, 6, 79, 46, 51, 37, 93, 108, 9, 58, 53, 58, 79, 36, 58, 91, 78, 58, 61, 81}; 48 | for (int i : new ShellSort().shellSort(c, 28)) { 49 | System.out.print(i + ","); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/Subsequence.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/7. 5 | * 6 | * 对于一个数组,请设计一个高效算法计算需要排序的最短子数组的长度。 7 | * 给定一个int数组A和数组的大小n,请返回一个二元组,代表所求序列的长度。 8 | * (原序列位置从0开始标号,若原序列有序,返回0)。保证A中元素均为正整数。 9 | */ 10 | public class Subsequence { 11 | public int shortestSubsequence(int[] A, int n) { 12 | if (A == null || n == 0) { 13 | return 0; 14 | } 15 | int max = A[0]; 16 | int min = A[n - 1]; 17 | int right = 0; 18 | int left = n - 1; 19 | 20 | for (int i = 0; i < n; i++) { 21 | if (A[i] >= max) { 22 | max = A[i]; 23 | } else { 24 | right = i; 25 | } 26 | } 27 | 28 | for (int i = n - 1; i >= 0; i--) { 29 | if (A[i] <= min) { 30 | min = A[i]; 31 | } else { 32 | left = i; 33 | } 34 | } 35 | 36 | // System.out.println("right:" + right); 37 | // System.out.println("left:" + left); 38 | if (right > left) { 39 | return right - left + 1; 40 | } else { 41 | return 0; 42 | } 43 | } 44 | 45 | public static void main(String[] args) { 46 | //int[] a = {1, 4, 6, 5, 9, 10}; 47 | int []a = {1,4,2,3}; 48 | int b = new Subsequence().shortestSubsequence(a, a.length); 49 | System.out.println(b); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/sort/ThreeColor.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.sort; 2 | 3 | /** 4 | * Created by brian on 16/11/7. 5 | * 6 | * 荷兰旗问题 7 | * 8 | * 有一个只由0,1,2三种元素构成的整数数组,请使用交换、原地排序而不是使用计数进行排序。 9 | * 给定一个只含0,1,2的整数数组A及它的大小,请返回排序后的数组。保证数组大小小于等于500。 10 | */ 11 | public class ThreeColor { 12 | public int[] sortThreeColor(int[] A, int n) { 13 | if (A == null || n == 0) { 14 | return null; 15 | } 16 | 17 | int lo = -1; 18 | int hi = n; 19 | int mid = 0; 20 | while (mid < hi) { 21 | if (A[mid] < 1) { 22 | swap(A, ++lo, mid++); 23 | } else if (A[mid] > 1) { 24 | swap(A, --hi, mid); 25 | } else { 26 | mid++; 27 | } 28 | 29 | } 30 | 31 | return A; 32 | } 33 | 34 | private void swap(int[] a, int i, int j) { 35 | int tmp = a[i]; 36 | a[i] = a[j]; 37 | a[j] = tmp; 38 | } 39 | 40 | public static void main(String[] args) { 41 | int[] a = {0, 1, 1, 0, 2, 2}; 42 | int[] b = new ThreeColor().sortThreeColor(a, 6); 43 | for (int i : b) { 44 | System.out.print(i + ","); 45 | } 46 | System.out.println(); 47 | int[] c = {1, 2, 0, 2}; 48 | int[] d = new ThreeColor().sortThreeColor(c, 4); 49 | for (int i : d) { 50 | System.out.print(i + ","); 51 | } 52 | System.out.println(); 53 | int[] e = {2, 2, 0, 2, 0}; 54 | int[] f = new ThreeColor().sortThreeColor(e, 5); 55 | for (int i : f) { 56 | System.out.print(i + ","); 57 | } 58 | System.out.println(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/stack/MaxTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.stack; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * Created by brian on 16/11/9. 7 | * 8 | * 对于一个没有重复元素的整数数组,请用其中元素构造一棵MaxTree, 9 | * MaxTree定义为一棵二叉树,其中的节点与数组元素一一对应, 10 | * 同时对于MaxTree的每棵子树,它的根的元素值为子树的最大值。 11 | * 现有一建树方法,对于数组中的每个元素, 12 | * 其在树中的父亲为数组中它左边比它大的第一个数和右边比它大的第一个数中更小的一个。 13 | * 若两边都不存在比它大的数,那么它就是树根。请设计O(n)的算法实现这个方法。 14 | * 给定一个无重复元素的数组A和它的大小n,请返回一个数组, 15 | * 其中每个元素为原数组中对应位置元素在树中的父亲节点的编号,若为根则值为-1。 16 | * 17 | * 测试样例: 18 | * [3,1,4,2],4 19 | * 返回:[2,0,-1,2] 20 | */ 21 | public class MaxTree { 22 | public int[] buildMaxTree(int[] A, int n) { 23 | if (A == null || n == 0) { 24 | return null; 25 | } 26 | 27 | int[] res = new int[n]; 28 | Stack stack = new Stack(); 29 | 30 | for (int i = 0; i < n; i++) { 31 | while (!stack.isEmpty() && A[stack.peek()] < A[i]) { 32 | int current = stack.pop(); 33 | if (stack.isEmpty() || A[stack.peek()] > A[i]) { 34 | res[current] = i; 35 | } else { 36 | res[current] = stack.peek(); 37 | } 38 | } 39 | 40 | if (stack.isEmpty()) { 41 | res[i] = -1; 42 | } else { 43 | res[i] = stack.peek(); 44 | } 45 | stack.push(i); 46 | 47 | } 48 | 49 | return res; 50 | 51 | } 52 | 53 | public static void main(String[] args) { 54 | MaxTree mt = new MaxTree(); 55 | int[] a = {3, 1, 4, 2}; 56 | int[] b = mt.buildMaxTree(a, a.length); 57 | for (int i : b) { 58 | System.out.print(i + ","); 59 | } 60 | System.out.println(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/stack/SlideWindow.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.stack; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * Created by brian on 16/11/9. 7 | * 8 | * 有一个整型数组 arr 和一个大小为 w 的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置。 9 | * 返回一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。 10 | * 以数组为[4,3,5,4,3,3,6,7],w=3为例。 11 | * 因为第一个窗口[4,3,5]的最大值为5,第二个窗口[3,5,4]的最大值为5, 12 | * 第三个窗口[5,4,3]的最大值为5。第四个窗口[4,3,3]的最大值为4。 13 | * 第五个窗口[3,3,6]的最大值为6。第六个窗口[3,6,7]的最大值为7。 14 | * 所以最终返回[5,5,5,4,6,7]。 15 | * 给定整形数组arr及它的大小n,同时给定w,请返回res数组。 16 | * 保证w小于等于n,同时保证数组大小小于等于500。 17 | * 18 | * 测试样例: 19 | * [4,3,5,4,3,3,6,7],8,3 20 | * 返回:[5,5,5,4,6,7] 21 | */ 22 | public class SlideWindow { 23 | 24 | public int[] slide(int[] arr, int n, int w) { 25 | if (arr == null || n < w || w == 0) { 26 | return null; 27 | } 28 | 29 | LinkedList deque = new LinkedList(); 30 | 31 | int[] max = new int[n - w + 1]; 32 | for (int i = 0; i < n; i++) { 33 | while (!deque.isEmpty() && arr[deque.getLast()] < arr[i]) { 34 | deque.removeLast(); 35 | } 36 | deque.addLast(i); 37 | 38 | if (deque.getFirst() < i - w + 1) { 39 | deque.removeFirst(); 40 | } 41 | 42 | if (i >= w - 1) { 43 | max[i - w + 1] = arr[deque.getFirst()]; 44 | } 45 | } 46 | return max; 47 | 48 | } 49 | 50 | public static void main(String[] args) { 51 | SlideWindow sw = new SlideWindow(); 52 | int[] a = {4, 3, 5, 4, 3, 3, 6, 7}; 53 | int[] b = sw.slide(a, a.length, 3); 54 | for (int i : b) { 55 | System.out.print(i + ","); 56 | } 57 | System.out.println(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/stack/StackMin.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.stack; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * Created by brian on 16/11/9. 7 | * 8 | * 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。 9 | */ 10 | public class StackMin { 11 | 12 | private Stack stackData = new Stack(); 13 | private Stack stackMin = new Stack(); 14 | 15 | public void push(int node) { 16 | stackData.push(node); 17 | if (stackMin.isEmpty() || stackMin.peek() >= node) { 18 | stackMin.push(node); 19 | } 20 | } 21 | 22 | public void pop() { 23 | if (stackData.isEmpty()) { 24 | throw new RuntimeException("stackData is empty!"); 25 | } 26 | 27 | if (stackData.peek() == stackMin.peek()) { 28 | stackMin.pop(); 29 | } 30 | 31 | stackData.pop(); 32 | } 33 | 34 | public int top() { 35 | if (stackData.isEmpty()) { 36 | throw new RuntimeException("stackData is empty!"); 37 | } 38 | 39 | return stackData.peek(); 40 | } 41 | 42 | public int min() { 43 | if (stackMin.isEmpty()) { 44 | throw new RuntimeException("stackMin is empty!"); 45 | } 46 | 47 | return stackMin.peek(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/stack/StackReverse.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.stack; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * Created by brian on 16/11/9. 7 | * 8 | * 实现一个栈的逆序,但是只能用递归函数和这个栈本身的pop操作来实现, 9 | * 而不能自己申请另外的数据结构。 10 | * 给定一个整数数组A即为给定的栈,同时给定它的大小n,请返回逆序后的栈。 11 | * 12 | * 测试样例: 13 | * [4,3,2,1],4 14 | * 返回:[1,2,3,4] 15 | */ 16 | public class StackReverse { 17 | public int[] reverseStack(int[] A, int n) { 18 | if (A == null || n == 0) { 19 | return null; 20 | } 21 | 22 | Stack stack = new Stack(); 23 | 24 | for (int i = n - 1; i >= 0; i--) { 25 | stack.push(A[i]); 26 | } 27 | 28 | reverse(stack); 29 | 30 | int i = 0; 31 | int[] res = new int[n]; 32 | while (!stack.isEmpty()) { 33 | res[i++] = stack.pop(); 34 | } 35 | return res; 36 | 37 | } 38 | 39 | /** 40 | * 取出栈底元素 41 | */ 42 | private int get(Stack stack) { 43 | int current = stack.pop(); 44 | if (stack.isEmpty()) { 45 | return current; 46 | } else { 47 | int last = get(stack); 48 | stack.push(current); 49 | return last; 50 | } 51 | } 52 | 53 | private void reverse(Stack stack) { 54 | if (stack.isEmpty()) { 55 | return; 56 | } 57 | int bottom = get(stack); 58 | reverse(stack); 59 | stack.push(bottom); 60 | } 61 | 62 | public static void main(String[] args) { 63 | StackReverse sr = new StackReverse(); 64 | int[] a = {1, 2, 3, 4}; 65 | int[] b = sr.reverseStack(a, a.length); 66 | for (int i : b) { 67 | System.out.print(i + ","); 68 | } 69 | System.out.println(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/stack/TwoStack.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.stack; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * Created by brian on 16/11/9. 7 | * 8 | * 编写一个类,只能用两个栈结构实现队列,支持队列的基本操作(push,pop)。 9 | * 给定一个操作序列ope及它的长度n,其中元素为正数代表push操作, 10 | * 为0代表pop操作,保证操作序列合法且一定含pop操作,请返回pop的结果序列。 11 | * 12 | * 测试样例: 13 | * [1,2,3,0,4,0],6 14 | * 返回:[1,2] 15 | */ 16 | public class TwoStack { 17 | 18 | public int[] twoStack(int[] ope, int n) { 19 | if (ope == null || n == 0) { 20 | return null; 21 | } 22 | 23 | Stack data = new Stack(); 24 | Stack help = new Stack(); 25 | 26 | int popCounts = 0; 27 | for (int i = 0; i < n; i++) { 28 | if (ope[i] > 0) { 29 | data.push(ope[i]); 30 | } else { 31 | popCounts++; 32 | } 33 | } 34 | 35 | while (!data.isEmpty()) { 36 | help.push(data.pop()); 37 | } 38 | 39 | int[] res = new int[popCounts]; 40 | int i = 0; 41 | while (popCounts-- > 0) { 42 | res[i++] = help.pop(); 43 | } 44 | 45 | return res; 46 | 47 | } 48 | 49 | public static void main(String[] args) { 50 | TwoStack ts = new TwoStack(); 51 | int[] a = {1, 2, 3, 0, 4, 0}; 52 | int[] b = ts.twoStack(a, a.length); 53 | for (int i : b) { 54 | System.out.print(i + ","); 55 | } 56 | System.out.println(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/stack/TwoStacks.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.stack; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Stack; 5 | 6 | /** 7 | * Created by brian on 16/11/9. 8 | * 9 | * 请编写一个程序,按升序对栈进行排序(即最大元素位于栈顶), 10 | * 要求最多只能使用一个额外的栈存放临时数据,但不得将元素复制到别的数据结构中。 11 | * 给定一个int[] numbers(C++中为vector),其中第一个元素为栈顶, 12 | * 请返回排序后的栈。请注意这是一个栈,意味着排序过程中你只能访问到第一个元素。 13 | * 14 | * 测试样例: 15 | * [1,2,3,4,5] 16 | * 返回:[5,4,3,2,1] 17 | */ 18 | public class TwoStacks { 19 | public ArrayList twoStacksSort(int[] numbers) { 20 | if (numbers == null || numbers.length == 0) { 21 | return null; 22 | } 23 | 24 | Stack stack = new Stack(); 25 | 26 | for (int i = numbers.length - 1; i >= 0; i--) { 27 | stack.push(numbers[i]); 28 | } 29 | 30 | ArrayList res = new ArrayList(); 31 | Stack help = new Stack(); 32 | 33 | while (!stack.isEmpty()) { 34 | int current = stack.pop(); 35 | while (!help.isEmpty() && help.peek() > current) { 36 | stack.push(help.pop()); 37 | } 38 | help.push(current); 39 | } 40 | 41 | while (!help.isEmpty()) { 42 | res.add(help.pop()); 43 | } 44 | return res; 45 | 46 | } 47 | 48 | public static void main(String[] args) { 49 | TwoStacks sr = new TwoStacks(); 50 | int[] a = {1, 2, 3, 4, 5}; 51 | //int[] a = {2, 1, 4, 3, 5}; 52 | ArrayList b = sr.twoStacksSort(a); 53 | for (int i : b) { 54 | System.out.print(i + ","); 55 | } 56 | System.out.println(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/string/DistinctSubstring.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.string; 2 | 3 | /** 4 | * Created by brian on 16/11/9. 5 | * 6 | * 对于一个字符串,请设计一个高效算法,找到字符串的最长无重复字符的子串长度。 7 | * 给定一个字符串A及它的长度n,请返回它的最长无重复字符子串长度。 8 | * 保证A中字符全部为小写英文字符,且长度小于等于500。 9 | * 10 | * 测试样例: 11 | * "aabcb",5 12 | * 返回:3 13 | */ 14 | public class DistinctSubstring { 15 | public int longestSubstring(String A, int n) { 16 | if (A == null || n == 0) { 17 | return 0; 18 | } 19 | char[] s = A.toCharArray(); 20 | int[] map = new int[256]; 21 | for (int i = 0; i < 256; i++) { 22 | map[i] = -1; 23 | } 24 | 25 | int maxLen = 0; 26 | int pre = -1; 27 | int cur = 0; 28 | for (int i = 0; i < n; i++) { 29 | pre = Math.max(pre, map[s[i]]); 30 | cur = i - pre; 31 | System.out.println(s[i]+"("+i+") pre:"+ pre + " cur:"+cur); 32 | maxLen = Math.max(cur, maxLen); 33 | map[s[i]] = i; 34 | } 35 | return maxLen; 36 | } 37 | 38 | public static void main(String[] args) { 39 | DistinctSubstring d = new DistinctSubstring(); 40 | //System.out.println(d.longestSubstring("aabcb", 5)); 41 | System.out.println(d.longestSubstring("adsaasdfghjhgfdsa", 42 | "adsaasdfghjhgfdsa".length())); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/string/Parenthesis.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.string; 2 | 3 | /** 4 | * Created by brian on 16/11/9. 5 | * 6 | * 对于一个字符串,请设计一个算法,判断其是否为一个合法的括号串。 7 | * 给定一个字符串A和它的长度n,请返回一个bool值代表它是否为一个合法的括号串。 8 | * 测试样例: 9 | * "(()())",6 10 | * 返回:true 11 | * 测试样例: 12 | * "()a()()",7 13 | * 返回:false 14 | * 测试样例: 15 | * "()(()()",7 16 | * 返回:false 17 | */ 18 | public class Parenthesis { 19 | 20 | public boolean chkParenthesis(String A, int n) { 21 | if (A == null || n == 0) { 22 | return false; 23 | } 24 | char[] s = A.toCharArray(); 25 | int count = 0; 26 | for (int i = 0; i < n; i++) { 27 | if (s[i] != '(' && s[i] != ')') { 28 | return false; 29 | } 30 | 31 | if (s[i] == '(') { 32 | count++; 33 | } 34 | if (s[i] == ')' && --count < 0) { 35 | return false; 36 | } 37 | 38 | } 39 | 40 | return count == 0; 41 | } 42 | 43 | public static void main(String[] args) { 44 | Parenthesis p = new Parenthesis(); 45 | boolean b; 46 | b = p.chkParenthesis("(()())", 6); 47 | System.out.println(b); 48 | b = p.chkParenthesis("()a()()", 7); 49 | System.out.println(b); 50 | b = p.chkParenthesis("()(()()", 7); 51 | System.out.println(b); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/string/Prior.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.string; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | /** 7 | * Created by brian on 16/11/8. 8 | * 9 | * 对于一个给定的字符串数组,请找到一种拼接顺序, 10 | * 使所有小字符串拼接成的大字符串是所有可能的拼接中字典序最小的。 11 | * 给定一个字符串数组strs,同时给定它的大小,请返回拼接成的串。 12 | * 13 | * 测试样例: 14 | * ["abc","de"],2 15 | * "abcde" 16 | */ 17 | public class Prior { 18 | public String findSmallest(String[] strs, int n) { 19 | if(strs == null|| n==0){ 20 | return null; 21 | } 22 | 23 | Arrays.sort(strs, new Comparator() { 24 | public int compare(String o1, String o2) { 25 | return (o1+o2).compareTo(o2+o1); 26 | } 27 | }); 28 | StringBuilder sb = new StringBuilder(); 29 | for(int i=0;i= 0; j--) { 31 | if (s[j] == ' ') { 32 | res[i--] = '0'; 33 | res[i--] = '2'; 34 | res[i--] = '%'; 35 | } else { 36 | res[i--] = s[j]; 37 | } 38 | } 39 | 40 | return new String(res); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/string/Reverse.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.string; 2 | 3 | /** 4 | * Created by brian on 16/11/8. 5 | * 6 | * 对于一个字符串,请设计一个算法,只在字符串的单词间做逆序调整, 7 | * 也就是说,字符串由一些由空格分隔的部分组成,你需要将这些部分逆序。 8 | * 给定一个原字符串A和他的长度,请返回逆序后的字符串。 9 | * 10 | * 测试样例: 11 | * "dog loves pig",13 12 | * 返回:"pig loves dog" 13 | */ 14 | public class Reverse { 15 | 16 | public String reverseSentence(String A, int n) { 17 | if (A == null || n == 0) { 18 | return null; 19 | } 20 | 21 | char[] s = A.toCharArray(); 22 | reverse(s, 0, n - 1); 23 | int i = 0; 24 | int begin = 0; 25 | int end = 0; 26 | while (i < s.length) { 27 | if (s[i] == ' ') { 28 | end = i - 1; 29 | reverse(s, begin, end); 30 | begin = i + 1; 31 | } 32 | i++; 33 | } 34 | 35 | if (s[n - 1] != ' ') { 36 | reverse(s, begin, n - 1); 37 | } 38 | 39 | return new String(s); 40 | 41 | } 42 | 43 | private void reverse(char[] chars, int begin, int end) { 44 | char c; 45 | while (begin < end) { 46 | c = chars[begin]; 47 | chars[begin] = chars[end]; 48 | chars[end] = c; 49 | begin++; 50 | end--; 51 | } 52 | } 53 | 54 | public static void main(String[] args) { 55 | String s = "dog loves pig"; 56 | System.out.println(s.length()); 57 | String r = new Reverse().reverseSentence(s, s.length()); 58 | System.out.println(r); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/string/Rotation.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.string; 2 | 3 | /** 4 | * Created by brian on 16/11/2. 5 | * 6 | * 如果对于一个字符串A,将A的前面任意一部分挪到后边去形成的字符串称为A的旋转词。 7 | * 比如A="12345",A的旋转词有"12345","23451","34512","45123"和"51234"。 8 | * 对于两个字符串A和B,请判断A和B是否互为旋转词。 9 | * 给定两个字符串A和B及他们的长度lena,lenb,请返回一个bool值,代表他们是否互为旋转词。 10 | */ 11 | 12 | public class Rotation { 13 | public boolean chkRotation(String A, int lena, String B, int lenb) { 14 | if (lena != lenb) { 15 | return false; 16 | } 17 | String doubleA = A + A; 18 | return doubleA.contains(B); 19 | } 20 | 21 | public static void main(String[] args) { 22 | boolean b = new Rotation().chkRotation("cdab", 4, "abcd", 4); 23 | System.out.println(b); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/string/Transform.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.string; 2 | 3 | /** 4 | * Created by brian on 16/11/8. 5 | * 6 | * 对于两个字符串A和B,如果A和B中出现的字符种类相同且每种字符出现的次数相同, 7 | * 则A和B互为变形词,请设计一个高效算法,检查两给定串是否互为变形词。 8 | * 给定两个字符串A和B及他们的长度,请返回一个bool值,代表他们是否互为变形词。 9 | */ 10 | public class Transform { 11 | public boolean chkTransform(String A, int lena, String B, int lenb) { 12 | if (A == null || B == null || lena != lenb) { 13 | return false; 14 | } 15 | 16 | char[] a = A.toCharArray(); 17 | char[] b = B.toCharArray(); 18 | int[] counts = new int[256]; 19 | for (int i = 0; i < lena; i++) { 20 | counts[a[i]]++; 21 | } 22 | for (int i = 0; i < lenb; i++) { 23 | if (counts[b[i]] == 0) { 24 | return false; 25 | } 26 | counts[b[i]]--; 27 | } 28 | return true; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /algorithms-lecture/src/main/java/com/brianway/learning/algorithms/lectures/string/Translation.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.lectures.string; 2 | 3 | /** 4 | * Created by brian on 16/11/8. 5 | * 6 | * 对于一个字符串,请设计一个算法,将字符串的长度为len的前缀平移到字符串的最后。 7 | * 给定一个字符串A和它的长度,同时给定len,请返回平移后的字符串。 8 | * 9 | * 测试样例: 10 | * "ABCDE",5,3 11 | * 返回:"DEABC" 12 | * 13 | */ 14 | public class Translation { 15 | public String stringTranslation(String A, int n, int len) { 16 | if (A == null || n == 0) { 17 | return null; 18 | } 19 | char[] s = A.toCharArray(); 20 | reverse(s, 0, len - 1); 21 | reverse(s, len, n - 1); 22 | reverse(s, 0, n - 1); 23 | 24 | return new String(s); 25 | } 26 | 27 | private void reverse(char[] chars, int begin, int end) { 28 | char c; 29 | while (begin < end) { 30 | c = chars[begin]; 31 | chars[begin] = chars[end]; 32 | chars[end] = c; 33 | begin++; 34 | end--; 35 | } 36 | } 37 | 38 | public static void main(String[] args) { 39 | String s = "ABCDE"; 40 | String t = new Translation().stringTranslation(s,5,3); 41 | System.out.println(t); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /algorithms-leetcode/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | algorithms-learning 7 | com.brianway.learning.algorithms 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | algorithms-leetcode 13 | 14 | 15 | 16 | junit 17 | junit 18 | 19 | 20 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/company/bytedance/TmpClz.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.company.bytedance; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @auther brian 11 | * @since 2024/4/24 21:57 12 | */ 13 | public class TmpClz { 14 | public static void main(String[] args) { 15 | int[][] a = new int[][] { 16 | // {2, 2}, {1, 1}, {0, 0}, {2, 0} 17 | {2, 1, 1}, {1, 1, 0}, {0, 1, 1} 18 | }; 19 | 20 | // System.out.println(new Solution().orangesRotting(a)); 21 | } 22 | 23 | // public static 24 | 25 | } 26 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/common/ListNode.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.common; 2 | 3 | /** 4 | * Created by Brian on 2016/5/5. 5 | * Definition for singly-linked list. 6 | */ 7 | public class ListNode { 8 | public int val; 9 | public ListNode next; 10 | 11 | ListNode() { 12 | } 13 | 14 | public ListNode(int val) { 15 | this.val = val; 16 | } 17 | 18 | public ListNode(int val, ListNode next) { 19 | this.val = val; this.next = next; 20 | } 21 | } -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/common/TreeNode.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.common; 2 | 3 | /** 4 | * Created by brian on 16/6/6. 5 | * Definition for a binary tree node. 6 | */ 7 | public class TreeNode { 8 | public int val; 9 | public TreeNode left; 10 | public TreeNode right; 11 | 12 | public TreeNode() { 13 | } 14 | 15 | public TreeNode(int val) { 16 | this.val = val; 17 | } 18 | 19 | public TreeNode(int val, TreeNode left, TreeNode right) { 20 | this.val = val; 21 | this.left = left; 22 | this.right = right; 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/AssignCookies.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * LeetCode 455. Assign Cookies 7 | * Question: https://leetcode.com/problems/assign-cookies/ 8 | * 关键题设: 无 9 | * 10 | * @auther brian 11 | * @since 2022/8/10 23:40 12 | */ 13 | public class AssignCookies { 14 | public int findContentChildren(int[] g, int[] s) { 15 | return 0; 16 | } 17 | 18 | /** 19 | * 贪心:在s[j]>=g[i]中,挑出最小的s[j] 20 | *

21 | * 先对 g 和 s 排序升序,然后从小到大遍历s, 满足 s[j]>=g[i]的就计数 22 | *

23 | * 时间复杂度:O(m log m + n log n) 24 | * 空间复杂度:取决于排序算法 25 | */ 26 | public class AssignCookies0 extends AssignCookies { 27 | @Override 28 | public int findContentChildren(int[] g, int[] s) { 29 | Arrays.sort(g); 30 | Arrays.sort(s); 31 | int i = 0; 32 | int count = 0; 33 | for (int j = 0; j < s.length; j++) { 34 | if (i >= g.length) { 35 | break; 36 | } 37 | if (s[j] >= g[i]) { 38 | count++; 39 | i++; 40 | } 41 | } 42 | return count; 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/AverageOfLevelsInBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import java.util.Queue; 9 | 10 | /** 11 | * LeetCode 637. Average of Levels in Binary Tree 12 | * Question https://leetcode.com/problems/average-of-levels-in-binary-tree/ 13 | * 关键题设:无 14 | * 15 | * @auther brian 16 | * @since 2022/9/2 22:26 17 | */ 18 | public class AverageOfLevelsInBinaryTree { 19 | public List averageOfLevels(TreeNode root) { 20 | return null; 21 | } 22 | 23 | public class AverageOfLevelsInBinaryTree0 extends AverageOfLevelsInBinaryTree { 24 | @Override 25 | public List averageOfLevels(TreeNode root) { 26 | List result = new ArrayList<>(); 27 | Queue queue = new LinkedList<>(); 28 | if (root == null) { 29 | return result; 30 | } 31 | queue.offer(root); 32 | while (!queue.isEmpty()) { 33 | int size = queue.size(); 34 | Double sum = 0.0; 35 | for (int i = 0; i < size; i++) { 36 | TreeNode cur = queue.poll(); 37 | sum += cur.val; 38 | if (cur.left != null) { 39 | queue.offer(cur.left); 40 | } 41 | if (cur.right != null) { 42 | queue.offer(cur.right); 43 | } 44 | } 45 | result.add(sum / size); 46 | } 47 | return result; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/BalancedBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 110. Balanced Binary Tree 7 | * Question: https://leetcode.com/problems/balanced-binary-tree/ 8 | * 关键题设: 无 9 | * 10 | * @auther brian 11 | * @since 2022/9/3 17:08 12 | */ 13 | public class BalancedBinaryTree { 14 | 15 | public boolean isBalanced(TreeNode root) { 16 | return false; 17 | } 18 | 19 | /** 20 | * 递归 21 | *

22 | * 用树的高度来解决,后序遍历 23 | */ 24 | public class BalancedBinaryTree0 extends BalancedBinaryTree { 25 | @Override 26 | public boolean isBalanced(TreeNode root) { 27 | if (root == null) { 28 | return true; 29 | } 30 | return getHeight(root) != -1; 31 | } 32 | 33 | /** 34 | * 如果cur是平衡的,则返回高度,否则返回-1 35 | */ 36 | public int getHeight(TreeNode cur) { 37 | if (cur == null) { 38 | return 0; 39 | } 40 | int leftHeight = getHeight(cur.left); 41 | if (leftHeight == -1) { 42 | return -1; 43 | } 44 | int rightHeight = getHeight(cur.right); 45 | if (rightHeight == -1) { 46 | return -1; 47 | } 48 | 49 | if (Math.abs(leftHeight - rightHeight) > 1) { 50 | return -1; 51 | } else { 52 | return Math.max(leftHeight, rightHeight) + 1; 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | /** 4 | * LeetCode 704. Binary Search 5 | * Question: https://leetcode.com/problems/binary-search/ 6 | * 关键题设:无 7 | * 8 | * @auther brian 9 | * @since 2022/8/8 21:00 10 | */ 11 | public class BinarySearch { 12 | 13 | public int search(int[] nums, int target) { 14 | int low = 0; 15 | int high = nums.length - 1; 16 | int mid = low + (high - low) / 2; 17 | 18 | while (low <= high) { 19 | if (target == nums[mid]) { 20 | return mid; 21 | } else if (target > nums[mid]) { 22 | low = mid + 1; 23 | } else { 24 | high = mid - 1; 25 | } 26 | // 这句也可以在循环开始处计算 27 | mid = low + (high - low) / 2; 28 | } 29 | return -1; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/FindModeInBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * LeetCode 501. Find Mode in Binary Search Tree 10 | * Question: https://leetcode.com/problems/find-mode-in-binary-search-tree/ 11 | * 关键题设:无 12 | * 13 | * @auther brian 14 | * @since 2022/9/7 23:07 15 | */ 16 | public class FindModeInBinarySearchTree { 17 | public int[] findMode(TreeNode root) { 18 | return null; 19 | } 20 | 21 | /** 22 | * 递归 23 | *

24 | * 中序遍历,一次遍历即可:边统计频次,边更新int[] 25 | */ 26 | public class FindModeInBinarySearchTree0 extends FindModeInBinarySearchTree { 27 | List result = new ArrayList<>(); 28 | int maxCount; 29 | int count; 30 | int preVal = Integer.MIN_VALUE; 31 | 32 | @Override 33 | public int[] findMode(TreeNode root) { 34 | transversal(root); 35 | return result.stream().mapToInt(i -> i).toArray(); 36 | } 37 | 38 | public void transversal(TreeNode root) { 39 | if (root == null) { 40 | return; 41 | } 42 | 43 | // 左 44 | transversal(root.left); 45 | 46 | // 中 47 | if (preVal == root.val) { 48 | count++; 49 | } else { 50 | count = 1; 51 | } 52 | 53 | // 更新 maxCount 和 result 54 | if (count > maxCount) { 55 | maxCount = count; 56 | result.clear(); 57 | result.add(root.val); 58 | } else if (count == maxCount) { 59 | result.add(root.val); 60 | } 61 | 62 | preVal = root.val; 63 | 64 | // 右 65 | transversal(root.right); 66 | 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/HappyNumber.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import java.util.HashSet; 4 | 5 | /** 6 | * Created by brian on 2016/5/15. 7 | * LeetCode 202. Happy Number 8 | * Question:https://leetcode.com/problems/happy-number/ 9 | * 关键题设: or it loops endlessly in a cycle which does not include 1 10 | */ 11 | public class HappyNumber { 12 | public boolean isHappy(int n) { 13 | return false; 14 | } 15 | 16 | /** 17 | * 哈希表 18 | * 结果总会出现环的,所以只需要每次都记录sum,每次算完sum查看是否已经存在 19 | * 若存在则跳出循环,返回 20 | * 若不存在则添加进HashSet,更新n 21 | * TODO 时间复杂度 空间复杂度 22 | */ 23 | public class HappyNumber0 extends HappyNumber { 24 | @Override 25 | public boolean isHappy(int n) { 26 | HashSet set = new HashSet(); 27 | int sum = 0; 28 | while (true) { 29 | sum = 0; 30 | while (n != 0) { 31 | sum += (n % 10) * (n % 10); 32 | n = n / 10; 33 | } 34 | if (set.contains(sum)) { 35 | return sum == 1; 36 | } else { 37 | set.add(sum); 38 | n = sum; 39 | } 40 | } 41 | 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/IntersectionofTwoLinkedLists.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.ListNode; 4 | 5 | /** 6 | * Created by Brian on 2016/5/4. 7 | * LeetCode 160. Intersection of Two Linked Lists 8 | * Question:https://leetcode.com/problems/intersection-of-two-linked-lists/ 9 | * 关键题设: preferably run in O(n) time and use only O(1) memory 10 | */ 11 | public class IntersectionofTwoLinkedLists { 12 | 13 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 14 | return null; 15 | } 16 | 17 | /** 18 | * 两次遍历,第一次分别遍历两链表,找长度的差值,第二次从距离交点等距的地方向后遍历 19 | * 时间复杂度O(n1+n2) 20 | * 空间复杂度O(1) 21 | */ 22 | public class IntersectionofTwoLinkedLists0 extends IntersectionofTwoLinkedLists { 23 | @Override 24 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 25 | ListNode a = headA; 26 | ListNode b = headB; 27 | int countA = 0; 28 | int countB = 0; 29 | 30 | while (a != null) { 31 | countA++; 32 | a = a.next; 33 | } 34 | while (b != null) { 35 | countB++; 36 | b = b.next; 37 | } 38 | a = headA; 39 | b = headB; 40 | if (countA > countB) { 41 | for (int i = 0; i < countA - countB; i++) { 42 | a = a.next; 43 | } 44 | } else { 45 | for (int i = 0; i < countB - countA; i++) { 46 | b = b.next; 47 | } 48 | } 49 | 50 | while (a != null) { 51 | if (a == b) { 52 | return a; 53 | } 54 | a = a.next; 55 | b = b.next; 56 | } 57 | 58 | return null; 59 | 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/InvertBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 226. Invert Binary Tree 7 | * Question https://leetcode.com/problems/invert-binary-tree/ 8 | * 关键题设:无 9 | * 10 | * @auther brian 11 | * @since 2022/9/2 22:43 12 | */ 13 | public class InvertBinaryTree { 14 | public TreeNode invertTree(TreeNode root) { 15 | return null; 16 | } 17 | 18 | public class InvertBinaryTree0 extends InvertBinaryTree { 19 | @Override 20 | public TreeNode invertTree(TreeNode root) { 21 | invert(root); 22 | return root; 23 | } 24 | 25 | public void invert(TreeNode cur) { 26 | if (cur == null) { 27 | return; 28 | } 29 | // invert current 30 | TreeNode tmp = cur.left; 31 | cur.left = cur.right; 32 | cur.right = tmp; 33 | 34 | invert(cur.left); 35 | invert(cur.right); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/LinkedListCycle.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.ListNode; 4 | 5 | /** 6 | * Created by brian on 16/5/22. 7 | * LeetCode 141. Linked List Cycle 8 | * Question:https://leetcode.com/problems/linked-list-cycle/ 9 | * 关键题设:without using extra space 10 | */ 11 | public class LinkedListCycle { 12 | 13 | public boolean hasCycle(ListNode head) { 14 | return false; 15 | } 16 | 17 | /** 18 | * 快慢指针 19 | * 1)如果有环,两指针一定会相遇 20 | * 因为每次循环,快指针会追赶慢指针一个节点的距离,所以不会出现跳过的问题 21 | * 2)如果没有环,fast会先遍历到结尾,直接结束while,不会出现死循环 22 | *

23 | * 时间复杂度 O(n) 24 | * 空间复杂度 O(1) 25 | * 分析可见 https://leetcode.com/articles/linked-list-cycle/ 26 | */ 27 | public class LinkedListCycle0 extends LinkedListCycle { 28 | @Override 29 | public boolean hasCycle(ListNode head) { 30 | if (head == null) { 31 | return false; 32 | } 33 | 34 | ListNode fast = head; 35 | ListNode slow = head; 36 | while (fast.next != null && fast.next.next != null) { 37 | fast = fast.next.next; 38 | slow = slow.next; 39 | if (fast == slow) { 40 | return true; 41 | } 42 | } 43 | return false; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MaximumDepthOfBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 104. Maximum Depth of Binary Tree 7 | * Question: https://leetcode.com/problems/maximum-depth-of-binary-tree/ 8 | * 关键题设: maximum depth 9 | * 10 | * @auther brian 11 | * @since 2022/9/3 15:33 12 | */ 13 | public class MaximumDepthOfBinaryTree { 14 | public int maxDepth(TreeNode root) { 15 | return 0; 16 | } 17 | 18 | /** 19 | * 递归解法 20 | *

21 | * 根节点的高度就是二叉树的最大深度 22 | * 后序遍历: 左子树高度,右子树高度,cur的高度 23 | */ 24 | public class MaximumDepthOfBinaryTree0 extends MaximumDepthOfBinaryTree { 25 | @Override 26 | public int maxDepth(TreeNode root) { 27 | if (root == null) { 28 | return 0; 29 | } 30 | 31 | int maxLeftDepth = maxDepth(root.left); 32 | int maxRightDepth = maxDepth(root.right); 33 | return Math.max(maxLeftDepth, maxRightDepth) + 1; 34 | } 35 | } 36 | 37 | // TODO 迭代法: 层序遍历即可 38 | } 39 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MergeTwoBinaryTrees.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 617. Merge Two Binary Trees 7 | * Question: https://leetcode.com/problems/merge-two-binary-trees/ 8 | * 关键题设:无 9 | * 10 | * @auther brian 11 | * @since 2022/9/7 21:43 12 | */ 13 | public class MergeTwoBinaryTrees { 14 | 15 | public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { 16 | return null; 17 | } 18 | 19 | /** 20 | * 递归 21 | *

22 | * 先序遍历/后序遍历都行 23 | */ 24 | public class MergeTwoBinaryTrees0 extends MergeTwoBinaryTrees { 25 | @Override 26 | public TreeNode mergeTrees(TreeNode root1, TreeNode root2) { 27 | // 终止条件 28 | if (root1 == null && root2 == null) { 29 | return null; 30 | } else if (root1 == null) { 31 | return root2; 32 | } else if (root2 == null) { 33 | return root1; 34 | } 35 | 36 | // merge current 37 | TreeNode cur = new TreeNode(root1.val + root2.val); 38 | // merge left 39 | TreeNode left = mergeTrees(root1.left, root2.left); 40 | // merge right 41 | TreeNode right = mergeTrees(root1.right, root2.right); 42 | 43 | cur.left = left; 44 | cur.right = right; 45 | 46 | return cur; 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MergeTwoSortedLists.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.ListNode; 4 | 5 | /** 6 | * Created by Brian on 2016/5/4. 7 | * LeetCode 21. Merge Two Sorted Lists 8 | * Question:https://leetcode.com/problems/merge-two-sorted-lists/ 9 | * 关键题设: two sorted linked lists 10 | */ 11 | public class MergeTwoSortedLists { 12 | 13 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 14 | return null; 15 | } 16 | 17 | /** 18 | * 链表的基本操作 19 | * 主要是要先添加一个头部,方便代码一致 20 | * 用一个指针指示当前节点的上一个节点,每次添加较小的那个 21 | * 直至一个其中一个遍历完,直接把另一链表全部接上即可 22 | * 23 | * 设l1长度为n1,l2长度n2 24 | * 时间复杂度:最坏情况O(n1+n2) 25 | * 空间复杂度 O(1) 26 | */ 27 | public class MergeTwoSortedLists0 extends MergeTwoSortedLists { 28 | @Override 29 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 30 | ListNode head = new ListNode(0); 31 | ListNode now = head; 32 | while (l1 != null && l2 != null) { 33 | if (l1.val < l2.val) { 34 | //now.next = new ListNode(l1.val); 35 | now.next = l1; 36 | l1 = l1.next; 37 | } else { 38 | //now.next = new ListNode(l2.val); 39 | now.next = l2; 40 | l2 = l2.next; 41 | } 42 | now = now.next; 43 | } 44 | if (l1 != null) { 45 | now.next = l1; 46 | } 47 | if (l2 != null) { 48 | now.next = l2; 49 | } 50 | return head.next; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MinimumAbsoluteDifferenceInBST.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 530. Minimum Absolute Difference in BST 7 | * Question https://leetcode.com/problems/minimum-absolute-difference-in-bst/ 8 | * 关键题设:无 9 | * 10 | * @auther brian 11 | * @since 2022/9/7 22:47 12 | */ 13 | public class MinimumAbsoluteDifferenceInBST { 14 | public int getMinimumDifference(TreeNode root) { 15 | return 0; 16 | } 17 | 18 | /** 19 | * 递归 20 | */ 21 | public class MinimumAbsoluteDifferenceInBST0 extends MinimumAbsoluteDifferenceInBST { 22 | private TreeNode pre; 23 | private int result = Integer.MAX_VALUE; 24 | 25 | @Override 26 | public int getMinimumDifference(TreeNode root) { 27 | if (root == null) { 28 | return 0; 29 | } 30 | traversal(root); 31 | return result; 32 | } 33 | 34 | /** 35 | * 中序遍历 36 | */ 37 | public void traversal(TreeNode root) { 38 | if (root == null) { 39 | return; 40 | } 41 | 42 | traversal(root.left); 43 | if (pre != null) { 44 | result = Math.min(root.val - pre.val, result); 45 | } 46 | pre = root; 47 | 48 | traversal(root.right); 49 | 50 | } 51 | 52 | } 53 | 54 | // TODO 迭代 55 | 56 | } 57 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/MinimumDepthOfBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 111. Minimum Depth of Binary Tree 7 | * Question: https://leetcode.com/problems/minimum-depth-of-binary-tree/ 8 | * 关键题设:The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 9 | * 10 | * @auther brian 11 | * @since 2022/9/3 15:47 12 | */ 13 | public class MinimumDepthOfBinaryTree { 14 | public int minDepth(TreeNode root) { 15 | return 0; 16 | } 17 | 18 | /** 19 | * 递归 20 | *

21 | * 后序遍历 22 | *

23 | * 注意:子树为空的情况 24 | */ 25 | public class MinimumDepthOfBinaryTree0 extends MinimumDepthOfBinaryTree { 26 | @Override 27 | public int minDepth(TreeNode root) { 28 | if (root == null) { 29 | return 0; 30 | } 31 | int leftMinDepth = minDepth(root.left); 32 | int rightMinDepth = minDepth(root.right); 33 | 34 | if (root.left != null && root.right == null) { 35 | return leftMinDepth + 1; 36 | } else if (root.left == null && root.right != null) { 37 | return rightMinDepth + 1; 38 | } else { 39 | return Math.min(leftMinDepth, rightMinDepth) + 1; 40 | } 41 | } 42 | } 43 | 44 | // TODO 层序遍历,左右孩子都空说明到最低点了 45 | } 46 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/PathSum.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 112. Path Sum 7 | * Question: https://leetcode.com/problems/path-sum/ 8 | * 关键题设:无 9 | * 10 | * @auther brian 11 | * @since 2022/9/6 21:41 12 | */ 13 | public class PathSum { 14 | public boolean hasPathSum(TreeNode root, int targetSum) { 15 | return false; 16 | } 17 | 18 | public class PathSum0 extends PathSum { 19 | @Override 20 | public boolean hasPathSum(TreeNode root, int targetSum) { 21 | // 终止条件: null or 叶子节点 22 | if (root == null) { 23 | return false; 24 | } 25 | if (root.left == null && root.right == null) { 26 | return targetSum - root.val == 0; 27 | } 28 | 29 | // 本层逻辑 30 | return hasPathSum(root.left, targetSum - root.val) 31 | || hasPathSum(root.right, targetSum - root.val); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/PowerOfTwo.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | /** 4 | * Created by brian on 16/5/23. 5 | * LeetCode 231. Power of Two 6 | * Question:https://leetcode.com/problems/power-of-two/ 7 | * 关键题设:power of two 8 | */ 9 | public class PowerOfTwo { 10 | public boolean isPowerOfTwo(int n) { 11 | return false; 12 | } 13 | 14 | /** 15 | * 2的幂实际上就是通过1向右移位得到的,每乘以2就是向右移动一位 16 | * 所以其二进制高位只有一个1,其余位为0 17 | * 此方法好像并不受小于0的数影响 18 | */ 19 | public class PowerOfTwo0 extends PowerOfTwo { 20 | @Override 21 | public boolean isPowerOfTwo(int n) { 22 | // if(n<0) return false;//多余,while能直接办到 23 | boolean hasOne = false; 24 | while (n > 0) { 25 | if ((n & 1) == 1) { 26 | if (hasOne) {//已经有1了,再次遇到1,非2的幂 27 | return false; 28 | } else {//第一次1 29 | hasOne = true; 30 | } 31 | } 32 | n >>= 1;//右移一位 33 | } 34 | return hasOne; 35 | } 36 | } 37 | 38 | /** 39 | * n 与 n-1 按位与 40 | * 好像并不受小于0的数影响,小于稳定返回false 41 | * 注意零值 42 | */ 43 | public class PowerOfTwo1 extends PowerOfTwo { 44 | @Override 45 | public boolean isPowerOfTwo(int n) { 46 | return n > 0 && (n & (n - 1)) == 0; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/RemoveDuplicatesfromSortedArray.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | /** 4 | * Created by Brian on 2016/4/26. 5 | * LeetCode 26. Remove Duplicates from Sorted Array 6 | * Question:https://leetcode.com/problems/remove-duplicates-from-sorted-array/ 7 | * 关键题设: a sorted array,remove the duplicates in place 8 | */ 9 | public class RemoveDuplicatesfromSortedArray { 10 | public int removeDuplicates(int[] nums) { 11 | return 0; 12 | } 13 | 14 | /** 15 | * 双指针,一个指示distinct的结尾,记为i,一个用于扫描,记为j 16 | * 当扫描指针所指示nums[j]和nums[j+i]值不同时,则赋值nums[i],并increment i指针。 17 | * 时间复杂度 O(n) 18 | * 空间复杂度 O(1) 19 | */ 20 | public class RemoveDuplicatesfromSortedArray0 extends RemoveDuplicatesfromSortedArray { 21 | @Override 22 | public int removeDuplicates(int[] nums) { 23 | if (nums.length <= 1) return nums.length; 24 | int i = 0; 25 | for (int j = 0; j < nums.length - 1; j++) { 26 | if (nums[j] < nums[j + 1]) { 27 | nums[++i] = nums[j + 1]; 28 | } 29 | } 30 | return i + 1; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/ReverseString.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | /** 4 | * Created by brian on 16/5/30. 5 | * LeetCode 344. Reverse String 6 | * Question:https://leetcode.com/problems/reverse-string/ 7 | * 关键题设:none 8 | */ 9 | public class ReverseString { 10 | public void reverseString(char[] s) { 11 | 12 | } 13 | 14 | /** 15 | * 首尾互换就行了 16 | * 将第i个字符和第length-1-i个字符交换 17 | * 0 ≤ i ≤ length/2-1 18 | * 这里边界不要搞错了,第一次就是想着少交换中间的一个,i 取的 0≤i≤(length-1)/2 19 | * 然后测试案例"a."没通过 20 | *

21 | * 例子: 22 | * s a b c d e f 23 | * i 0 1 2 3 4 5 24 | * length = 6,中间的 i = 3,其实取到 i = 2 即可 25 | * a a b c d e 26 | * i 0 1 2 3 4 27 | * length = 5,中间的 i = 2,其实取到 i = 1 即可 28 | *

29 | * 相关链接:http://javahungry.blogspot.com/2014/12/5-ways-to-reverse-string-in-java-with-example.html 30 | *

31 | * 时间复杂度 O(n/2) 32 | * 空间复杂度 O(1) 33 | */ 34 | public class ReverseString0 extends ReverseString { 35 | @Override 36 | public void reverseString(char[] s) { 37 | int length = s.length; 38 | char tmp; 39 | for (int i = 0; i < length / 2; i++) { 40 | tmp = s[i]; 41 | s[i] = s[length - 1 - i]; 42 | s[length - 1 - i] = tmp; 43 | } 44 | } 45 | } 46 | 47 | public class RevereString1 extends ReverseString { 48 | public void reverseString(char[] s) { 49 | int l = 0; 50 | int r = s.length - 1; 51 | while (l < r) { 52 | s[l] ^= s[r]; //构造 a ^ b 的结果,并放在 a 中 53 | s[r] ^= s[l]; //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b 54 | s[l] ^= s[r]; //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换 55 | l++; 56 | r--; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/ReverseStringII.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | /** 4 | * LeetCode 541. Reverse String II 5 | * Question: https://leetcode.com/problems/reverse-string-ii/ 6 | * 关键题设:无 7 | * 8 | * @auther brian 9 | * @since 2022/9/9 00:05 10 | */ 11 | public class ReverseStringII { 12 | 13 | public String reverseStr(String s, int k) { 14 | return null; 15 | } 16 | 17 | public class ReverseStringII0 extends ReverseStringII { 18 | @Override 19 | public String reverseStr(String s, int k) { 20 | char[] ss = s.toCharArray(); 21 | int len = 2 * k; 22 | for (int i = 0; i < ss.length; i = i + len) { 23 | reversePart(ss, i, Math.min(i + k, ss.length)); 24 | } 25 | return new String(ss); 26 | } 27 | 28 | public void reversePart(char[] ss, int lowInclusive, int highExclusive) { 29 | char tmp; 30 | for (int i = lowInclusive; i < lowInclusive + (highExclusive - lowInclusive) / 2; i++) { 31 | tmp = ss[i]; 32 | ss[i] = ss[highExclusive + lowInclusive - 1 - i]; 33 | ss[highExclusive + lowInclusive - 1 - i] = tmp; 34 | } 35 | } 36 | 37 | public void reversePart2(char[] ss, int lowInclusive, int highExclusive) { 38 | int highInclusive = highExclusive - 1; 39 | char tmp; 40 | while (lowInclusive < highInclusive) { 41 | tmp = ss[lowInclusive]; 42 | ss[lowInclusive] = ss[highInclusive]; 43 | ss[highInclusive] = tmp; 44 | lowInclusive++; 45 | highInclusive--; 46 | } 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/SearchInBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 700. Search in a Binary Search Tree 7 | * Question: https://leetcode.com/problems/search-in-a-binary-search-tree/ 8 | * 关键题设:无 9 | * 10 | * @auther brian 11 | * @since 2022/9/7 21:51 12 | */ 13 | public class SearchInBinarySearchTree { 14 | 15 | public TreeNode searchBST(TreeNode root, int val) { 16 | return null; 17 | } 18 | 19 | /** 20 | * 递归 21 | */ 22 | public class SearchInBinarySearchTree0 extends SearchInBinarySearchTree { 23 | @Override 24 | public TreeNode searchBST(TreeNode root, int val) { 25 | // 终止条件 26 | if (root == null) { 27 | return null; 28 | } 29 | 30 | if (root.val == val) { 31 | return root; 32 | } else if (root.val > val) { 33 | return searchBST(root.left, val); 34 | } else { 35 | return searchBST(root.right, val); 36 | } 37 | } 38 | } 39 | 40 | /** 41 | * 迭代 42 | */ 43 | public class SearchInBinarySearchTree01 extends SearchInBinarySearchTree { 44 | @Override 45 | public TreeNode searchBST(TreeNode root, int val) { 46 | TreeNode cur = root; 47 | while (cur != null) { 48 | if (cur.val == val) { 49 | return cur; 50 | } else if (cur.val > val) { 51 | cur = cur.left; 52 | } else { 53 | cur = cur.right; 54 | } 55 | } 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/SearchInsertPosition.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | /** 4 | * LeetCode 35. Search Insert Position 5 | * Question https://leetcode.com/problems/search-insert-position/ 6 | * 关键题设:array of distinct integers 7 | * 8 | * @auther brian 9 | * @since 2022/5/8 15:16 10 | */ 11 | public class SearchInsertPosition { 12 | 13 | public int searchInsert(int[] nums, int target) { 14 | return 0; 15 | } 16 | 17 | /** 18 | * 如果target在nums中找不到,则最终一定是low>high,且low=high+1 19 | * 此时,如果 target < nums[mid], 则说明最后一次low=high=mid, 然后分支走的是 high = mid - 1, 20 | * 从而循环结束时,mid=low>high, 插入位置为 mid,即low; 21 | * 如果 target > nums[mid],则说明最后一次low=high=mid, 然后分支走的是 low = mid + 1, 22 | * 从而循环结束时,mid=high < low, 插入位置为 mid+1,也即low; 23 | */ 24 | public static class SearchInsertPosition0 extends SearchInsertPosition { 25 | @Override 26 | public int searchInsert(int[] nums, int target) { 27 | int low = 0; 28 | int high = nums.length - 1; 29 | while (low <= high) { 30 | int mid = low + (high - low) / 2; 31 | if (nums[mid] == target) { 32 | return mid; 33 | } else if (nums[mid] > target) { 34 | high = mid - 1; 35 | } else { 36 | low = mid + 1; 37 | } 38 | } 39 | 40 | return low; 41 | } 42 | } 43 | } 44 | 45 | // System.out.println("target:" + target + ", mid: " + mid); 46 | // System.out.println("low:" + low + ", high: " + high); 47 | // -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/SumOfLeftLeaves.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 404. Sum of Left Leaves 7 | * Question https://leetcode.com/problems/sum-of-left-leaves/ 8 | * 关键题设:A leaf is a node with no children. 9 | * A left leaf is a leaf that is the left child of another node. 10 | * 11 | * @auther brian 12 | * @since 2022/9/6 00:00 13 | */ 14 | public class SumOfLeftLeaves { 15 | 16 | public int sumOfLeftLeaves(TreeNode root) { 17 | return 0; 18 | } 19 | 20 | /** 21 | * 递归 22 | * 后序遍历 23 | */ 24 | public class SumOfLeftLeaves0 extends SumOfLeftLeaves { 25 | @Override 26 | public int sumOfLeftLeaves(TreeNode root) { 27 | // 终止条件 28 | if (root == null) { 29 | return 0; 30 | } 31 | // 单层逻辑 32 | int leftSum = sumOfLeftLeaves(root.left); 33 | if (root.left != null && root.left.left == null && root.left.right == null) { 34 | // 仅这个if条件下才会有val值贡献进来 35 | leftSum = root.left.val; 36 | } 37 | int rightSum = sumOfLeftLeaves(root.right); 38 | 39 | return leftSum + rightSum; 40 | } 41 | } 42 | 43 | // TODO 迭代写法 44 | } 45 | 46 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/easy/ValidParentheses.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * LeetCode 20. Valid Parentheses 7 | * Question:https://leetcode.com/problems/valid-parentheses/description/ 8 | * 关键题设:无 9 | */ 10 | public class ValidParentheses { 11 | public boolean isValid(String s) { 12 | return false; 13 | } 14 | 15 | /** 16 | * 栈来存 17 | * 左括号直接入栈,右括号则看是否和栈顶元素匹配 18 | * 注意事项:栈为空时,需要判断,要避免 java.util.EmptyStackException 19 | *

20 | * 时间复杂度 O(n) 21 | * 空间复杂度 O(n) 22 | */ 23 | public class ValidParentheses0 extends ValidParentheses { 24 | @Override 25 | public boolean isValid(String s) { 26 | if (s == null || s.isEmpty()) { 27 | return true; 28 | } 29 | char[] chars = s.toCharArray(); 30 | Stack stack = new Stack<>(); 31 | for (int i = 0; i < chars.length; i++) { 32 | if (isLeftParentheses(chars[i])) { 33 | stack.push(chars[i]); 34 | } else if (isRightParentheses(chars[i])) { 35 | if (stack.isEmpty() || !match(stack.pop(), chars[i])) { 36 | return false; 37 | } 38 | } 39 | } 40 | return stack.isEmpty(); 41 | } 42 | 43 | private boolean isLeftParentheses(char c) { 44 | return c == '(' || c == '[' || c == '{'; 45 | } 46 | 47 | private boolean isRightParentheses(char c) { 48 | return c == ')' || c == ']' || c == '}'; 49 | } 50 | 51 | private boolean match(char left, char right) { 52 | return left == '(' && right == ')' || left == '[' && right == ']' || left == '{' && right == '}'; 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/hard/DistinctSubsequences.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.hard; 2 | 3 | /** 4 | * LeetCode 115. Distinct Subsequences 5 | * Question: https://leetcode.com/problems/distinct-subsequences/ 6 | * 关键题设:无 7 | * 8 | * @auther brian 9 | * @since 2022/8/22 23:31 10 | */ 11 | public class DistinctSubsequences { 12 | 13 | public int numDistinct(String s, String t) { 14 | return 0; 15 | } 16 | 17 | /** 18 | * DP 19 | *

20 | * 1. dp数组以及下标含义: dp[i+1][j+1] 表示 s的[0...i] 中 子序列为t[0...j]的不同子序列的个数 21 | * 2. 递推关系: 22 | * if(s[i]==t[j]) dp[i+1][j+1] = dp[i][j]+dp[i][j+1], 表示使用s[i] 和不使用s[i]的不同子序列的个数 23 | * else dp[i+1][j+1]=dp[i][j+1], 表示不使用s[i] 24 | * 3. 初始化: 25 | * dp[i][0] 都是1, 表示t为空串时,子序列个数为1,即 "" 是任意字符串的子序列,且最只有一个; 26 | * dp[0][j]=0,(j>0) 表示没有子序列; 27 | * dp[0][0]=1, 表示 "" 是 "" 的子序列 28 | * 4. 遍历顺序:从左到右 29 | *

30 | * 最后返回 dp[s.len][t.len] 31 | */ 32 | public class DistinctSubsequences0 extends DistinctSubsequences { 33 | @Override 34 | public int numDistinct(String s, String t) { 35 | int[][] dp = new int[s.length() + 1][t.length() + 1]; 36 | // 很关键的初始化 37 | for (int i = 0; i < s.length(); i++) { 38 | dp[i][0] = 1; 39 | } 40 | for (int j = 0; j < t.length(); j++) { 41 | dp[0][j] = 0; 42 | } 43 | dp[0][0] = 1; 44 | 45 | for (int i = 0; i < s.length(); i++) { 46 | for (int j = 0; j < t.length(); j++) { 47 | if (t.charAt(j) == s.charAt(i)) { 48 | dp[i + 1][j + 1] = dp[i][j] + dp[i][j + 1]; 49 | } else { 50 | dp[i + 1][j + 1] = dp[i][j + 1]; 51 | } 52 | } 53 | } 54 | return dp[s.length()][t.length()]; 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/hard/TrappingRainWater.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.hard; 2 | 3 | /** 4 | * LeetCode 42. Trapping Rain Water 5 | * Question: https://leetcode.com/problems/trapping-rain-water/ 6 | * 关键题设: 无 7 | * 8 | * @auther brian 9 | * @since 2022/12/2 23:32 10 | */ 11 | public class TrappingRainWater { 12 | 13 | /** 14 | * 按列求 15 | * 对于每一列,找出其左侧最高列的高度 max_left 和 右侧最高列的高度 max_right 16 | * 如果 min(max_left, max_right) > 当前列高度,则 该列对应雨水 为 min(max_left, max_right)- height[i], 否则为0 17 | * 累加每列的雨水即可 18 | *

19 | * 每一列的max_left和max_right可用动态规划求 20 | *

21 | * 时间复杂度 O(n) 三次遍历 22 | * 空间复杂度 O(n) 两个长度n的数组存每一列的max_left和max_right 23 | */ 24 | class Solution { 25 | public int trap(int[] height) { 26 | int[] leftMax = new int[height.length]; 27 | int[] rightMax = new int[height.length]; 28 | // leftMax[i]表示0~i-1的最大值 29 | for (int i = 1; i < height.length; i++) { 30 | leftMax[i] = Math.max(leftMax[i - 1], height[i - 1]); 31 | } 32 | // rightMax[i]表示i+1~n的最大值 33 | for (int i = height.length - 2; i >= 0; i--) { 34 | rightMax[i] = Math.max(rightMax[i + 1], height[i + 1]); 35 | } 36 | 37 | int total = 0; 38 | for (int i = 0; i < height.length; i++) { 39 | int min = Math.min(leftMax[i], rightMax[i]); 40 | if (min > height[i]) { 41 | total += (min - height[i]); 42 | } 43 | } 44 | return total; 45 | 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/BinaryTreeLevelOrderTraversalII.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * LeetCode 107. Binary Tree Level Order Traversal II 9 | * Question: https://leetcode.com/problems/binary-tree-level-order-traversal-ii/ 10 | * 关键题设:无 11 | * 12 | * @auther brian 13 | * @since 2022/9/2 00:04 14 | */ 15 | public class BinaryTreeLevelOrderTraversalII { 16 | public List> levelOrderBottom(TreeNode root) { 17 | return null; 18 | } 19 | 20 | // TODO 练手复习 21 | } 22 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/BinaryTreeRightSideView.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import java.util.Queue; 9 | 10 | /** 11 | * LeetCode 199. Binary Tree Right Side View 12 | * Question: https://leetcode.com/problems/binary-tree-right-side-view/ 13 | * 关键题设:无 14 | * 15 | * @auther brian 16 | * @since 2022/9/2 21:53 17 | */ 18 | public class BinaryTreeRightSideView { 19 | public List rightSideView(TreeNode root) { 20 | return null; 21 | } 22 | 23 | /** 24 | * BFS,层序遍历 25 | * 每层只把最后一个加到结果中即可 26 | */ 27 | public class BinaryTreeRightSideView0 extends BinaryTreeRightSideView { 28 | @Override 29 | public List rightSideView(TreeNode root) { 30 | List result = new ArrayList<>(); 31 | Queue queue = new LinkedList<>(); 32 | if (root == null) { 33 | return result; 34 | } 35 | queue.offer(root); 36 | while (!queue.isEmpty()) { 37 | int levelSize = queue.size(); 38 | while (levelSize > 0) { 39 | TreeNode cur = queue.poll(); 40 | if (cur.left != null) { 41 | queue.offer(cur.left); 42 | } 43 | if (cur.right != null) { 44 | queue.offer(cur.right); 45 | } 46 | levelSize--; 47 | 48 | // 最后一个元素添加到result 49 | if (levelSize == 0) { 50 | result.add(cur.val); 51 | } 52 | } 53 | } 54 | return result; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/CombinationSumIII.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * LeetCode 216. Combination Sum III 9 | * Question: https://leetcode.com/problems/combination-sum-iii/ 10 | * 关键题设:Only numbers 1 through 9 are used. Each number is used at most once. 11 | * 12 | * @auther brian 13 | * @since 2022/9/26 22:30 14 | */ 15 | public class CombinationSumIII { 16 | public List> combinationSum3(int k, int n) { 17 | return null; 18 | } 19 | 20 | /** 21 | * 回溯+剪枝 22 | */ 23 | public class CombinationSumIII0 extends CombinationSumIII { 24 | @Override 25 | public List> combinationSum3(int k, int n) { 26 | List> result = new ArrayList<>(); 27 | backtracking(result, new LinkedList<>(), 0, n, k, 1); 28 | return result; 29 | } 30 | 31 | /** 32 | * @param result 满足条件的所有结果 33 | * @param path 单个结果的路径 34 | * @param pathSum 单个路径和 35 | * @param n n 36 | * @param k k 37 | * @param startIndex 本层的一个数 38 | */ 39 | public void backtracking(List> result, LinkedList path, int pathSum, int n, int k, int startIndex) { 40 | if (path.size() == k) { 41 | if (pathSum == n) { 42 | result.add(new ArrayList<>(path)); 43 | } 44 | return; 45 | } 46 | 47 | for (int i = startIndex; i <= 9 - k + path.size() + 1 && pathSum <= n; i++) { 48 | path.push(i); 49 | backtracking(result, path, pathSum + i, n, k, i + 1); 50 | path.pop(); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/ContainerWithMostWater.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 11. Container With Most Water 5 | * Question: https://leetcode.com/problems/container-with-most-water/ 6 | * 关键题设: 无 7 | * 8 | * @auther brian 9 | * @since 2022/8/8 20:12 10 | */ 11 | public class ContainerWithMostWater { 12 | public int maxArea(int[] height) { 13 | return 0; 14 | } 15 | 16 | /** 17 | * 双指针 18 | * 正确性分析可以使用二维表来证明 19 | *

20 | * 面积=高*宽, 即 S(i,j)= min{h[i],h[j]}*(j-i) 21 | * left,right分别指向两边,然后依次向内移动高度较小的一边,直至两指针相遇。 22 | * 因为向内移动,必然会使得宽度变窄,而高度又是取小, 23 | * 所以移动高度大的一边面积一定变小,而移动高度小的一边面积可能增大 24 | *

25 | * 时间复杂度 O(n) 26 | * 空间复杂度 O(1) 27 | */ 28 | public class ContainerWithMostWater0 extends ContainerWithMostWater { 29 | @Override 30 | public int maxArea(int[] height) { 31 | int left = 0, right = height.length - 1; 32 | int area = 0; 33 | int maxArea = 0; 34 | while (left < right) { 35 | area = Math.min(height[left], height[right]) * (right - left); 36 | maxArea = Math.max(area, maxArea); 37 | if (height[left] < height[right]) { 38 | left++; 39 | } else { 40 | right--; 41 | } 42 | } 43 | return maxArea; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/CopyListWithRandomPointer.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * LeetCode 138. Copy List with Random Pointer 8 | * Question: https://leetcode.com/problems/copy-list-with-random-pointer/ 9 | * 关键题设:None of the pointers in the new list should point to nodes in the original list. 10 | * 11 | * @auther brian 12 | * @since 2022/12/11 19:47 13 | */ 14 | public class CopyListWithRandomPointer { 15 | 16 | // Definition for a Node. 17 | private static class Node { 18 | int val; 19 | Node next; 20 | Node random; 21 | 22 | public Node(int val) { 23 | this.val = val; 24 | this.next = null; 25 | this.random = null; 26 | } 27 | } 28 | 29 | /** 30 | * 哈希表,key:老节点,value: 新节点 31 | *

32 | * 时间复杂度 O(n), 遍历两遍 33 | * 空间复杂度 O(n),额外的哈希表 34 | */ 35 | class Solution { 36 | public Node copyRandomList(Node head) { 37 | Map oldToNew = new HashMap<>(); 38 | Node cur = head; 39 | while (cur != null) { 40 | Node copyOfCur = new Node(cur.val); 41 | oldToNew.put(cur, copyOfCur); 42 | cur = cur.next; 43 | } 44 | cur = head; 45 | while (cur != null) { 46 | Node copyOfCur = oldToNew.get(cur); 47 | Node copyOfNext = oldToNew.get(cur.next); 48 | Node copyOfRandom = oldToNew.get(cur.random); 49 | copyOfCur.next = copyOfNext; 50 | copyOfCur.random = copyOfRandom; 51 | cur = cur.next; 52 | } 53 | 54 | return oldToNew.get(head); 55 | 56 | } 57 | } 58 | 59 | // TODO 不使用额外空间的解法 60 | 61 | } 62 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/CountCompleteTreeNodes.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * 222. Count Complete Tree Nodes 7 | * Question: https://leetcode.com/problems/count-complete-tree-nodes/ 8 | * 关键题设: 无 9 | * 10 | * @auther brian 11 | * @since 2022/9/3 16:07 12 | */ 13 | public class CountCompleteTreeNodes { 14 | public int countNodes(TreeNode root) { 15 | return 0; 16 | } 17 | 18 | /** 19 | * 递归,后序遍历 20 | *

21 | * 1.如果为空 或者 是满二叉树,直接可通过公式得到节点个数 22 | * 2.否则,返回左子树节点个数和右子树节点个数,求和得到当前根节点下的节点个数 23 | *

24 | * 时间复杂度:O(log n × log n),深度h=log n, 25 | * 最差情况:只缺最后一个节点就是满二叉树,则每次遍历深度的时间复杂度为 h,h-1,h-2,...,1,加起来是h^2 26 | * 空间复杂度:O(log n) 27 | */ 28 | public class CountCompleteTreeNodes0 extends CountCompleteTreeNodes { 29 | @Override 30 | public int countNodes(TreeNode root) { 31 | // 终止条件 32 | if (root == null) { 33 | return 0; 34 | } 35 | TreeNode left = root.left; 36 | TreeNode right = root.right; 37 | int leftDepth = 0; 38 | int rightDepth = 0; 39 | while (left != null) { 40 | left = left.left; 41 | leftDepth++; 42 | } 43 | while (right != null) { 44 | right = right.right; 45 | rightDepth++; 46 | } 47 | 48 | // 说明是满二叉树 49 | if (leftDepth == rightDepth) { 50 | // 注意运算符优先级 51 | return (2 << leftDepth) - 1; 52 | } 53 | 54 | // 非满二叉树 55 | // 本层逻辑 56 | return countNodes(root.left) + countNodes(root.right) + 1; 57 | } 58 | } 59 | 60 | 61 | // TODO 二分查找的方法 62 | // https://leetcode.cn/problems/count-complete-tree-nodes/solution/wan-quan-er-cha-shu-de-jie-dian-ge-shu-by-leetco-2/ 63 | } 64 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/DeleteOperationForTwoStrings.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 583. Delete Operation for Two Strings 5 | * Question: https://leetcode.com/problems/delete-operation-for-two-strings/ 6 | * 关键题设: In one step, you can delete exactly one character in either string. 7 | * 8 | * @auther brian 9 | * @since 2022/8/24 23:46 10 | */ 11 | public class DeleteOperationForTwoStrings { 12 | 13 | public int minDistance(String word1, String word2) { 14 | return 0; 15 | } 16 | 17 | /** 18 | * 思路1:先根据 1143. Longest Common Subsequence 求最长公共子序列长度lcs 19 | * 然后 word1.len+word2.len- lcs*2 就是结果 20 | *

21 | * dp[i+1][j+1] 表示word1的前0~i个字符 和 word2的前0~j个字符的最长公共自序列的长度 22 | */ 23 | public class DeleteOperationForTwoStrings0 extends DeleteOperationForTwoStrings { 24 | @Override 25 | public int minDistance(String word1, String word2) { 26 | int[][] dp = new int[word1.length() + 1][word2.length() + 1]; 27 | for (int i = 0; i < word1.length(); i++) { 28 | for (int j = 0; j < word2.length(); j++) { 29 | if (word1.charAt(i) == word2.charAt(j)) { 30 | dp[i + 1][j + 1] = dp[i][j] + 1; 31 | } else { 32 | dp[i + 1][j + 1] = Math.max(dp[i + 1][j], dp[i][j + 1]); 33 | } 34 | } 35 | } 36 | return word1.length() + word2.length() - 2 * dp[word1.length()][word2.length()]; 37 | } 38 | } 39 | 40 | // TODO 按正常DP解,不借助最长公共子序列长度lcs 41 | } 42 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/FlattenBinaryTreeToLinkedList.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 114. Flatten Binary Tree to Linked List 7 | * Question: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/ 8 | * 关键题设: preorder 9 | * 10 | * @auther brian 11 | * @since 2022/12/5 20:51 12 | */ 13 | public class FlattenBinaryTreeToLinkedList { 14 | 15 | /** 16 | * 递归解法 17 | */ 18 | class Solution { 19 | public void flatten(TreeNode root) { 20 | if (root == null) { 21 | return; 22 | } 23 | recursiveFlatten(root); 24 | } 25 | 26 | /** 27 | * 返回链表的最后一个节点(避免遍历链表) 28 | * 29 | * @param root 非空 30 | * @return 链表的最后一个节点 31 | */ 32 | public TreeNode recursiveFlatten(TreeNode root) { 33 | // 叶子节点 34 | if (root.left == null && root.right == null) { 35 | return root; 36 | } 37 | 38 | // flatten左子树 39 | TreeNode leftEnd = null; 40 | if (root.left != null) { 41 | leftEnd = recursiveFlatten(root.left); 42 | } 43 | 44 | // flatten右子树 45 | TreeNode rightEnd = null; 46 | if (root.right != null) { 47 | rightEnd = recursiveFlatten(root.right); 48 | } 49 | 50 | // 更新指向 51 | if (leftEnd != null) { 52 | TreeNode rightStart = root.right; 53 | root.right = root.left; 54 | root.left = null; 55 | leftEnd.right = rightStart; 56 | } 57 | 58 | return rightEnd == null ? leftEnd : rightEnd; 59 | 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/GroupAnagrams.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * LeetCode 49. Group Anagrams 11 | * Question: https://leetcode.com/problems/group-anagrams/ 12 | * 关键题设: 无 13 | * 14 | * @auther brian 15 | * @since 2022/12/2 22:49 16 | */ 17 | public class GroupAnagrams { 18 | 19 | /** 20 | * 排序 21 | */ 22 | class Solution0 { 23 | public List> groupAnagrams(String[] strs) { 24 | Map> map = new HashMap<>(); 25 | for (int i = 0; i < strs.length; i++) { 26 | char[] chars = strs[i].toCharArray(); 27 | Arrays.sort(chars); 28 | String asc = new String(chars); 29 | 30 | map.computeIfAbsent(asc, k -> new ArrayList()); 31 | 32 | List group = map.get(asc); 33 | group.add(strs[i]); 34 | } 35 | return new ArrayList<>(map.values()); 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/JumpGame.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 55. Jump Game 5 | * Question: https://leetcode.com/problems/jump-game/ 6 | * 关键题设: 无 7 | * 8 | * @auther brian 9 | * @since 2022/8/16 21:40 10 | */ 11 | public class JumpGame { 12 | public boolean canJump(int[] nums) { 13 | return false; 14 | } 15 | 16 | /** 17 | * 贪心 18 | *

19 | * 对于每个可到达的i, i+nums[i] 就是i这个格子可触达的最远处,和当前最远maxReach取大者即可 20 | * 依次遍历每个可到达的i,不断更新maxReach即可。可到达的含义为:i<=maxReach 21 | *

22 | * 初始化:在第0个格子,maxReach=0+nums[0] 23 | *

24 | * 时间复杂度 O(n) 25 | * 空间复杂度 O(1) 26 | */ 27 | public class JumpGame0 extends JumpGame { 28 | @Override 29 | public boolean canJump(int[] nums) { 30 | int maxReach = nums[0]; 31 | for (int i = 1; i <= maxReach && i < nums.length; i++) { 32 | maxReach = Math.max(i + nums[i], maxReach); 33 | } 34 | return maxReach >= nums.length - 1; 35 | } 36 | } 37 | 38 | public class JumpGame1 extends JumpGame { 39 | @Override 40 | public boolean canJump(int[] nums) { 41 | int maxReach = 0; 42 | for (int i = 0; i <= maxReach; i++) { 43 | maxReach = Math.max(i + nums[i], maxReach); 44 | if (maxReach >= nums.length - 1) { 45 | return true; 46 | } 47 | } 48 | return maxReach >= nums.length - 1; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/JumpGameII.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 45. Jump Game II 5 | * Question: https://leetcode.com/problems/jump-game-ii/ 6 | * 关键题设: non-negative integers, assume that you can always reach the last index. 7 | * 8 | * @auther brian 9 | * @since 2022/8/10 22:42 10 | */ 11 | public class JumpGameII { 12 | public int jump(int[] nums) { 13 | return 0; 14 | } 15 | 16 | /** 17 | * DP? 18 | * 1. dp数组下标及含义:dp[i] 表示到达下标i的最小跳数 19 | * 2. 递推公式:dp[i] = min{dp[j]+1} ,其中 j=i 20 | * 3. dp数组初始化: dp[0]=0, dp[i]=Int.Max 21 | * 4. 遍历顺序:从左到右 22 | */ 23 | public class JumpGameII0 extends JumpGameII { 24 | @Override 25 | public int jump(int[] nums) { 26 | int[] dp = new int[nums.length]; 27 | dp[0] = 0; 28 | // 初始化 29 | for (int i = 1; i < nums.length; i++) { 30 | dp[i] = Integer.MAX_VALUE; 31 | } 32 | 33 | for (int i = 0; i < nums.length; i++) { 34 | for (int step = 1; step <= nums[i]; step++) { 35 | if (i + step < nums.length) { 36 | dp[i + step] = Math.min(dp[i + step], dp[i] + 1); 37 | } 38 | } 39 | } 40 | 41 | return dp[nums.length - 1]; 42 | } 43 | } 44 | 45 | /** 46 | * 贪心 47 | *

48 | * TODO 49 | */ 50 | public class JumpGameII1 extends JumpGameII { 51 | @Override 52 | public int jump(int[] nums) { 53 | return super.jump(nums); 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/KthSmallestElementInBST.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * LeetCode 230. Kth Smallest Element in a BST 10 | * Question: https://leetcode.com/problems/kth-smallest-element-in-a-bst/ 11 | * 关键题设:无 12 | * 13 | * @auther brian 14 | * @since 2022/5/17 21:45 15 | */ 16 | public class KthSmallestElementInBST { 17 | public int kthSmallest(TreeNode root, int k) { 18 | return 0; 19 | } 20 | 21 | /** 22 | * 常规解法:中序遍历BST,到第k个即可。 23 | *

24 | * 中序遍历采用递归实现 25 | */ 26 | public static class KthSmallestElementInBST0 extends KthSmallestElementInBST { 27 | @Override 28 | public int kthSmallest(TreeNode root, int k) { 29 | List list = new ArrayList<>(); 30 | inorder(list, root, k); 31 | return list.get(list.size() - 1); 32 | } 33 | 34 | public boolean inorder(List list, TreeNode tree, int k) { 35 | if (tree == null) { 36 | return false; 37 | } 38 | if (inorder(list, tree.left, k)) { 39 | return true; 40 | } 41 | 42 | list.add(tree.val); 43 | if (list.size() == k) { 44 | return true; 45 | } 46 | 47 | if (inorder(list, tree.right, k)) { 48 | return true; 49 | } 50 | return false; 51 | } 52 | } 53 | 54 | // TODO 看看其他解法 55 | } 56 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/LinkedListCycleII.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.ListNode; 4 | 5 | /** 6 | * LeetCode 142. Linked List Cycle II 7 | * Question: https://leetcode.com/problems/linked-list-cycle-ii/ 8 | * 关键题设:无 9 | * 10 | * @auther brian 11 | * @since 2022/12/11 20:19 12 | */ 13 | public class LinkedListCycleII { 14 | 15 | /** 16 | * 时间复杂度 O(n), 快慢指针相遇时,慢指针走过的节点不会超过链表长度n;相遇后,慢指针走过的节点也不会超过链表长度n 17 | */ 18 | public class Solution { 19 | public ListNode detectCycle(ListNode head) { 20 | if (head == null) { 21 | return null; 22 | } 23 | ListNode fast = head; 24 | ListNode slow = head; 25 | while (fast != null) { 26 | fast = fast.next; 27 | if (fast != null) { 28 | slow = slow.next; 29 | fast = fast.next; 30 | } else { 31 | return null; 32 | } 33 | 34 | // 快慢指针相遇说明有有环 35 | if (slow == fast) { 36 | ListNode pointer = head; 37 | while (slow != pointer) { 38 | pointer = pointer.next; 39 | slow = slow.next; 40 | } 41 | return pointer; 42 | } 43 | 44 | } 45 | return null; 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/LongestConsecutiveSequence.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.HashSet; 4 | 5 | /** 6 | * LeetCode 128. Longest Consecutive Sequence 7 | * Question: https://leetcode.com/problems/longest-consecutive-sequence/ 8 | * 关键题设:runs in O(n) time. 9 | * 10 | * @auther brian 11 | * @since 2022/9/6 23:59 12 | */ 13 | public class LongestConsecutiveSequence { 14 | public int longestConsecutive(int[] nums) { 15 | return 0; 16 | } 17 | 18 | /** 19 | * 哈希表 20 | *

21 | * 先构建哈希集合,用于去重; 22 | * 再依次遍历其中的元素num:只统计num-1不在其中时,一直next,看nums++是否在哈希集合中,统计next的次数 23 | * 1)如果num-1在里面,则忽略跳过 24 | * 2)如果num-1不在里面,则每次查看看num是否在里面 25 | * 26 | *

27 | * 时间复杂度:O(n) 28 | * 空间复杂度:O(n) 29 | */ 30 | public class LongestConsecutiveSequence0 extends LongestConsecutiveSequence { 31 | @Override 32 | public int longestConsecutive(int[] nums) { 33 | // 构建哈希Set 34 | HashSet hashSet = new HashSet<>(); 35 | for (int i = 0; i < nums.length; i++) { 36 | hashSet.add(nums[i]); 37 | } 38 | int maxCount = 0; 39 | // 遍历 40 | for (int num : hashSet) { 41 | if (!hashSet.contains(num - 1)) { 42 | // 进入统计循环 43 | int curCount = 1; 44 | int cur = num; 45 | while (hashSet.contains(++cur)) { 46 | curCount++; 47 | } 48 | maxCount = Math.max(maxCount, curCount); 49 | } 50 | // else 忽略 51 | } 52 | return maxCount; 53 | } 54 | } 55 | 56 | // TODO 其他解法 57 | } 58 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/LongestPalindromicSubsequence.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 516. Longest Palindromic Subsequence 5 | * Question: https://leetcode.com/problems/longest-palindromic-subsequence/ 6 | * 关键题设: 无 7 | * 8 | * @auther brian 9 | * @since 2022/8/30 22:54 10 | */ 11 | public class LongestPalindromicSubsequence { 12 | public int longestPalindromeSubseq(String s) { 13 | return 0; 14 | } 15 | 16 | /** 17 | * DP 18 | *

19 | * 1. dp数组以及下标含义:dp[i][j] 表示 s[i...j] 的回文子序列的最大长度 20 | * 2. 递推关系: 21 | * 如果 s[i]==s[j],则 dp[i][j] = dp[i+1][j-1]+2,表示s[i]和s[j]分别作为新的回文子序列的两端 22 | * 如果 s[i]!=s[j],则 dp[i][j] = max{dp[i+1][j],dp[i][j-1]}, 表示取s[i+1...j]和s[i...j-1]的回文子序列长度的较大者 23 | * 3. 初始化:i==j时,dp[i][j]=1 24 | * 4. 遍历顺序:i从大到小,j从小到大,且i<=j,所以只需要上半个矩阵 25 | */ 26 | public class LongestPalindromicSubsequence0 extends LongestPalindromicSubsequence { 27 | @Override 28 | public int longestPalindromeSubseq(String s) { 29 | int[][] dp = new int[s.length()][s.length()]; 30 | for (int i = s.length() - 1; i >= 0; i--) { 31 | for (int j = i; j < s.length(); j++) { 32 | if (i == j) { 33 | dp[i][j] = 1; 34 | } else if (s.charAt(i) == s.charAt(j)) { 35 | // 即使i+1>j-1时,dp[i + 1][j - 1]=0, 所以dp[i][j]=2,即"aa",i=0,j=1,dp[0][1]=dp[1][0]+2=2这种情况 36 | dp[i][j] = dp[i + 1][j - 1] + 2; 37 | } else { 38 | dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]); 39 | } 40 | } 41 | } 42 | return dp[0][s.length() - 1]; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/LongestSubstringWithoutRepeatingCharacters.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * LeetCode 3. Longest Substring Without Repeating Characters 8 | * Question: https://leetcode.com/problems/longest-substring-without-repeating-characters/ 9 | * 关键题设: 无 10 | * 11 | * @auther brian 12 | * @since 2022/11/30 23:37 13 | */ 14 | public class LongestSubstringWithoutRepeatingCharacters { 15 | 16 | public int lengthOfLongestSubstring(String s) { 17 | return 0; 18 | } 19 | 20 | /** 21 | * 滑动窗口+hash表 22 | *

23 | * 测试用例:"tmmzuxt" 24 | */ 25 | public class LongestSubstringWithoutRepeatingCharacters0 extends LongestSubstringWithoutRepeatingCharacters { 26 | @Override 27 | public int lengthOfLongestSubstring(String s) { 28 | char[] chars = s.toCharArray(); 29 | Map exist = new HashMap<>(); 30 | int maxLen = 0; 31 | int start = 0; 32 | 33 | for (int i = 0; i < chars.length; i++) { 34 | Integer lastIndex = exist.get(chars[i]); 35 | if (lastIndex == null || lastIndex < start) { 36 | // 未出现过,或者出现在左指针之前,直接计算length 37 | maxLen = Math.max(i - start + 1, maxLen); 38 | } else { 39 | // 当前chars[i]出现在start后,则需要右移start 40 | start = lastIndex + 1; 41 | } 42 | exist.put(chars[i], i); 43 | } 44 | return maxLen; 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/LowestCommonAncestorOfBinaryTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 236. Lowest Common Ancestor of a Binary Tree 7 | * Question: https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/ 8 | * 关键题设:All Node.val are unique. p != q 9 | * 10 | * @auther brian 11 | * @since 2022/9/7 23:25 12 | */ 13 | public class LowestCommonAncestorOfBinaryTree { 14 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 15 | return null; 16 | } 17 | 18 | /** 19 | * LCA 20 | * 递归 21 | * 后序遍历,回溯 22 | */ 23 | public class LowestCommonAncestorOfBinaryTree0 extends LowestCommonAncestorOfBinaryTree { 24 | @Override 25 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 26 | if (root == null) { 27 | return null; 28 | } 29 | 30 | TreeNode left = lowestCommonAncestor(root.left, p, q); 31 | TreeNode right = lowestCommonAncestor(root.right, p, q); 32 | 33 | if (root == p || root == q) { 34 | return root; 35 | } 36 | 37 | // 一边一个 38 | if (left != null && right != null) { 39 | return root; 40 | } else if (left != null) { 41 | return left; 42 | } else if (right != null) { 43 | return right; 44 | } else { 45 | return null; 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/MaximumLengthOfRepeatedSubarray.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 718. Maximum Length of Repeated Subarray 5 | * Question: https://leetcode.com/problems/maximum-length-of-repeated-subarray/ 6 | * 关键题设: 无 7 | * 8 | * @auther brian 9 | * @since 2022/7/19 22:28 10 | */ 11 | public class MaximumLengthOfRepeatedSubarray { 12 | public int findLength(int[] nums1, int[] nums2) { 13 | return 0; 14 | } 15 | 16 | /** 17 | * DP 18 | *

19 | * 1. dp数组下标以及含义:dp[i+1][j+1] 表示nums1数组以下标i结尾,nums2数数组以下标j结尾时,最长重复子数组长度。 20 | * 即 dp[i][j] 表示nums1数组以下标i-1结尾,nums2数数组以下标j-1结尾时,最长重复子数组长度。 21 | * 2. 递推关系:dp[i+1][j+1] = nums1[i]== nums2[j]? dp[i][j]+1 : 0 22 | * 3. 初始化:dp[i][0]=0, dp[0][j]=0 23 | * 4. 遍历顺序:从左到右 24 | */ 25 | public static class MaximumLengthOfRepeatedSubarray0 extends MaximumLengthOfRepeatedSubarray { 26 | @Override 27 | public int findLength(int[] nums1, int[] nums2) { 28 | int[][] dp = new int[nums1.length + 1][nums2.length + 1]; 29 | int maxLen = 0; 30 | for (int i = 0; i < nums1.length; i++) { 31 | for (int j = 0; j < nums2.length; j++) { 32 | if (nums1[i] == nums2[j]) { 33 | dp[i + 1][j + 1] = dp[i][j] + 1; 34 | } 35 | if (dp[i + 1][j + 1] > maxLen) { 36 | maxLen = dp[i + 1][j + 1]; 37 | } 38 | } 39 | } 40 | return maxLen; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/MinStack.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * LeetCode 155. Min Stack 7 | * Question: https://leetcode.com/problems/min-stack/ 8 | * 关键题设:in constant time. 9 | * 10 | * @auther brian 11 | * @since 2022/12/11 21:41 12 | */ 13 | public class MinStack { 14 | 15 | /** 16 | * 原始栈 17 | */ 18 | Stack stack = new Stack<>(); 19 | /** 20 | * 最小值栈 21 | */ 22 | Stack min = new Stack<>(); 23 | 24 | public MinStack() { 25 | 26 | } 27 | 28 | public void push(int val) { 29 | stack.push(val); 30 | if (min.empty() || min.peek() > val) { 31 | min.push(val); 32 | } else { 33 | int minVal = min.peek(); 34 | min.push(minVal); 35 | } 36 | } 37 | 38 | public void pop() { 39 | stack.pop(); 40 | min.pop(); 41 | } 42 | 43 | public int top() { 44 | return stack.peek(); 45 | } 46 | 47 | public int getMin() { 48 | return min.peek(); 49 | } 50 | 51 | /** 52 | * Your MinStack object will be instantiated and called as such: 53 | * MinStack obj = new MinStack(); 54 | * obj.push(val); 55 | * obj.pop(); 56 | * int param_3 = obj.top(); 57 | * int param_4 = obj.getMin(); 58 | */ 59 | } 60 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/MinimumPathSum.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 64. Minimum Path Sum 5 | * Question: https://leetcode.com/problems/minimum-path-sum/ 6 | * 关键题设: 无 7 | * 8 | * @auther brian 9 | * @since 2022/12/4 23:07 10 | */ 11 | public class MinimumPathSum { 12 | /** 13 | * DP 14 | * 直接使用一维数组解决 15 | *

16 | * 注意第一排初始化。题设是从最左上 到 最 右下。 17 | */ 18 | class Solution { 19 | public int minPathSum(int[][] grid) { 20 | int[] dp = new int[grid[0].length]; 21 | // 初始化 22 | dp[0] = grid[0][0]; 23 | for (int j = 1; j < grid[0].length; j++) { 24 | dp[j] = dp[j - 1] + grid[0][j]; 25 | } 26 | 27 | for (int i = 1; i < grid.length; i++) { 28 | dp[0] = dp[0] + grid[i][0]; 29 | for (int j = 1; j < grid[0].length; j++) { 30 | dp[j] = Math.min(dp[j - 1] + grid[i][j], dp[j] + grid[i][j]); 31 | } 32 | } 33 | return dp[grid[0].length - 1]; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/PalindromePartitioning.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * LeetCode 131. Palindrome Partitioning 9 | * Question: https://leetcode.com/problems/palindrome-partitioning/ 10 | * 关键题设: 无 11 | * 12 | * @auther brian 13 | * @since 2022/12/5 21:01 14 | */ 15 | public class PalindromePartitioning { 16 | /** 17 | * 回溯 18 | *

19 | * 时间复杂度 O(n * 2^n) 20 | * 空间复杂度 O(n) 递归调用栈的高度为 n 21 | */ 22 | class Solution { 23 | public List> partition(String s) { 24 | List> result = new ArrayList<>(); 25 | char[] charArr = s.toCharArray(); 26 | backtracking(result, new LinkedList(), charArr, 0); 27 | return result; 28 | } 29 | 30 | public void backtracking(List> result, LinkedList path, char[] charArr, int start) { 31 | if (start == charArr.length) { 32 | result.add(new ArrayList<>(path)); 33 | return; 34 | } 35 | 36 | for (int i = start; i < charArr.length; i++) { 37 | if (!isPalindrome(charArr, start, i)) { 38 | continue; 39 | } 40 | path.addLast(new String(charArr, start, i - start + 1)); 41 | backtracking(result, path, charArr, i + 1); 42 | path.removeLast(); 43 | } 44 | 45 | } 46 | 47 | public boolean isPalindrome(char[] charArr, int start, int end) { 48 | while (start <= end) { 49 | if (charArr[start++] != charArr[end--]) { 50 | return false; 51 | } 52 | } 53 | return true; 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/Permutations.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * LeetCode 46. Permutations 10 | * Question: https://leetcode.com/problems/permutations/ 11 | * 关键题设: 无 12 | * 13 | * @auther brian 14 | * @since 2022/12/1 23:08 15 | */ 16 | public class Permutations { 17 | 18 | public List> permute(int[] nums) { 19 | return null; 20 | } 21 | 22 | /** 23 | * 回溯 24 | */ 25 | public class Permutations0 extends Permutations { 26 | @Override 27 | public List> permute(int[] nums) { 28 | List> result = new ArrayList<>(); 29 | List numbers = new ArrayList(); 30 | for (int num : nums) { 31 | numbers.add(num); 32 | } 33 | 34 | backtracking(result, new LinkedList<>(), numbers, 0); 35 | return result; 36 | } 37 | 38 | /** 39 | * @param result 所有排列 40 | * @param path 已经被安置在当前排列的数字 41 | * @param nums 使用List是为了使用Collections.swap的API 42 | * @param start 当前从数组哪个位置开始是未使用过的数字 43 | */ 44 | public void backtracking(List> result, LinkedList path, List nums, int start) { 45 | if (start == nums.size()) { 46 | result.add(new ArrayList<>(path)); 47 | } 48 | 49 | for (int i = start; i < nums.size(); i++) { 50 | path.push(nums.get(i)); 51 | Collections.swap(nums, i, start); 52 | backtracking(result, path, nums, start + 1); 53 | Collections.swap(nums, start, i); 54 | path.pop(); 55 | } 56 | } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/RotateImage.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 48. Rotate Image 5 | * Question: https://leetcode.com/problems/rotate-image/ 6 | * 关键题设: in-place 7 | * 8 | * @auther brian 9 | * @since 2022/12/1 23:43 10 | */ 11 | public class RotateImage { 12 | 13 | public void rotate(int[][] matrix) { 14 | 15 | } 16 | 17 | /** 18 | * 纯数学推导: 19 | * 假设矩阵为n*n 20 | * 则顺时针旋转90度相当于先沿对角线反转,再沿垂直中线反转 21 | * 即 22 | * 1. swap (i,j), (j,i) 23 | * 2. swap (i,j), (i ,n-1-j) 24 | */ 25 | public class RotateImage0 extends RotateImage { 26 | @Override 27 | public void rotate(int[][] matrix) { 28 | int n = matrix.length; 29 | 30 | for (int i = 0; i < n; i++) { 31 | for (int j = 0; j < n; j++) { 32 | // 上右 三角 33 | if (i < j) { 34 | swap(matrix, i, j, j, i); 35 | } 36 | } 37 | } 38 | 39 | for (int i = 0; i < n; i++) { 40 | for (int j = 0; j < n / 2; j++) { 41 | swap(matrix, i, j, i, n - 1 - j); 42 | } 43 | } 44 | 45 | } 46 | 47 | public void swap(int[][] matrix, int i1, int j1, int i2, int j2) { 48 | int tmp = matrix[i1][j1]; 49 | matrix[i1][j1] = matrix[i2][j2]; 50 | matrix[i2][j2] = tmp; 51 | } 52 | } 53 | 54 | // TODO 一题多解 55 | } 56 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/Search2DMatrix.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 74. Search a 2D Matrix 5 | * Question: https://leetcode.com/problems/search-a-2d-matrix/ 6 | * 关键题设: 无 7 | * 8 | * @auther brian 9 | * @since 2022/12/5 19:52 10 | */ 11 | public class Search2DMatrix { 12 | /** 13 | * 二分查找 14 | * 将二维数组看成一维的,index -> matrix[i][j] 15 | *

16 | * 时间复杂度 O(log m*n) 17 | * 空间复杂度 O(1) 18 | */ 19 | class Solution { 20 | public boolean searchMatrix(int[][] matrix, int target) { 21 | // index: 0~m*n 22 | int m = matrix.length; 23 | int n = matrix[0].length; 24 | int left = 0; 25 | int right = m * n - 1; 26 | while (left <= right) { 27 | int mid = (left + right) / 2; 28 | if (getValue(matrix, mid, n) == target) { 29 | return true; 30 | } else if (getValue(matrix, mid, n) < target) { 31 | left = mid + 1; 32 | } else { 33 | right = mid - 1; 34 | } 35 | } 36 | return false; 37 | } 38 | 39 | private int getValue(int[][] matrix, int index, int n) { 40 | int i = index / n; 41 | int j = index % n; 42 | return matrix[i][j]; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/SetMatrixZeroes.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * LeetCode 73. Set Matrix Zeroes 10 | * Question: https://leetcode.com/problems/set-matrix-zeroes/ 11 | * 关键题设: 无 12 | * 13 | * @auther brian 14 | * @since 2022/12/5 19:36 15 | */ 16 | public class SetMatrixZeroes { 17 | /** 18 | * 非最优解, m*n的矩阵 19 | *

20 | * 时间复杂度 O(m*n) 21 | * 空间复杂度 O(m+n) 22 | */ 23 | class Solution { 24 | public void setZeroes(int[][] matrix) { 25 | Map rows = new HashMap<>(); 26 | List cols = new ArrayList<>(); 27 | int m = matrix.length; 28 | int n = matrix[0].length; 29 | for (int i = 0; i < m; i++) { 30 | for (int j = 0; j < n; j++) { 31 | if (matrix[i][j] == 0) { 32 | rows.put(i, true); 33 | cols.add(j); 34 | } 35 | } 36 | } 37 | 38 | for (int i = 0; i < m; i++) { 39 | if (rows.get(i) != null) { 40 | for (int j = 0; j < n; j++) { 41 | matrix[i][j] = 0; 42 | } 43 | } else { 44 | for (int j : cols) { 45 | matrix[i][j] = 0; 46 | } 47 | } 48 | } 49 | 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/SortColors.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 75. Sort Colors 5 | * Question: https://leetcode.com/problems/sort-colors/ 6 | * 关键题设:without using the library's sort function. 7 | * 8 | * @auther brian 9 | * @since 2022/8/9 23:12 10 | */ 11 | public class SortColors { 12 | public void sortColors(int[] nums) { 13 | 14 | } 15 | 16 | /** 17 | * 思路:快排的子过程 partition 18 | *

19 | * 维护两个指针: 20 | * p0表示 [0,p0)下标范围全是0 21 | * p2表示 (p2,n-1]下标范围全是2 22 | * 初始化: p0=0, p2=n-1, 这样两个区间范围初始都是空 23 | *

24 | * 依次遍历i, 25 | * - 遇到0就交换nums[i]和nums[p0],同时,p0 和 i 都向后移一位(因为一定有i>=p0, 所以此时i指向的是之前的nums[p0],且一定遇到过,不可能是2,无论是1还是0,都无需再次判断) 26 | * - 遇到2就交换nums[i]和nums[p2],只 p2 向前移一位,i不动(因为交换后,i指向的是之前的nums[p2],值未知,可能为0,需要再次判断,故i不能++) 27 | * - 遇到1就不需要交换,i 向后移一位 28 | * 当i>p2,结束遍历 29 | */ 30 | public class SortColors0 extends SortColors { 31 | @Override 32 | public void sortColors(int[] nums) { 33 | int p0 = 0; 34 | int p2 = nums.length - 1; 35 | for (int i = 0; i <= p2; ) { 36 | if (nums[i] == 0) { 37 | swap(nums, i, p0); 38 | p0++; 39 | i++; 40 | } else if (nums[i] == 2) { 41 | swap(nums, i, p2); 42 | p2--; 43 | // i 不移动 44 | } else { 45 | i++; 46 | } 47 | } 48 | } 49 | 50 | private void swap(int[] nums, int i, int j) { 51 | int temp = nums[i]; 52 | nums[i] = nums[j]; 53 | nums[j] = temp; 54 | } 55 | 56 | } 57 | 58 | // TODO 补充其他解法 59 | 60 | } 61 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/Subsets.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * LeetCode 78. Subsets 9 | * Question: https://leetcode.com/problems/subsets/ 10 | * 关键题设: 无 11 | * 12 | * @auther brian 13 | * @since 2022/12/5 20:07 14 | */ 15 | public class Subsets { 16 | 17 | /** 18 | * 回溯 19 | */ 20 | class Solution { 21 | public List> subsets(int[] nums) { 22 | List> result = new ArrayList<>(); 23 | backtracking(result, new LinkedList<>(), nums, 0); 24 | return result; 25 | } 26 | 27 | public void backtracking(List> result, LinkedList path, int[] nums, int startIndex) { 28 | if (startIndex == nums.length) { 29 | result.add(new ArrayList<>(path)); 30 | return; 31 | } 32 | 33 | // 不用 nums[startIndex] 34 | backtracking(result, path, nums, startIndex + 1); 35 | //用 nums[startIndex] 36 | path.push(nums[startIndex]); 37 | backtracking(result, path, nums, startIndex + 1); 38 | path.pop(); 39 | 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/UncrossedLines.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 1035. Uncrossed Lines 5 | * Question: https://leetcode.com/problems/uncrossed-lines/ 6 | * 关键题设: 无 7 | * 8 | * @auther brian 9 | * @since 2022/7/21 21:35 10 | */ 11 | public class UncrossedLines { 12 | public int maxUncrossedLines(int[] nums1, int[] nums2) { 13 | return 0; 14 | } 15 | 16 | /** 17 | * DP,该题可以转化为最长公共子序列,见 LeetCode 1143. Longest Common Subsequence 18 | */ 19 | public static class UncrossedLines0 extends UncrossedLines { 20 | @Override 21 | public int maxUncrossedLines(int[] nums1, int[] nums2) { 22 | int[][] dp = new int[nums1.length + 1][nums2.length + 1]; 23 | for (int i = 0; i < nums1.length; i++) { 24 | for (int j = 0; j < nums2.length; j++) { 25 | if (nums1[i] == nums2[j]) { 26 | dp[i + 1][j + 1] = dp[i][j] + 1; 27 | } else { 28 | dp[i + 1][j + 1] = Math.max(dp[i + 1][j], dp[i][j + 1]); 29 | } 30 | } 31 | } 32 | return dp[nums1.length][nums2.length]; 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/UniqueBinarySearchTrees.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 96. Unique Binary Search Trees 5 | * Question:https://leetcode.com/problems/unique-binary-search-trees/ 6 | * 关键题设:无 7 | * 8 | * @auther brian 9 | * @since 2022/6/14 23:43 10 | */ 11 | public class UniqueBinarySearchTrees { 12 | 13 | public int numTrees(int n) { 14 | return 0; 15 | } 16 | 17 | /** 18 | * 思路:动态规划 19 | *

20 | * BST节点个数为i时的结构数记为 dp[i], 则dp[i]= ∑ 根节点为j的结构数, j依次取i个节点的每一个。 21 | * 当根节点为j (1<=j<=i)时,假设小于j的有l个节点,大于j的有r个节点 22 | * 则左子树就是这l个节点构成的BST,右子树就是这r个节点构成的BST,且l+r+1=i 23 | * 所以 当根节点为j时的结构数=dp[l]*dp[r] 24 | * 当j依次取i个节点中的每一个节点,l和r会分别依次 +1 和 -1。 25 | * 将这些 dp[l]*dp[r] 求和,即可得到 dp[i] 26 | *

27 | * 搜索二叉树的特点:左子树的所有节点小于根节点,左子树的所有节点大于根节点 28 | *

29 | * 例子: 30 | * dp[0] = 1 表示子树为空的情况 31 | * dp[1] = 1 可以直观看出,也由 dp[0]*dp[0] 推导出。写代码时注意不要重复计算 dp[1] 32 | * dp[2] = dp[0]*dp[1] + dp[1]*dp[0]; 33 | * dp[3] = dp[0]*dp[2] + dp[1]+dp1[1] + dp[2]*dp[0] 34 | * 35 | *

36 | * 时间复杂度 O(n^2) 37 | * 空间复杂度 O(n), 由于递推关系中,历史所有规模的子问题都需要记录,所以没法简化了。 38 | */ 39 | public class UniqueBinarySearchTrees0 extends UniqueBinarySearchTrees { 40 | @Override 41 | public int numTrees(int n) { 42 | int[] dp = new int[n + 1]; 43 | dp[0] = 1; 44 | // dp[1] = 1; // i从1循环则不需要 45 | for (int i = 1; i <= n; i++) { 46 | for (int l = 0; l < i; l++) { 47 | // 右子树节点个数 r = i - 1 - l 48 | dp[i] = dp[i] + dp[l] * dp[i - 1 - l]; 49 | } 50 | } 51 | return dp[n]; 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/ValidateBinarySearchTree.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import com.brianway.learning.algorithms.leetcode.common.TreeNode; 4 | 5 | /** 6 | * LeetCode 98. Validate Binary Search Tree 7 | * Question https://leetcode.com/problems/validate-binary-search-tree/ 8 | * 关键题设:无 9 | * 10 | * @auther brian 11 | * @since 2022/9/7 22:14 12 | */ 13 | public class ValidateBinarySearchTree { 14 | public boolean isValidBST(TreeNode root) { 15 | return false; 16 | } 17 | 18 | /** 19 | * 递归 20 | *

21 | * 注意:不是只比较每一层的cur > left,cur < right就完了 22 | * 需要 cur> any of left, cur < any of right 23 | *

24 | * 时间复杂度:O(n) 25 | * 空间复杂度:O(n), 递归用到了栈 26 | */ 27 | public class ValidateBinarySearchTree0 extends ValidateBinarySearchTree { 28 | @Override 29 | public boolean isValidBST(TreeNode root) { 30 | return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE); 31 | } 32 | 33 | /** 34 | * 判断root是否在区间 (min, max) 内,左开右开 35 | * 因为测试数据范围是可能到 Integer.MIN_VALUE 和 Integer.MAX_VALUE,所以这里用long 36 | * 37 | * @param root 当前节点 38 | * @param min 下限 39 | * @param max 上限 40 | * @return 是否BST 41 | */ 42 | public boolean isValidBST(TreeNode root, long min, long max) { 43 | if (root == null) { 44 | return true; 45 | } 46 | 47 | if (root.val <= min || root.val >= max) { 48 | return false; 49 | } 50 | 51 | return isValidBST(root.left, min, root.val) 52 | && isValidBST(root.right, root.val, max); 53 | } 54 | } 55 | 56 | // TODO 中序遍历,递归/迭代, 然后检查数组是否递增即可 57 | // 中序遍历可以加一个pre指针,表示上一次访问的节点 58 | // https://leetcode.cn/problems/validate-binary-search-tree/solution/zhong-xu-bian-li-qing-song-na-xia-bi-xu-miao-dong-/ 59 | 60 | } 61 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/WiggleSubsequence.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | /** 4 | * LeetCode 376. Wiggle Subsequence 5 | * Question: https://leetcode.com/problems/wiggle-subsequence/ 6 | * 关键题设: 无 7 | * 8 | * @auther brian 9 | * @since 2022/8/11 23:14 10 | */ 11 | public class WiggleSubsequence { 12 | 13 | public int wiggleMaxLength(int[] nums) { 14 | return 0; 15 | } 16 | 17 | /** 18 | * 贪心 19 | * len表示 wiggleMaxLength 20 | * 当前基准数cur 21 | * 上一次趋势lastTrend, 小于0表示递减,大于0表示递增, 22 | * 遇到同趋势的就忽略,并更新cur; 遇到不同趋势的,则len+1, 并更新cur 23 | *

24 | * 注意: 25 | * 上一次趋势的初始化问题需要注意! 26 | *

27 | * 边界情况: 28 | * [3,3,3,2,5] 29 | */ 30 | public class WiggleSubsequence0 extends WiggleSubsequence { 31 | @Override 32 | public int wiggleMaxLength(int[] nums) { 33 | int len = 1; 34 | int cur = nums[0]; 35 | int lastTrend = 0; // 假设 下标-1的元素和 nums[0]一样 36 | int trend = 0; 37 | 38 | for (int i = 1; i < nums.length; i++) { 39 | trend = nums[i] - cur; 40 | 41 | // 当Wiggle Subsequence内只有一个元素时,不管递增还是递减,只要不是相等,都len+1 42 | if (len == 1 && trend != 0) { 43 | len++; 44 | } 45 | if ((trend > 0 && lastTrend < 0) || (trend < 0 && lastTrend > 0)) { 46 | len++; 47 | } 48 | 49 | cur = nums[i]; 50 | if (trend != 0) { 51 | lastTrend = trend; 52 | } 53 | 54 | } 55 | return len; 56 | } 57 | } 58 | 59 | // TODO 用DP解 60 | 61 | } 62 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/main/java/com/brianway/learning/algorithms/leetcode/medium/WordBreak.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * LeetCode 139. Word Break 7 | * Question: https://leetcode.com/problems/word-break/ 8 | * 关键题设: 无 9 | * 10 | * @auther brian 11 | * @since 2022/7/11 21:19 12 | */ 13 | public class WordBreak { 14 | 15 | public boolean wordBreak(String s, List wordDict) { 16 | return false; 17 | } 18 | 19 | /** 20 | * DP,完全背包 21 | *

22 | * 1. dp数组下标及含义:dp[j] 表示用字典里的词能否匹配到s中从开头开始长度为j的字符 23 | * 2. 递推关系: 24 | * 如果 s[0...j-1] 以wordDict中的某个单词word结尾,则dp[j] = dp[j-word.length] || dp[j] 25 | * (这里用 或,而不是直接dp[j] = dp[j-word.length],是因为任一匹配即可,不能因为某次以单词word结尾,但dp[j-word.length]=false 而导致dp[j]被覆盖为false, 26 | * 应该只要匹配过一次true就算true) 27 | * 否则 dp[j] = false 28 | *

29 | * 3. 初始化: dp[0] = true,表示s长度为0时默认匹配。很关键 30 | * 4. 遍历顺序:外层j,从左到右,内层 wordDict。 31 | */ 32 | public static class WordBreak0 extends WordBreak { 33 | @Override 34 | public boolean wordBreak(String s, List wordDict) { 35 | boolean[] dp = new boolean[s.length() + 1]; 36 | dp[0] = true; 37 | for (int j = 1; j <= s.length(); j++) { 38 | String stageS = s.substring(0, j); 39 | for (String word : wordDict) { 40 | if (stageS.endsWith(word)) { 41 | // 之前匹配过即可 42 | dp[j] = dp[j] || dp[j - word.length()]; 43 | } 44 | } 45 | } 46 | return dp[s.length()]; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/easy/HappyNumberTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by Brian on 2016/4/30. 9 | */ 10 | public class HappyNumberTest { 11 | 12 | private HappyNumber testObject; 13 | 14 | private int[] nums = new int[] {19, 11}; 15 | 16 | private boolean[] results = new boolean[] {true, false}; 17 | 18 | @Before 19 | public void setUp() { 20 | testObject = new HappyNumber().new HappyNumber0(); 21 | } 22 | 23 | @Test 24 | public void testAll() { 25 | for (int i = 0; i < nums.length; i++) { 26 | Assert.assertEquals(results[i], testObject.isHappy(nums[i])); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/easy/MajorityElementTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by Brian on 2016/4/26. 9 | */ 10 | public class MajorityElementTest { 11 | 12 | private MajorityElement[] testObjects; 13 | 14 | @Before 15 | public void setUp() { 16 | testObjects = new MajorityElement[3]; 17 | testObjects[0] = new MajorityElement().new MajorityElement0(); 18 | testObjects[1] = new MajorityElement().new MajorityElement1(); 19 | testObjects[2] = new MajorityElement().new MajorityElement2(); 20 | } 21 | 22 | @Test 23 | public void testRemoveDuplicates() { 24 | int[] nums = new int[] {1, 1, 1, 2, 2, 2, 2, 2, 3}; 25 | int result = 2; 26 | Assert.assertEquals(result, testObjects[0].majorityElement(nums)); 27 | Assert.assertEquals(result, testObjects[1].majorityElement(nums)); 28 | Assert.assertEquals(result, testObjects[2].majorityElement(nums)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/easy/MaximumSubarrayTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import com.brianway.learning.algorithms.leetcode.medium.MaximumSubarray; 4 | import org.junit.Assert; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by Brian on 2016/4/30. 10 | */ 11 | public class MaximumSubarrayTest { 12 | 13 | private MaximumSubarray[] testObjects; 14 | 15 | @Before 16 | public void setUp() { 17 | testObjects = new MaximumSubarray[2]; 18 | testObjects[0] = new MaximumSubarray.MaximumSubarray0(); 19 | testObjects[1] = new MaximumSubarray.MaximumSubarray1(); 20 | } 21 | 22 | @Test 23 | public void testMaximumSubarray() { 24 | int[] nums = new int[] {-2, 1, -3, 4, -1, 2, 1, -5, 4}; 25 | int result = 6; 26 | Assert.assertEquals(result, testObjects[0].maxSubArray(nums)); 27 | Assert.assertEquals(result, testObjects[1].maxSubArray(nums)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/easy/PowerOfTwoTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by Brian on 2016/4/19. 9 | */ 10 | public class PowerOfTwoTest { 11 | 12 | private PowerOfTwo[] testObjects; 13 | 14 | @Before 15 | public void setUp() { 16 | testObjects = new PowerOfTwo[2]; 17 | testObjects[0] = new PowerOfTwo().new PowerOfTwo0(); 18 | testObjects[1] = new PowerOfTwo().new PowerOfTwo1(); 19 | } 20 | 21 | @Test 22 | public void testIsPowerOfTwo() { 23 | int[] nums = new int[] {0, 2, -4, 11, 16, -6}; 24 | boolean[] result = {false, true, false, false, true, false}; 25 | for (int i = 0; i < nums.length; i++) { 26 | Assert.assertEquals(result[i], testObjects[0].isPowerOfTwo(nums[i])); 27 | Assert.assertEquals(result[i], testObjects[1].isPowerOfTwo(nums[i])); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/easy/RemoveDuplicatesfromSortedArrayTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by Brian on 2016/4/26. 9 | */ 10 | public class RemoveDuplicatesfromSortedArrayTest { 11 | 12 | private RemoveDuplicatesfromSortedArray testObject; 13 | 14 | @Before 15 | public void setUp() { 16 | testObject = new RemoveDuplicatesfromSortedArray().new RemoveDuplicatesfromSortedArray0(); 17 | } 18 | 19 | @Test 20 | public void testremoveDuplicates() { 21 | int[] nums = new int[] {1, 1, 2, 2, 3, 4, 7, 7, 15}; 22 | int result = 6; 23 | Assert.assertEquals(result, testObject.removeDuplicates(nums)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/easy/ReverseStringTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by Brian on 2016/4/19. 9 | */ 10 | public class ReverseStringTest { 11 | 12 | private ReverseString testObject; 13 | 14 | @Before 15 | public void setUp() { 16 | testObject = new ReverseString().new ReverseString0(); 17 | } 18 | 19 | @Test 20 | public void testAll() { 21 | String[] origin = new String[] {"", "123", "a.", "asdfg", "asdfgh"}; 22 | String[] result = {"", "321", ".a", "gfdsa", "hgfdsa"}; 23 | // for (int i = 0; i < origin.length; i++) { 24 | // Assert.assertEquals(result[i], testObject.reverseString(origin[i])); 25 | // } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/easy/SearchInsertPositionTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | /** 11 | * @auther brian 12 | * @since 2022/5/5 22:55 13 | */ 14 | public class SearchInsertPositionTest { 15 | private SearchInsertPosition testObject; 16 | 17 | private List testcases; 18 | 19 | @Before 20 | public void setUp() { 21 | testObject = new SearchInsertPosition.SearchInsertPosition0(); 22 | 23 | testcases = Arrays.asList( 24 | Testcase.of(new int[] {1, 3, 5, 6}, 5, 2), 25 | Testcase.of(new int[] {1, 3, 5, 6}, 2, 1), 26 | Testcase.of(new int[] {1, 3, 5, 6}, 7, 4), 27 | Testcase.of(new int[] {2, 3, 5, 6}, 1, 0) 28 | ); 29 | } 30 | 31 | @Test 32 | public void testSearchInsert() { 33 | int[] nums = {1, 3, 5, 6}; 34 | int target = 5; 35 | int result = 2; 36 | Assert.assertEquals(result, testObject.searchInsert(nums, target)); 37 | } 38 | 39 | @Test 40 | public void testAll() { 41 | for (Testcase tc : testcases) { 42 | Assert.assertEquals(tc.result, testObject.searchInsert(tc.nums, tc.target)); 43 | } 44 | } 45 | 46 | private static class Testcase { 47 | int[] nums; 48 | int target; 49 | int result; 50 | 51 | private Testcase(int[] nums, int target, int result) { 52 | this.nums = nums; 53 | this.target = target; 54 | this.result = result; 55 | } 56 | 57 | public static Testcase of(int[] nums, int target, int result) { 58 | return new Testcase(nums, target, result); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/easy/TwoSumTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.easy; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by Brian on 2016/4/19. 9 | */ 10 | public class TwoSumTest { 11 | 12 | private TwoSum[] testObjects; 13 | 14 | private int[][] allNums = new int[][] { 15 | {2, 7, 11, 15}, 16 | {1, 4, 4, 5}, 17 | {2, 1, 3} 18 | }; 19 | private int[] targets = {9, 8, 4}; 20 | private int[][] results = { 21 | {0, 1}, 22 | {1, 2}, 23 | {1, 2} 24 | }; 25 | 26 | @Before 27 | public void setUp() { 28 | testObjects = new TwoSum[3]; 29 | testObjects[0] = new TwoSum().new TwoSum0(); 30 | testObjects[1] = new TwoSum().new TwoSum1(); 31 | testObjects[2] = new TwoSum().new TwoSum2(); 32 | 33 | } 34 | 35 | @Test 36 | public void testTwoSum() { 37 | int i = 2; 38 | int[] nums = allNums[i]; 39 | int target = targets[i]; 40 | int[] result = results[i]; 41 | Assert.assertArrayEquals(result, testObjects[1].twoSum(nums, target)); 42 | } 43 | 44 | @Test 45 | public void testAll() { 46 | for (int oi = 0; oi < testObjects.length; oi++) { 47 | for (int i = 0; i < targets.length; i++) { 48 | int[] nums = allNums[i]; 49 | int target = targets[i]; 50 | int[] result = results[i]; 51 | Assert.assertArrayEquals(result, testObjects[oi].twoSum(nums, target)); 52 | } 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/hard/FirstMissingPositiveTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.hard; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | /** 11 | * @auther brian 12 | * @since 2022/5/5 22:55 13 | */ 14 | public class FirstMissingPositiveTest { 15 | private FirstMissingPositive testObject; 16 | 17 | private List testcases; 18 | 19 | @Before 20 | public void setUp() { 21 | testObject = new FirstMissingPositive.FirstMissingPositive1(); 22 | 23 | testcases = Arrays.asList( 24 | Testcase.of(new int[] {1, 2, 0}, 3), 25 | Testcase.of(new int[] {3, 4, -1, 1}, 2), 26 | Testcase.of(new int[] {1, 1}, 2), 27 | Testcase.of(new int[] {7, 8, 9, 11, 12}, 1) 28 | ); 29 | } 30 | 31 | @Test 32 | public void testFirstMissingPositive() { 33 | int[] nums = {3, 4, -1, 1}; 34 | int result = 2; 35 | Assert.assertEquals(result, testObject.firstMissingPositive(nums)); 36 | } 37 | 38 | @Test 39 | public void testAll() { 40 | for (Testcase tc : testcases) { 41 | Assert.assertEquals(tc.result, testObject.firstMissingPositive(tc.nums)); 42 | } 43 | } 44 | 45 | private static class Testcase { 46 | int[] nums; 47 | int result; 48 | 49 | private Testcase(int[] nums, int result) { 50 | this.nums = nums; 51 | this.result = result; 52 | } 53 | 54 | public static Testcase of(int[] nums, int result) { 55 | return new Testcase(nums, result); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/hard/RegularExpressionMatchingTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.hard; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | public class RegularExpressionMatchingTest { 8 | private RegularExpressionMatching testObject; 9 | 10 | private String[][] sp = { 11 | {"aa", "a*"}, 12 | {"aaa", "ab*a*c*a"} 13 | }; 14 | 15 | private boolean[] results = {true, true}; 16 | 17 | @Before 18 | public void setUp() { 19 | testObject = new RegularExpressionMatching().new RegularExpressionMatching1(); 20 | } 21 | 22 | @Test 23 | public void testIsMatch() { 24 | String s = "aab"; 25 | String p = "c*a*b"; 26 | Assert.assertEquals(true, testObject.isMatch(s, p)); 27 | } 28 | 29 | @Test 30 | public void testAll() { 31 | for (int i = 0; i < sp.length; i++) { 32 | Assert.assertEquals(results[i], testObject.isMatch(sp[i][0], sp[i][1])); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/medium/FindMinimuminRotatedSortedArrayTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | public class FindMinimuminRotatedSortedArrayTest { 8 | 9 | private FindMinimuminRotatedSortedArray[] testObjects; 10 | 11 | private int[][] allNums = { 12 | {0, 1, 2, 4, 5, 6, 7}, 13 | {6, 7, 0, 1, 2, 4, 5}, 14 | {2, 4, 5, 6, 7, 0, 1} 15 | }; 16 | private int[] results = {0, 0, 0}; 17 | 18 | @Before 19 | public void setUp() { 20 | testObjects = new FindMinimuminRotatedSortedArray[2]; 21 | testObjects[0] = new FindMinimuminRotatedSortedArray().new FindMinimuminRotatedSortedArray0(); 22 | testObjects[1] = new FindMinimuminRotatedSortedArray().new FindMinimuminRotatedSortedArray1(); 23 | 24 | } 25 | 26 | @Test 27 | public void testFindMin() { 28 | int[] nums = {4, 5, 6, 7, 0, 1, 2}; 29 | int result = 0; 30 | Assert.assertEquals(result, testObjects[0].findMin(nums)); 31 | Assert.assertEquals(result, testObjects[1].findMin(nums)); 32 | } 33 | 34 | @Test 35 | public void testAll() { 36 | for (int oi = 0; oi < testObjects.length; oi++) { 37 | for (int i = 0; i < allNums.length; i++) { 38 | int[] nums = allNums[i]; 39 | int result = results[i]; 40 | Assert.assertEquals(result, testObjects[oi].findMin(nums)); 41 | } 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/medium/FindPeakElementTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by Brian on 2016/4/30. 9 | */ 10 | public class FindPeakElementTest { 11 | 12 | private FindPeakElement testObject; 13 | 14 | private int[][] allNums = new int[][] { 15 | {1}, 16 | {3, 4}, 17 | {4, 2}, 18 | {1, 2, 3}, 19 | {3, 2, 1}, 20 | {1, 2, 3, 1} 21 | }; 22 | private int[] results = new int[] {0, 1, 0, 2, 0, 2}; 23 | 24 | @Before 25 | public void setUp() { 26 | testObject = new FindPeakElement().new FindPeakElement0(); 27 | } 28 | 29 | @Test 30 | public void testFindPeakElement() { 31 | int[] nums = new int[] {1, 2, 3, 1}; 32 | int result = 2; 33 | Assert.assertEquals(result, testObject.findPeakElement(nums)); 34 | } 35 | 36 | @Test 37 | public void testAll() { 38 | for (int i = 0; i < allNums.length; i++) { 39 | Assert.assertEquals(results[i], testObject.findPeakElement(allNums[i])); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/medium/LetterCombinationsOfPhoneNumberTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class LetterCombinationsOfPhoneNumberTest { 11 | 12 | private LetterCombinationsOfPhoneNumber testObject; 13 | 14 | @Before 15 | public void setUp() { 16 | testObject = new LetterCombinationsOfPhoneNumber.LetterCombinationsOfPhoneNumber0(); 17 | } 18 | 19 | @Test 20 | public void testLetterCombinations() { 21 | String digits = ""; 22 | List result = new ArrayList<>(); 23 | Assert.assertEquals(result, testObject.letterCombinations(digits)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/medium/MinimumSizeSubarraySumTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | public class MinimumSizeSubarraySumTest { 8 | private MinimumSizeSubarraySum testObject; 9 | 10 | private int[][] allNums = {{2, 3, 1, 2, 4, 3}, {1, 2, 3, 4, 5}}; 11 | private int[] ss = {7, 11}; 12 | private int[] results = {2, 3}; 13 | 14 | @Before 15 | public void setUp() { 16 | testObject = new MinimumSizeSubarraySum().new MinimumSizeSubarraySum0(); 17 | } 18 | 19 | @Test 20 | public void testMinSubArrayLen() { 21 | int[] nums = {2, 3, 1, 2, 4, 3}; 22 | int s = 7; 23 | int result = 2; 24 | Assert.assertEquals(result, testObject.minSubArrayLen(s, nums)); 25 | } 26 | 27 | @Test 28 | public void testAll() { 29 | for (int i = 0; i < allNums.length; i++) { 30 | int[] nums = allNums[i]; 31 | int s = ss[i]; 32 | int result = results[i]; 33 | Assert.assertEquals(result, testObject.minSubArrayLen(s, nums)); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/medium/SearchRotatedSortedArrayTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | /** 11 | * @auther brian 12 | * @since 2022/5/5 22:55 13 | */ 14 | public class SearchRotatedSortedArrayTest { 15 | private SearchInRotatedSortedArray testObject; 16 | 17 | private List testcases; 18 | 19 | @Before 20 | public void setUp() { 21 | testObject = new SearchInRotatedSortedArray.SearchInRotatedSortedArray0(); 22 | 23 | testcases = Arrays.asList( 24 | Testcase.of(new int[] {4, 5, 6, 7, 0, 1, 2}, 0, 4), 25 | Testcase.of(new int[] {3, 2}, 2, 1), 26 | Testcase.of(new int[] {1, 3}, 3, 1), 27 | Testcase.of(new int[] {4, 5, 6, 7, 8, 1, 2, 3}, 8, 4), 28 | Testcase.of(new int[] {1, 2, 4, 5}, 4, 2) 29 | ); 30 | } 31 | 32 | @Test 33 | public void testSearch() { 34 | int[] nums = {4, 5, 6, 7, 8, 1, 2, 3}; 35 | int target = 8; 36 | int result = 4; 37 | Assert.assertEquals(result, testObject.search(nums, target)); 38 | } 39 | 40 | @Test 41 | public void testAll() { 42 | for (Testcase tc : testcases) { 43 | Assert.assertEquals(tc.result, testObject.search(tc.nums, tc.target)); 44 | } 45 | } 46 | 47 | private static class Testcase { 48 | int[] nums; 49 | int target; 50 | int result; 51 | 52 | private Testcase(int[] nums, int target, int result) { 53 | this.nums = nums; 54 | this.target = target; 55 | this.result = result; 56 | } 57 | 58 | public static Testcase of(int[] nums, int target, int result) { 59 | return new Testcase(nums, target, result); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/medium/ThreeSumTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | 9 | /** 10 | * Created by Brian on 2016/4/30. 11 | */ 12 | public class ThreeSumTest { 13 | 14 | private ThreeSum testObject; 15 | 16 | private int[] nums; 17 | private ArrayList> result;//= new ArrayList>(); 18 | 19 | @Before 20 | public void setUp() { 21 | nums = new int[] {1, -1, -1, 2, 0, 1}; 22 | int[][] array = { 23 | {-1, -1, 2}, 24 | {-1, 0, 1} 25 | }; 26 | result = getArrayList(array); 27 | testObject = new ThreeSum().new ThreeSum0(); 28 | } 29 | 30 | private ArrayList> getArrayList(int[][] array) { 31 | ArrayList> all = new ArrayList<>(); 32 | int size = 3; 33 | for (final int[] anArray : array) { 34 | ArrayList match = new ArrayList<>(size); 35 | for (int j = 0; j < size; j++) { 36 | match.add(anArray[j]); 37 | } 38 | all.add(match); 39 | } 40 | return all; 41 | } 42 | 43 | @Test 44 | public void testThreeSum() { 45 | Assert.assertEquals(result, testObject.threeSum(nums)); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /algorithms-leetcode/src/test/java/com/brianway/learning/algorithms/leetcode/medium/TriangleTest.java: -------------------------------------------------------------------------------- 1 | package com.brianway.learning.algorithms.leetcode.medium; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.stream.Collectors; 10 | import java.util.stream.IntStream; 11 | 12 | public class TriangleTest { 13 | 14 | private Triangle testObject; 15 | 16 | @Before 17 | public void setUp() { 18 | testObject = new Triangle().new Triangle1(); 19 | } 20 | 21 | @Test 22 | public void testMinimumTotal() { 23 | //[[2],[3,4], [6,5,7],[4,1,8,3]] 24 | int[][] a = {{2}, {3, 4}, {6, 5, 7}, {4, 1, 8, 3}}; 25 | int result = 11; 26 | List> triangle = transform(a); 27 | //System.out.println(triangle); 28 | Assert.assertEquals(result, testObject.minimumTotal(triangle)); 29 | } 30 | 31 | private List> transform(int[][] a) { 32 | List> triangle = new ArrayList<>(); 33 | if (a == null) { 34 | return triangle; 35 | } 36 | List row; 37 | for (int i = 0; i < a.length; i++) { 38 | row = IntStream.of(a[i]).boxed().collect(Collectors.toList()); 39 | triangle.add(row); 40 | } 41 | return triangle; 42 | } 43 | } 44 | --------------------------------------------------------------------------------