├── 3Sum With Multiplicity.java ├── Add Two Numbers II.java ├── Add Two Numbers.java ├── Add to Array-Form of Integer.java ├── Advantage Shuffle.java ├── All Nodes Distance K in Binary Tree.java ├── All Paths From Source to Target.java ├── All Possible Full Binary Trees.java ├── Alphabet Board Path.java ├── Ambiguous Coordinates.java ├── Array Nesting.java ├── As Far from Land as Possible.java ├── Asteroid Collision.java ├── Average of Levels in Binary Tree.java ├── Base 7.java ├── Baseball Game.java ├── Basic Calculator II.java ├── Basic Calculator.java ├── Beautiful Array.java ├── Best Sightseeing Pair.java ├── Best Time to Buy and Sell Stock I.java ├── Best Time to Buy and Sell Stock II.java ├── Best Time to Buy and Sell Stock III.java ├── Best Time to Buy and Sell Stock IV.java ├── Best Time to Buy and Sell Stock with Cooldown.java ├── Best Time to Buy and Sell Stock with Transaction Fee.java ├── Binary Index Tree Template.java ├── Binary Prefix Divisible By 5 ├── Binary Prefix Divisible By 5.java └── Binary Prefix Divisible By 5.py ├── Binary Search Tree to Greater Sum Tree ├── Binary Search Tree to Greater Sum Tree.java └── Binary Search Tree to Greater Sum Tree.py ├── Binary String With Substrings Representing 1 To N ├── Binary String With Substrings Representing 1 To N.java └── Binary String With Substrings Representing 1 To N.py ├── Binary Tree Cameras.java ├── Binary Tree Coloring Game.java ├── Binary Trees With Factors.java ├── Bitwise ORs of Subarrays.java ├── Bomb Enemy.java ├── Bricks Falling When Hit.java ├── Broken Calculator.java ├── Burst Balloons.java ├── Bus Routes.java ├── Camelcase Matching ├── Camelcase Matching.java └── Camelcase Matching.py ├── Can I Win.java ├── Can Make Palindrome from Substring.java ├── Can Place Flowers.java ├── Candy.java ├── Capacity To Ship Packages Within D Days.java ├── Car Pooling ├── Car Pooling.java └── Car Pooling.py ├── Card Flipping Game.java ├── Cells with Odd Values in a Matrix.java ├── Champagne Tower.java ├── Cheapest Flights Within K Stops.java ├── Check If It Is a Good Array.java ├── Check If Word Is Valid After Substitutions.java ├── Cherry Pickup.java ├── Closest Leaf in a Binary Tree.java ├── Coloring A Border ├── Coloring A Border.java └── Coloring A Border.py ├── Combination Sum II.java ├── Combination Sum III.java ├── Combination Sum IV.java ├── Combination Sum.java ├── Compare Strings by Frequency of the Smallest Character.java ├── Complement of Base 10 Integer.java ├── Consecutive Numbers Sum.java ├── Construct Binary Tree from String.java ├── Construct String from Binary Tree.java ├── Continuous Subarray Sum.java ├── Convert BST to Greater Tree.java ├── Convert to Base -2 ├── Convert to Base -2.java └── Convert to Base -2.py ├── Convex Polygon.java ├── Corporate Flight Bookings.java ├── Count Complete Tree Nodes.java ├── Count Number of Binary Strings Without Consecutive 1’s.java ├── Count Number of Nice Subarrays.java ├── Count Primes.java ├── Count Vowels Permutation.java ├── Count of Smaller Numbers After Self.java ├── Course Schedule III.java ├── Cousins in Binary Tree.java ├── Cracking the Safe.java ├── Critical Connections in a Network.java ├── Daily Temperatures.java ├── Day of the Week.java ├── Decode String.java ├── Decode Ways II.java ├── Decode Ways.java ├── Decrease Elements To Make Array Zigzag.java ├── Defanging an IP Address ├── Defanging an IP Address.java └── Defanging an IP Address.py ├── Degree of an Array.java ├── Delete Nodes And Return Forest ├── Delete Nodes And Return Forest.java └── Delete Nodes And Return Forest.py ├── Delete and Earn.java ├── Design Twitter.java ├── Different Ways to Add Parentheses.java ├── Dinner Plate Stacks.java ├── Distance Between Bus Stops.java ├── Distant Barcodes ├── Distant Barcodes.java └── Distant Barcodes.py ├── Distinct Subsequences.java ├── Distribute Candies to People ├── Distribute Candies to People.java └── Distribute Candies to People.py ├── Distribute Coins in Binary Tree.java ├── Divisor Game ├── Divisor Game.java └── Divisor Game.py ├── Domino and Tromino Tiling.java ├── Duplicate Zeros ├── Duplicate Zeros.java └── Duplicate Zeros.py ├── Employee Importance.java ├── Equal Rational Numbers.java ├── Escape a Large Maze ├── Escape a Large Maze.java └── Escape a Large Maze.py ├── Evaluate Division.java ├── Exclusive Time of Functions.java ├── Expression Add Operators.java ├── Filling Bookcase Shelves ├── Filling Bookcase Shelves.java └── Filling Bookcase Shelves.py ├── Find All Anagrams in a String.java ├── Find Common Characters.java ├── Find Elements in a Contaminated Binary Tree.java ├── Find Eventual Safe States.java ├── Find K Pairs with Smallest Sums.java ├── Find K-th Smallest Pair Distance.java ├── Find Median from Data Stream.java ├── Find Peak Element.java ├── Find in Mountain Array ├── Find in Mountain Array.java └── Find in Mountain Array.py ├── Find the Duplicate Number.java ├── Find the Missing Number.java ├── Find the Shortest Superstring.java ├── Find the Town Judge.java ├── First Missing Positive.java ├── Flatten Nested List Iterator.java ├── Flip Columns For Maximum Number of Equal Rows ├── Flip Columns For Maximum Number of Equal Rows.java └── Flip Columns For Maximum Number of Equal Rows.py ├── Flip Equivalent Binary Trees.java ├── Flip String to Monotone Increasing.java ├── Flood Fill.java ├── Flower Planting With No Adjacent ├── Flower Planting With No Adjacent.java └── Flower Planting With No Adjacent.py ├── Friend Circles.java ├── Friends Of Appropriate Ages.java ├── Frog Jump.java ├── Game of Life.java ├── Gas Station.java ├── Generate Parentheses.java ├── Get Equal Substrings Within Budget.java ├── Global and Local Inversions.java ├── Gray Code.java ├── Greatest Common Divisor of Strings ├── Greatest Common Divisor of Strings.java └── Greatest Common Divisor of Strings.py ├── Grid Illumination.java ├── Group Anagrams.java ├── Grumpy Bookstore Owner ├── Grumpy Bookstore Owner.java └── Grumpy Bookstore Owner.py ├── Hamming Distance.java ├── Height Checker ├── Height Checker.java └── Height Checker.py ├── Implement Magic Dictionary.java ├── Implement Queue Using Array.java ├── Implement Queue Using Stacks.java ├── Implement Rand10() Using Rand7().java ├── Implement Stack Using Array.java ├── Implement Stack using Queues.java ├── Increasing Triplet Subsequence.java ├── Inorder Successor in BST.java ├── Insert Interval.java ├── Insufficient Nodes in Root to Leaf Paths ├── Insufficient Nodes in Root to Leaf Paths.java └── Insufficient Nodes in Root to Leaf Paths.py ├── Integer Break.java ├── Integer to Roman.java ├── Interval List Intersections.java ├── Is Graph Bipartite.java ├── Island Perimeter.java ├── Jump Game II.java ├── Jump Game.java ├── K Closest Points to Origin.java ├── K-th Smallest Prime Fraction.java ├── Knight Dialer.java ├── Knight Probability in Chessboard.java ├── Koko Eating Bananas.java ├── Kth Smallest Element in a BST.java ├── Kth Smallest Element in a Sorted Matrix.java ├── Kth Smallest Number in Multiplication Table.java ├── Largest 1-Bordered Square.java ├── Largest BST Subtree.java ├── Largest Component Size by Common Factor.java ├── Largest Number.java ├── Largest Sum of Averages.java ├── Largest Time for Given Digits.java ├── Largest Triangle Area.java ├── Largest Values From Labels ├── Largest Values From Labels.java └── Largest Values From Labels.py ├── Last Stone Weight II ├── Last Stone Weight II.java └── Last Stone Weight II.py ├── Last Stone Weight ├── Last Stone Weight.java └── Last Stone Weight.py ├── Least Operators to Express Number.java ├── Length of Longest Fibonacci Subsequence.java ├── Letter Case Permutation.java ├── Letter Tile Possibilities ├── Letter Tile Possibilities.java └── Letter Tile Possibilities.py ├── Linked List Components.java ├── Linked List Random Node.java ├── Longest Arithmetic Sequence ├── Longest Arithmetic Sequence.java └── Longest Arithmetic Sequence.py ├── Longest Arithmetic Subsequence of Given Difference.java ├── Longest Chunked Palindrome Decomposition.java ├── Longest Harmonious Subsequence.java ├── Longest Increasing Path in a Matrix.java ├── Longest String Chain ├── Longest String Chain.java └── Longest String Chain.py ├── Longest Substring Without Repeating Characters.java ├── Longest Substring with At Most Two Distinct Characters.java ├── Longest Turbulent Subarray.java ├── Longest Valid Parentheses.java ├── Longest Well-Performing Interval ├── Longest Well-Performing Interval.java └── Longest Well-Performing Interval.py ├── Longest Word in Dictionary through Deleting.java ├── Longest Word in Dictionary.java ├── Lowest Common Ancestor of a Binary Tree.java ├── Magical String.java ├── Make Array Strictly Increasing.java ├── Making A Large Island.java ├── Masking Personal Information.java ├── Matrix Cells in Distance Order ├── Matrix Cells in Distance Order.java └── Matrix Cells in Distance Order.py ├── Max Area of Island.java ├── Max Consecutive Ones II.java ├── Max Consecutive Ones III.java ├── Max Consecutive Ones.java ├── Max Sum of Rectangle No Larger Than K.java ├── Maximal Rectangle.java ├── Maximal Square.java ├── Maximum Binary Tree II.java ├── Maximum Binary Tree.java ├── Maximum Difference Between Node and Ancestor ├── Maximum Difference Between Node and Ancestor.java └── Maximum Difference Between Node and Ancestor.py ├── Maximum Frequency Stack.java ├── Maximum Gap.java ├── Maximum Nesting Depth of Two Valid Parentheses Strings.java ├── Maximum Product Subarray.java ├── Maximum Score Words Formed by Letters.java ├── Maximum Subarray Sum with One Deletion.java ├── Maximum Sum of Two Non-Overlapping Subarrays ├── Maximum Sum of Two Non-Overlapping Subarrays.java └── Maximum Sum of Two Non-Overlapping Subarrays.py ├── Maximum XOR of Two Numbers in an Array.java ├── Maximum of Absolute Value Expression.java ├── Median of Two Sorted Arrays.java ├── Merge Intervals.java ├── Minimum ASCII Delete Sum for Two Strings.java ├── Minimum Cost For Tickets.java ├── Minimum Cost Tree From Leaf Values.java ├── Minimum Cost to Merge Stones.java ├── Minimum Increment to Make Array Unique.java ├── Minimum Index Sum of Two Lists.java ├── Minimum Moves to Equal Array Elements II.java ├── Minimum Moves to Equal Array Elements.java ├── Minimum Number of Arrows to Burst Balloons.java ├── Minimum Number of K Consecutive Bit Flips ├── Minimum Number of K Consecutive Bit Flips.java └── Minimum Number of K Consecutive Bit Flips.py ├── Minimum Number of Refueling Stops.java ├── Minimum Score Triangulation of Polygon ├── Minimum Score Triangulation of Polygon.java └── Minimum Score Triangulation of Polygon.py ├── Minimum Size Subarray Sum.java ├── Minimum Swaps To Make Sequences Increasing.java ├── Minimum Swaps to Make Strings Equal.java ├── Minimum Window Substring.java ├── Most Common Word.java ├── Most Frequent Subtree Sum.java ├── Most Profit Assigning Work.java ├── Most Stones Removed with Same Row or Column.java ├── Move Zeroes.java ├── Moving Stones Until Consecutive II ├── Moving Stones Until Consecutive II.java └── Moving Stones Until Consecutive II.py ├── Moving Stones Until Consecutive ├── Moving Stones Until Consecutive.java └── Moving Stones Until Consecutive.py ├── Multiply Strings.java ├── Network Delay Time.java ├── Next Greater Element I ├── Next Greater Element I.java └── Next Greater Element I.py ├── Next Greater Element II ├── Next Greater Element II.java └── Next Greater Element II.py ├── Next Greater Element III ├── Next Greater Element III.java └── Next Greater Element III.py ├── Next Greater Node In Linked List ├── Next Greater Node In Linked List.java └── Next Greater Node In Linked List.py ├── Next Permutation.java ├── Non-negative Integers without Consecutive Ones.java ├── Number Complement.java ├── Number of Atoms.java ├── Number of Big Islands.java ├── Number of Boomerangs.java ├── Number of Closed Islands.java ├── Number of Dice Rolls With Target Sum.java ├── Number of Enclaves ├── Number of Enclaves.java └── Number of Enclaves.py ├── Number of Equivalent Domino Pairs.java ├── Number of Islands II.java ├── Number of Islands.java ├── Number of Matching Subsequences.java ├── Number of Squareful Arrays.java ├── Number of Submatrices That Sum to Target ├── Number of Submatrices That Sum to Target.java └── Number of Submatrices That Sum to Target.py ├── Number of Valid Words for Each Puzzle.java ├── Numbers At Most N Given Digit Set.java ├── Numbers With Repeated Digits.java ├── Numbers With Same Consecutive Differences.java ├── Occurrences After Bigram ├── Occurrences After Bigram.java └── Occurrences After Bigram.py ├── Odd Even Jump.java ├── Online Majority Element In Subarray.java ├── Online Stock Span.java ├── Open the Lock.java ├── Orderly Queue.java ├── Out of Boundary Paths.java ├── PIO.java ├── Pacific Atlantic Water Flow ├── Pacific Atlantic Water Flow.java └── Pacific Atlantic Water Flow.py ├── Pairs of Songs With Total Durations Divisible by 60.java ├── Palindrome Permutation II.java ├── Palindrome Permutation.java ├── Parsing A Boolean Expression ├── Parsing A Boolean Expression.java └── Parsing A Boolean Expression.py ├── Partition Array Into Three Parts With Equal Sum.java ├── Partition Array for Maximum Sum ├── Partition Array for Maximum Sum.java └── Partition Array for Maximum Sum.py ├── Partition Equal Subset Sum.java ├── Partition Labels.java ├── Partition to K Equal Sum Subsets.java ├── Path In Zigzag Labelled Binary Tree ├── Path In Zigzag Labelled Binary Tree.java └── Path In Zigzag Labelled Binary Tree.py ├── Path Sum III.java ├── Path with Maximum Gold.java ├── Peak Index in a Mountain Array ├── Peak Index in a Mountain Array.java └── Peak Index in a Mountain Array.py ├── Perfect Rectangle ├── Perfect Rectangle.java └── Perfect Rectangle.py ├── Perfect Squares.java ├── Permutation Sequence.java ├── Permutation in String.java ├── Play with Chips.java ├── Plus One.java ├── Populating Next Right Pointers in Each Node II.java ├── Populating Next Right Pointers in Each Node.java ├── Positions of Large Groups.java ├── Possible Bipartition.java ├── Power of Four.java ├── Power of Three.java ├── Power of Two.java ├── Prefix and Suffix Search.java ├── Previous Permutation With One Swap ├── Previous Permutation With One Swap.java └── Previous Permutation With One Swap.py ├── Prime Arrangements.java ├── Product of Array Exclude Itself.java ├── Profitable Schemes.java ├── README.md ├── Race Car.java ├── Random Pick Index.java ├── Range Sum Query - Immutable.java ├── Range Sum Query - Mutable.java ├── Range Sum Query 2D - Mutable.java ├── Reach a Number.java ├── Reachable Nodes In Subdivided Graph.java ├── Reconstruct a 2-Row Binary Matrix.java ├── Recover a Tree From Preorder Traversal ├── Recover a Tree From Preorder Traversal.java └── Recover a Tree From Preorder Traversal.py ├── Rectangle Area.java ├── Rectangle Overlap.java ├── Redundant Connection II.java ├── Redundant Connection.java ├── Regions Cut By Slashes.java ├── Regular Expression Matching.java ├── Relative Sort Array.java ├── Remove All Adjacent Duplicates In String ├── Remove All Adjacent Duplicates In String.java └── Remove All Adjacent Duplicates In String.py ├── Remove All Adjacent Duplicates in String II.java ├── Remove Boxes.java ├── Remove Duplicate Letters ├── Remove Duplicate Letters.java └── Remove Duplicate Letters.py ├── Remove Invalid Parentheses.java ├── Remove Outermost Parentheses ├── Remove Outermost Parentheses.java └── Remove Outermost Parentheses.py ├── Remove Zero Sum Consecutive Nodes from Linked List.java ├── Reorder List.java ├── Repeated String Match.java ├── Repeated Substring Pattern.java ├── Reveal Cards In Increasing Order.java ├── Reverse Bits.java ├── Reverse Nodes in k-Group.java ├── Reverse Pairs.java ├── Reverse Substrings Between Each Pair of Parentheses.java ├── Robot Bounded In Circle ├── Robot Bounded In Circle.java └── Robot Bounded In Circle.py ├── Roman to Integer.java ├── Rotate Array.java ├── Rotate Image.java ├── Rotate List.java ├── Rotated Digits.java ├── Rotting Oranges.java ├── Russian Doll Envelopes.java ├── Same Tree.java ├── Satisfiability of Equality Equations.java ├── Score of Parentheses.java ├── Search in Rotated Sorted Array.java ├── Self Dividing Numbers.java ├── Sentence Similarity.java ├── Shift 2D Grid.java ├── Shifting Letters.java ├── Short Encoding of Words.java ├── Shortest Bridge.java ├── Shortest Common Supersequence ├── Shortest Common Supersequence.java └── Shortest Common Supersequence.py ├── Shortest Distance to a Character.java ├── Shortest Palindrome.java ├── Shortest Path Visiting All Nodes.java ├── Shortest Path in Binary Matrix ├── Shortest Path in Binary Matrix.java └── Shortest Path in Binary Matrix.py ├── Shortest Path to Get All Keys.java ├── Shortest Path with Alternating Colors.java ├── Single Element in a Sorted Array.java ├── Sliding Window Maximum.java ├── Sliding Window Median.java ├── Sliding Window Template.java ├── Smallest Integer Divisible by K.java ├── Smallest Rotation with Highest Score.java ├── Smallest String Starting From Leaf.java ├── Smallest Subsequence of Distinct Characters ├── Smallest Subsequence of Distinct Characters.java └── Smallest Subsequence of Distinct Characters.py ├── Smallest Subtree with all the Deepest Nodes.java ├── Smallest Sufficient Team.java ├── Snapshot Array.java ├── Special Binary String.java ├── Split Array Largest Sum.java ├── Split Array With Same Average.java ├── Stamping The Sequence.java ├── Stone Game II.java ├── Stone Game.java ├── Strange Printer.java ├── Stream of Characters ├── Stream of Characters.java └── Stream of Characters.py ├── String Without AAA or BBB.java ├── Subarray Sum Equals K.java ├── Subarrays with K Different Integers.java ├── Substring with Concatenation of All Words.java ├── Subtree of Another Tree.java ├── Sudoku Solver.java ├── Sum of Distances in Tree.java ├── Sum of Even Numbers After Queries.java ├── Sum of Root To Leaf Binary Numbers ├── Sum of Root To Leaf Binary Numbers.java └── Sum of Root To Leaf Binary Numbers.py ├── Sum of Square Numbers.java ├── Sum of Subarray Minimums.java ├── Sum of Subsequence Widths.java ├── Super Ugly Number.java ├── Surface Area of 3D Shapes.java ├── Surrounded Regions.java ├── Swap For Longest Repeated Character Substring.java ├── Swap Nodes in Pairs.java ├── Swim in Rising Water.java ├── Symmetric Tree.java ├── Tallest Billboard.java ├── Target Sum.java ├── The Maze II.java ├── The Maze III.java ├── The Maze.java ├── Top K Frequent Elements.java ├── Top K Frequent Words.java ├── Total Hamming Distance.java ├── Transform to Chessboard.java ├── Triples with Bitwise AND Equal To Zero.java ├── Two City Scheduling ├── Two City Scheduling.java └── Two City Scheduling.py ├── Ugly Number II.java ├── Ugly Number III.java ├── Ugly Number.java ├── Uncrossed Lines ├── Uncrossed Lines.java └── Uncrossed Lines.py ├── Unique Binary Search Trees II.java ├── Unique Binary Search Trees.java ├── Unique Letter String.java ├── Unique Paths III.java ├── Unique Paths.java ├── Vaild Square.java ├── Valid Anagram.java ├── Valid Boomerang ├── Valid Boomerang.java └── Valid Boomerang.py ├── Valid Sudoku.java ├── Validate Binary Search Tree.java ├── Validate Stack Sequences.java ├── Vertical Order Traversal of a Binary Tree.java ├── Video Stitching ├── Video Stitching.java └── Video Stitching.py ├── Wildcard Matching.java ├── Word Frequency.linux ├── Word Ladder II.java ├── Word Ladder.java └── Zuma Game.java /Advantage Shuffle.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given two arrays A and B of equal size, the advantage of A with respect to B is the number of indices i for which A[i] > B[i]. 3 | Return any permutation of A that maximizes its advantage with respect to B. 4 | 5 | Example 1: 6 | Input: A = [2,7,11,15], B = [1,10,4,11] 7 | Output: [2,11,7,15] 8 | 9 | Example 2: 10 | Input: A = [12,24,8,32], B = [13,25,32,11] 11 | Output: [24,32,8,12] 12 | 13 | Note: 14 | 1 <= A.length = B.length <= 10000 15 | 0 <= A[i] <= 10^9 16 | 0 <= B[i] <= 10^9 17 | */ 18 | 19 | /** 20 | * Approach: Greedy (田忌赛马) 21 | * 根据数据规模可得,时间复杂度应该在 O(nlogn) 级别。 22 | * 题目要求一个排列使得 A[i] > B[i] 的对数尽量多,对应过来其实就是一个 田忌赛马 的问题。 23 | * 使得 A 尽量多地赢 B. 24 | * 因此我们可以将 A 进行一个排序(从小到大) 25 | * 然后对于 B 则放入一个 最大堆 中,我们必须首先检测能否找到一个数使得 A[i] > currentMaxB. 26 | * 因为它是最难满足的条件,如果能够找到,就使用这个数。(上等马 VS 上等马,只不过A的更强) 27 | * 否则就说明这场比赛必败,因此我们可以使用最小的元素跟当前B最大的元素进行PK。(下等马 VS 上等马) 28 | * 基于以上做法,我们就能够保证 A 赢的场数最多了。 29 | * 30 | * 时间复杂度:O(nlogn) 31 | * 空间复杂度:O(n) 32 | * 33 | * 参考资料: 34 | * https://leetcode.com/problems/advantage-shuffle/discuss/149822/JAVA-Greedy-6-lines-with-Explanation 35 | */ 36 | class Solution { 37 | public int[] advantageCount(int[] A, int[] B) { 38 | Arrays.sort(A); 39 | PriorityQueue maxHeap = new PriorityQueue<>(new Comparator() { 40 | @Override 41 | public int compare(int[] a, int[] b) { 42 | return b[0] - a[0]; 43 | } 44 | }); 45 | for (int i = 0; i < B.length; i++) { 46 | maxHeap.offer(new int[]{B[i], i}); 47 | } 48 | 49 | int[] rst = new int[A.length]; 50 | int low = 0, high = A.length - 1; 51 | while (low <= high) { // !maxHeap.isEmpty() 这两个判断条件均可 52 | int [] curr = maxHeap.poll(); 53 | if (A[high] > curr[0]) { 54 | // 上等马 VS 上等马 55 | rst[curr[1]] = A[high--]; 56 | } else { 57 | // 下等马 VS 上等马 58 | rst[curr[1]] = A[low++]; 59 | } 60 | } 61 | return rst; 62 | } 63 | } -------------------------------------------------------------------------------- /All Paths From Source to Target.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a directed, acyclic graph of N nodes. 3 | Find all possible paths from node 0 to node N-1, and return them in any order. 4 | The graph is given as follows: the nodes are 0, 1, ..., graph.length - 1. 5 | graph[i] is a list of all nodes j for which the edge (i, j) exists. 6 | 7 | Example: 8 | Input: [[1,2], [3], [3], []] 9 | Output: [[0,1,3],[0,2,3]] 10 | Explanation: The graph looks like this: 11 | 0--->1 12 | | | 13 | v v 14 | 2--->3 15 | There are two paths: 0 -> 1 -> 3 and 0 -> 2 -> 3. 16 | 17 | Note: 18 | The number of nodes in the graph will be in the range [2, 15]. 19 | You can print different paths in any order, but you should keep the order of nodes inside one path. 20 | */ 21 | 22 | /** 23 | * Approach: Graph DFS (Backtracking) 24 | * 需要求出所有从 0 到 n-1 的具体路径,因此需要使用 DFS 进行遍历,并记录路径。 25 | * 这里我们枚举了所有的方案数,找出结尾通向 n-1 的即可。 26 | * 27 | * 关于 Backtracking 的模板和详细解释可以参考: 28 | * https://github.com/cherryljr/LintCode/blob/master/Subset.java 29 | */ 30 | class Solution { 31 | public List> allPathsSourceTarget(int[][] graph) { 32 | List> rst = new LinkedList<>(); 33 | List path = new LinkedList<>(); 34 | path.add(0); 35 | dfs(graph, 0, path, rst); 36 | return rst; 37 | } 38 | 39 | private void dfs(int[][] graph, int index, List path, List> rst) { 40 | if (index == graph.length - 1) { 41 | rst.add(new LinkedList<>(path)); 42 | return; 43 | } 44 | 45 | for (int neigh : graph[index]) { 46 | path.add(neigh); 47 | dfs(graph, neigh, path, rst); 48 | // Backtracking 49 | path.remove(path.size() - 1); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Average of Levels in Binary Tree.java: -------------------------------------------------------------------------------- 1 | Basic question about Level order traversal using BFS. 2 | You can see the BFS Template here: 3 | https://github.com/cherryljr/LintCode/blob/master/BFS%20Template.java 4 | 5 | /* 6 | Given a non-empty binary tree, return the average value of the nodes on each level in the form of an array. 7 | 8 | Example 1: 9 | Input: 10 | 3 11 | / \ 12 | 9 20 13 | / \ 14 | 15 7 15 | Output: [3, 14.5, 11] 16 | 17 | Explanation: 18 | The average value of nodes on level 0 is 3, on level 1 is 14.5, and on level 2 is 11. Hence return [3, 14.5, 11]. 19 | 20 | Note: 21 | The range of node's value is in the range of 32-bit signed integer. 22 | */ 23 | 24 | /** 25 | * Definition for a binary tree node. 26 | * public class TreeNode { 27 | * int val; 28 | * TreeNode left; 29 | * TreeNode right; 30 | * TreeNode(int x) { val = x; } 31 | * } 32 | */ 33 | class Solution { 34 | public List averageOfLevels(TreeNode root) { 35 | List rst = new ArrayList<>(); 36 | if (root == null) { 37 | return rst; 38 | } 39 | 40 | Queue queue = new LinkedList<>(); 41 | queue.offer(root); 42 | while (!queue.isEmpty()) { 43 | int size = queue.size(); 44 | double sum = 0; 45 | for (int i = 0; i < size; i++) { 46 | TreeNode node = queue.poll(); 47 | sum += node.val; 48 | if (node.left != null) { 49 | queue.offer(node.left); 50 | } 51 | if (node.right != null) { 52 | queue.offer(node.right); 53 | } 54 | } 55 | rst.add(sum / size); 56 | } 57 | 58 | return rst; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Base 7.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer, return its base 7 string representation. 3 | 4 | Example 1: 5 | Input: 100 6 | Output: "202" 7 | 8 | Example 2: 9 | Input: -7 10 | Output: "-10" 11 | 12 | Note: The input will be in range of [-1e7, 1e7]. 13 | */ 14 | 15 | /** 16 | * Approach 1: Convert Radix 17 | * 使用取余,整除的方法一步步走下去即可。 18 | * 注意该方法先算出来的是高位,所以需要一次 reverse. 19 | * (需要处理负数) 20 | */ 21 | class Solution { 22 | public String convertToBase7(int num) { 23 | int abs = Math.abs(num); 24 | StringBuilder sb = new StringBuilder(); 25 | while (abs >= 7) { 26 | sb.append(abs % 7); 27 | abs /= 7; 28 | } 29 | sb.append(abs).reverse(); 30 | return num >= 0 ? sb.toString() : "-" + sb.toString(); 31 | } 32 | } 33 | 34 | /** 35 | * Approach 2: Using Native Method 36 | * 直接使用 Integer 自带的 toString() 转换过去即可 37 | * 本题为 由 整数 -> 字符串 38 | * 39 | * 类似的问题还有: 40 | * 进制转换:https://github.com/cherryljr/NowCoder/blob/master/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2.java 41 | * 由 字符串 -> 整数 42 | */ 43 | class Solution { 44 | public String convertToBase7(int num) { 45 | return Integer.toString(num, 7); 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /Basic Calculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a basic calculator to evaluate a simple expression string. 3 | The expression string may contain open ( and closing parentheses ), 4 | the plus + or minus sign -, non-negative integers and empty spaces . 5 | 6 | You may assume that the given expression is always valid. 7 | 8 | Some examples: 9 | "1 + 1" = 2 10 | " 2-1 + 2 " = 3 11 | "(1+(4+5+2)-3)+(6+8)" = 23 12 | 13 | Note: Do not use the eval built-in library function. 14 | */ 15 | 16 | /** 17 | * Approach: Using Stack 18 | * 使用 栈 来模拟中序表达式的计算即可 19 | */ 20 | class Solution { 21 | public int calculate(String s) { 22 | if (s == null || s.length() == 0) { 23 | return 0; 24 | } 25 | 26 | Stack stack = new Stack<>(); 27 | char[] chars = s.toCharArray(); 28 | int rst = 0; 29 | int num = 0; 30 | int sign = 1; 31 | stack.push(sign); 32 | 33 | for (int i = 0; i < chars.length; i++) { 34 | if (chars[i] >= '0' && chars[i] <= '9') { 35 | num = num * 10 + (chars[i] - '0'); 36 | } else if (chars[i] == '+' || chars[i] == '-') { 37 | rst += sign * num; 38 | sign = stack.peek() * (chars[i] == '+' ? 1 : -1); 39 | num = 0; 40 | } else if (chars[i] == '(') { 41 | stack.push(sign); 42 | } else if (chars[i] == ')') { 43 | stack.pop(); 44 | } 45 | } 46 | 47 | rst += sign * num; 48 | return rst; 49 | } 50 | } -------------------------------------------------------------------------------- /Best Sightseeing Pair.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array A of positive integers, A[i] represents the value of the i-th sightseeing spot, 3 | and two sightseeing spots i and j have distance j - i between them. 4 | 5 | The score of a pair (i < j) of sightseeing spots is (A[i] + A[j] + i - j) : 6 | the sum of the values of the sightseeing spots, minus the distance between them. 7 | 8 | Return the maximum score of a pair of sightseeing spots. 9 | 10 | Example 1: 11 | Input: [8,1,5,2,6] 12 | Output: 11 13 | Explanation: i = 0, j = 2, A[i] + A[j] + i - j = 8 + 5 + 0 - 2 = 11 14 | 15 | Note: 16 | 1. 2 <= A.length <= 50000 17 | 2. 1 <= A[i] <= 1000 18 | */ 19 | 20 | /** 21 | * Approach: Traversal (Tricky Problem) 22 | * 这道题目看数据规模有 50000,所以算法时间复杂度应该在 O(nlogn) 或者以下。 23 | * 因为涉及到大小问题,所以想着排序,但是排序后将会丢失掉 index 信息。 24 | * 所以想到最终解法应该在 O(n) 级别。 25 | * 26 | * 这道题目的想法其实挺好玩的: 27 | * 大家可以想象一下我们的日常生活。比如:你当前位置在 i,去地点 j 能够赚到 A[j] 的钱, 28 | * 但是过去的路上你要花掉 |i-j| 的车费,所以当你到了 A[j],你实际上的收益只有 A[j] - |i-j| 29 | * 有了上述思路,我们可以按照如下的方式来遍历数组: 30 | * 利用 currBest 来表示目前遇到的景点值最高的景点,但是因为我们每向前移动一步, 31 | * 距离最佳景点位置的距离就会增加1,这就给我们增加了 1 点的距离消耗, 32 | * 即相当于景点值 currBest 的收益值就会 -1. 33 | * 然后不断向后遍历,当前位置的最佳收益为 currBest + A[i], 34 | * 向下一个位置移动的时候更新 currBest = Math.max(currBest, A[i]) - 1 35 | * 36 | * 时间复杂度:O(n) 37 | * 空间复杂度:O(1) 38 | */ 39 | class Solution { 40 | public int maxScoreSightseeingPair(int[] A) { 41 | int ans = 0, currBest = 0; 42 | for (int num : A) { 43 | ans = Math.max(ans, currBest + num); 44 | currBest = Math.max(currBest, num) - 1; 45 | } 46 | return ans; 47 | } 48 | } -------------------------------------------------------------------------------- /Best Time to Buy and Sell Stock II.java: -------------------------------------------------------------------------------- 1 | 和Stock I 的区别:可以买卖多次,求总和的最大盈利。 2 | 3 | 思路: 4 | 本题中买卖次数无限制,所以为了利润最大化我们要找到所有的 波峰 和 波谷。 5 | 故遍历整个数组,只要前后两个数之间的差值为正数,则说明可以获利。 6 | 将 profit 加上二者的差值即可。 7 | 8 | /* 9 | Say you have an array for which the ith element is the price of a given stock on day i. 10 | 11 | Design an algorithm to find the maximum profit. You may complete as many transactions as you like 12 | (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions 13 | at the same time (ie, you must sell the stock before you buy again). 14 | 15 | Example 16 | Given an example [2,1,2,0,1], return 2 17 | 18 | Tags Expand 19 | Greedy Enumeration Array 20 | */ 21 | 22 | public class Solution { 23 | /* 24 | * @param prices: Given an integer array 25 | * @return: Maximum profit 26 | */ 27 | public int maxProfit(int[] prices) { 28 | if (prices == null || prices.length == 0) { 29 | return 0; 30 | } 31 | 32 | int profit = 0; 33 | for (int i = 0; i < prices.length - 1; i++) { 34 | int diff = prices[i + 1] - prices[i]; 35 | if (diff > 0) { 36 | profit += diff; 37 | } 38 | } 39 | 40 | return profit; 41 | } 42 | } -------------------------------------------------------------------------------- /Binary Prefix Divisible By 5/Binary Prefix Divisible By 5.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array A of 0s and 1s, consider N_i: the i-th subarray from A[0] to A[i] interpreted as a binary number 3 | (from most-significant-bit to least-significant-bit.) 4 | 5 | Return a list of booleans answer, where answer[i] is true if and only if N_i is divisible by 5. 6 | 7 | Example 1: 8 | Input: [0,1,1] 9 | Output: [true,false,false] 10 | Explanation: 11 | The input numbers in binary are 0, 01, 011; which are 0, 1, and 3 in base-10. 12 | Only the first number is divisible by 5, so answer[0] is true. 13 | 14 | Example 2: 15 | Input: [1,1,1] 16 | Output: [false,false,false] 17 | 18 | Example 3: 19 | Input: [0,1,1,1,1,1] 20 | Output: [true,false,false,false,true,false] 21 | 22 | Example 4: 23 | Input: [1,1,1,0,1] 24 | Output: [false,false,false,false,false] 25 | 26 | Note: 27 | 1. 1 <= A.length <= 30000 28 | 2. A[i] is 0 or 1 29 | ''' 30 | 31 | # 解法详解参考同名 java 文件 32 | class Solution: 33 | def prefixesDivBy5(self, A: List[int]) -> List[bool]: 34 | reminder = 0 35 | ans = list() 36 | for i in range(len(A)): 37 | reminder = (reminder << 1 | A[i]) % 5 38 | ans.append(reminder == 0) 39 | return ans -------------------------------------------------------------------------------- /Binary Search Tree to Greater Sum Tree/Binary Search Tree to Greater Sum Tree.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the root of a binary search tree with distinct values, modify it so that every node has a new value 3 | equal to the sum of the values of the original tree that are greater than or equal to node.val. 4 | 5 | As a reminder, a binary search tree is a tree that satisfies these constraints: 6 | ·The left subtree of a node contains only nodes with keys less than the node's key. 7 | ·The right subtree of a node contains only nodes with keys greater than the node's key. 8 | ·Both the left and right subtrees must also be binary search trees. 9 | 10 | Example 1: 11 | https://leetcode.com/problems/binary-search-tree-to-greater-sum-tree/ 12 | Input: [4,1,6,0,2,5,7,null,null,null,3,null,null,null,8] 13 | Output: [30,36,21,36,35,26,15,null,null,null,33,null,null,null,8] 14 | 15 | Note: 16 | 1. The number of nodes in the tree is between 1 and 100. 17 | 2. Each node will have value between 0 and 100. 18 | 3. The given tree is a binary search tree. 19 | ''' 20 | 21 | # Approach: Reverse In-Order Traversal (Recursive) 22 | # 时间复杂度:O(n) 23 | # 空间复杂度:O(logn) 24 | # 解法详解参考同名 java 文件 25 | 26 | # Definition for a binary tree node. 27 | # class TreeNode: 28 | # def __init__(self, x): 29 | # self.val = x 30 | # self.left = None 31 | # self.right = None 32 | class Solution: 33 | sum = 0 34 | 35 | def bstToGst(self, root: TreeNode) -> TreeNode: 36 | if (root.right): self.bstToGst(root.right) 37 | self.sum = root.val = self.sum + root.val 38 | if (root.left): self.bstToGst(root.left) 39 | return root -------------------------------------------------------------------------------- /Binary String With Substrings Representing 1 To N/Binary String With Substrings Representing 1 To N.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary string S (a string consisting only of '0' and '1's) and a positive integer N, 3 | return true if and only if for every integer X from 1 to N, the binary representation of X is a substring of S. 4 | 5 | Example 1: 6 | Input: S = "0110", N = 3 7 | Output: true 8 | 9 | Example 2: 10 | Input: S = "0110", N = 4 11 | Output: false 12 | 13 | Note: 14 | 1. 1 <= S.length <= 1000 15 | 2. 1 <= N <= 10^9 16 | */ 17 | 18 | /** 19 | * Approach: Mathematics 20 | * 这道题目我们可以发现 S.length 只有 1000. 21 | * 按照这个字符串长度是根本没有办法表示 10^9 以内所有这么多数的全部二进制的。 22 | * 因此,我们可以想到,这道题目的数据规模实际上并没有题目所给的这么大。 23 | * 其上界应该是 S 而并不是 N. 24 | * 25 | * 对于字符串 S 而言,其最多只有 S.length^2 个不同的 substring。 26 | * 因此其实际上的时间复杂度上限只有到 O(S.length^2) 级别而已。 27 | * 然后我们将 N 由大到小进行 遍历,(由大到小是因为更大数的二进制值更加难以被表示,如果不符合可以更早退出循环) 28 | * 同时,我们知道 num 的二进制字符串肯定是可以被包含在 2 * num 的二进制字符串中的 29 | * (原因很简单:num << 1 == num * 2.所以 2*num的二进制字符串 就是 num二进制字符串的左移一位罢了,后面多了个0) 30 | * 所以我们实际上遍历的范围只是(N, N/2) 之间 31 | * 32 | * 时间复杂度:O(S.length * 2) == O(S) (详细分析将 References) 33 | * 空间复杂度:O(bin(N)) (因为每次需要生成二进制字符串) 34 | * 35 | * References: 36 | * https://leetcode.com/problems/binary-string-with-substrings-representing-1-to-n/discuss/260847/JavaC%2B%2BPython-O(S2) 37 | */ 38 | class Solution { 39 | public boolean queryString(String S, int N) { 40 | for (int i = N; i > N >> 1; i--) { 41 | String str = Integer.toBinaryString(i); 42 | if (!S.contains(str)) { 43 | return false; 44 | } 45 | } 46 | return true; 47 | } 48 | } -------------------------------------------------------------------------------- /Binary String With Substrings Representing 1 To N/Binary String With Substrings Representing 1 To N.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a binary string S (a string consisting only of '0' and '1's) and a positive integer N, 3 | return true if and only if for every integer X from 1 to N, the binary representation of X is a substring of S. 4 | 5 | Example 1: 6 | Input: S = "0110", N = 3 7 | Output: true 8 | 9 | Example 2: 10 | Input: S = "0110", N = 4 11 | Output: false 12 | 13 | Note: 14 | 1. 1 <= S.length <= 1000 15 | 2. 1 <= N <= 10^9 16 | ''' 17 | 18 | # 解法详解参考同名 java 文件 19 | class Solution: 20 | def queryString(self, S: str, N: int) -> bool: 21 | return all(bin(i)[2:] in S for i in range(N, N >> 1, -1)) -------------------------------------------------------------------------------- /Candy.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cherryljr/LeetCode/1b1868961adc8500b0d3bff95033ebf7c56e320f/Candy.java -------------------------------------------------------------------------------- /Check If It Is a Good Array.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array nums of positive integers. Your task is to select some subset of nums, 3 | multiply each element by an integer and add all these numbers. 4 | The array is said to be good if you can obtain a sum of 1 from the array by any possible subset and multiplicand. 5 | 6 | Return True if the array is good otherwise return False. 7 | 8 | Example 1: 9 | Input: nums = [12,5,7,23] 10 | Output: true 11 | Explanation: Pick numbers 5 and 7. 12 | 5*3 + 7*(-2) = 1 13 | 14 | Example 2: 15 | Input: nums = [29,6,10] 16 | Output: true 17 | Explanation: Pick numbers 29, 6 and 10. 18 | 29*1 + 6*(-3) + 10*(-1) = 1 19 | 20 | Example 3: 21 | Input: nums = [3,6] 22 | Output: false 23 | 24 | Constraints: 25 | 1. 1 <= nums.length <= 10^5 26 | 2. 1 <= nums[i] <= 10^9 27 | */ 28 | 29 | /** 30 | * Approach: Bezout's Identity (Chinese Remainder Theorem) 31 | * Time Complexity: O(n) 32 | * Space Complexity: O(1) 33 | * 34 | * Reference: av77974575 35 | */ 36 | class Solution { 37 | public boolean isGoodArray(int[] nums) { 38 | int ans = nums[0]; 39 | for (int num : nums) { 40 | ans = gcd(ans, num); 41 | } 42 | return ans == 1; 43 | } 44 | 45 | private int gcd(int a, int b) { 46 | return b == 0 ? a : gcd(b, a % b); 47 | } 48 | } -------------------------------------------------------------------------------- /Combination Sum III.java: -------------------------------------------------------------------------------- 1 | /* 2 | Find all possible combinations of k numbers that add up to a number n, 3 | given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers. 4 | 5 | Example 1: 6 | Input: k = 3, n = 7 7 | Output: 8 | [[1,2,4]] 9 | 10 | Example 2: 11 | Input: k = 3, n = 9 12 | Output: 13 | [[1,2,6], [1,3,5], [2,3,4]] 14 | */ 15 | 16 | /** 17 | * Approach: Backtracking 18 | * 依旧是 DFS 枚举所有可能性即可。 19 | * 因为只能从 1~9 中选择数字,并且每个数字只能使用一次。 20 | * 因此这就相当于:给定一个 有序 且 不包含重复元素 的数组。求所有 sum 为 n 的 subset. 21 | * 不了解 Backtracking 的可以参考: 22 | * https://github.com/cherryljr/LintCode/blob/master/Subset.java 23 | */ 24 | class Solution { 25 | public List> combinationSum3(int k, int n) { 26 | if (k <= 0) { 27 | return new LinkedList<>(); 28 | } 29 | 30 | List> rst = new LinkedList<>(); 31 | dfs(1, n, k, new LinkedList<>(), rst); 32 | return rst; 33 | } 34 | 35 | private void dfs(int start, int remainTarget, int k, LinkedList list, List> rst) { 36 | // 找到一个符合条件的答案就将其 add 到 rst 中。 37 | if (list.size() == k && remainTarget == 0) { 38 | rst.add(new LinkedList<>(list)); 39 | return; 40 | } 41 | 42 | for (int i = start; i <= 9; i++) { 43 | if (i > remainTarget) { 44 | break; 45 | } 46 | list.add(i); 47 | dfs(i + 1,remainTarget - i, k, list, rst); 48 | list.remove(list.size() - 1); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Complement of Base 10 Integer.java: -------------------------------------------------------------------------------- 1 | /* 2 | Every non-negative integer N has a binary representation. For example, 5 can be represented as "101" in binary, 11 as "1011" in binary, and so on. 3 | Note that except for N = 0, there are no leading zeroes in any binary representation. 4 | 5 | The complement of a binary representation is the number in binary you get when changing every 1 to a 0 and 0 to a 1. 6 | For example, the complement of "101" in binary is "010" in binary. 7 | 8 | For a given number N in base-10, return the complement of it's binary representation as a base-10 integer. 9 | 10 | Example 1: 11 | Input: 5 12 | Output: 2 13 | Explanation: 5 is "101" in binary, with complement "010" in binary, which is 2 in base-10. 14 | 15 | Example 2: 16 | Input: 7 17 | Output: 0 18 | Explanation: 7 is "111" in binary, with complement "000" in binary, which is 0 in base-10. 19 | 20 | Example 3: 21 | Input: 10 22 | Output: 5 23 | Explanation: 10 is "1010" in binary, with complement "0101" in binary, which is 5 in base-10. 24 | 25 | Note: 0 <= N < 10^9 26 | */ 27 | 28 | /** 29 | * Approach: Bit Manipulation (Same as Number Complement) 30 | * 跟 Number Complement 基本一样,对 0 进行一次特殊处理即可,没啥好说的... 31 | * 32 | * 时间复杂度:O(1) 33 | * 空间复杂度:O(1) 34 | * 35 | * References: 36 | * Number Complement: 37 | * https://github.com/cherryljr/LeetCode/blob/master/Number%20Complement.java 38 | */ 39 | class Solution { 40 | public int bitwiseComplement(int N) { 41 | return N == 0 ? 1 : N ^ ((Integer.highestOneBit(N) << 1) - 1); 42 | } 43 | } -------------------------------------------------------------------------------- /Consecutive Numbers Sum.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a positive integer N, how many ways can we write it as a sum of consecutive positive integers? 3 | 4 | Example 1: 5 | Input: 5 6 | Output: 2 7 | Explanation: 5 = 5 = 2 + 3 8 | 9 | Example 2: 10 | Input: 9 11 | Output: 3 12 | Explanation: 9 = 9 = 4 + 5 = 2 + 3 + 4 13 | 14 | Example 3: 15 | Input: 15 16 | Output: 4 17 | Explanation: 15 = 15 = 8 + 7 = 4 + 5 + 6 = 1 + 2 + 3 + 4 + 5 18 | 19 | Note: 1 <= N <= 10 ^ 9. 20 | */ 21 | 22 | /** 23 | * Approach: Mathematics 24 | * To be honest, this is a really good question, I love it! 25 | * If you are clear with Gauss formula, you can solve it quickly. 26 | * 27 | * let sum(m,n) = N; According to Gauss formula: 28 | * (m + n) * (n - m + 1) / 2 = N; 29 | * (m + n) * (n - m + 1) = 2 * N 30 | * 31 | * let's say: 32 | * a * b = 2 * N 33 | * Then we have: 34 | * 1. m + n = a 35 | * 2. n - m + 1 = b 36 | * plus 1 and 2 37 | * 2n + 1 = a + b 38 | * 39 | * so if a * b = 2* N and a + b is an odd number, there is a solution 40 | * 41 | * Time Complexity: O(sqrt(n)) 42 | */ 43 | class Solution { 44 | public int consecutiveNumbersSum(int N) { 45 | int rst = 0; 46 | // Make N = 2 * N 47 | N <<= 1; 48 | // Traverse the value of a 49 | for (int i = 1; i * i < N; i++) { 50 | // a * b = 2N and a + b is odd 51 | if (N % i == 0 && ((i + N / i) & 1) == 1) { 52 | rst++; 53 | } 54 | } 55 | return rst; 56 | } 57 | } -------------------------------------------------------------------------------- /Convert to Base -2/Convert to Base -2.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a number N, return a string consisting of "0"s and "1"s that 3 | represents its value in base -2 (negative two). 4 | 5 | The returned string must have no leading zeroes, unless the string is "0". 6 | 7 | Example 1: 8 | Input: 2 9 | Output: "110" 10 | Explantion: (-2) ^ 2 + (-2) ^ 1 = 2 11 | 12 | Example 2: 13 | Input: 3 14 | Output: "111" 15 | Explantion: (-2) ^ 2 + (-2) ^ 1 + (-2) ^ 0 = 3 16 | 17 | Example 3: 18 | Input: 4 19 | Output: "100" 20 | Explantion: (-2) ^ 2 = 4 21 | 22 | Note: 23 | 1. 0 <= N <= 10^9 24 | ''' 25 | 26 | # 解法详解参考同名 java 文件 27 | class Solution(object): 28 | def baseNeg2(self, N): 29 | """ 30 | :type N: int 31 | :rtype: str 32 | """ 33 | ans = [] 34 | while N != 0: 35 | reminder = N % -2 36 | N //= -2 37 | if reminder < 0: 38 | reminder += 2 39 | N += 1 40 | ans.append(str(reminder)) 41 | 42 | if len(ans) == 0: 43 | return "0" 44 | else: 45 | # Attetion here: 46 | # list.reverse() method acts in-place, and therefore returns None 47 | # "".join(ans.reverse()) will be wrong (can't be iterable) 48 | ans.reverse() 49 | return "".join(ans) 50 | -------------------------------------------------------------------------------- /Corporate Flight Bookings.java: -------------------------------------------------------------------------------- 1 | /* 2 | There are n flights, and they are labeled from 1 to n. 3 | We have a list of flight bookings. 4 | The i-th booking bookings[i] = [i, j, k] means that we booked k seats from flights labeled i to j inclusive. 5 | 6 | Return an array answer of length n, representing the number of seats booked on each flight in order of their label. 7 | 8 | Example 1: 9 | Input: bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5 10 | Output: [10,55,45,25,25] 11 | 12 | Constraints: 13 | 1. 1 <= bookings.length <= 20000 14 | 2. 1 <= bookings[i][0] <= bookings[i][1] <= n <= 20000 15 | 3. 1 <= bookings[i][2] <= 10000 16 | */ 17 | 18 | /** 19 | * Approach: Record the change and Accumulate 20 | * 这道题目在评论区出现了 线段树 和 Sweep Line 解法的解读。 21 | * 这两种方法确实可以很轻松地解决这个问题,但是未免小题大作了。 22 | * 我们不妨简单一点,因为要求的是最终每个站上有多少人。 23 | * 而题目又把每个站的人数变化告知我们了,因此只需要提前统计一下每个站的人数变化。 24 | * 然后最后依次累加下去就是我们最后需要的答案了。就是这么简单的逻辑... 25 | * 26 | * 时间复杂度:O(n) 27 | * 空间复杂度:O(1) 28 | */ 29 | class Solution { 30 | public int[] corpFlightBookings(int[][] bookings, int n) { 31 | int[] ans = new int[n]; 32 | for (int[] booking : bookings) { 33 | ans[booking[0] - 1] += booking[2]; 34 | // 注意别越界就行 35 | if (booking[1] < n) { 36 | ans[booking[1]] -= booking[2]; 37 | } 38 | } 39 | for (int i = 1; i < ans.length; i++) { 40 | ans[i] += ans[i - 1]; 41 | } 42 | return ans; 43 | } 44 | } -------------------------------------------------------------------------------- /Count Complete Tree Nodes.java: -------------------------------------------------------------------------------- 1 | Algorithm: 2 | The Solution is simply easy. You can get it from the comment in code. 3 | Complexity Analysis: 4 | We halve the tree in every recursive step, and we have O(log(n)) steps. 5 | Finding a height costs O(log(n)). 6 | So overall the time complexity is : O(log(n)^2). 7 | 8 | /* 9 | Given a complete binary tree, count the number of nodes. 10 | 11 | Definition of a complete binary tree from Wikipedia: 12 | In a complete binary tree every level, except possibly the last, is completely filled, 13 | and all nodes in the last level are as far left as possible. 14 | It can have between 1 and 2h nodes inclusive at the last level h. 15 | */ 16 | 17 | /** 18 | * Definition for a binary tree node. 19 | * public class TreeNode { 20 | * int val; 21 | * TreeNode left; 22 | * TreeNode right; 23 | * TreeNode(int x) { val = x; } 24 | * } 25 | */ 26 | class Solution { 27 | public int countNodes(TreeNode root) { 28 | int leftDepth = leftDepth(root); 29 | int rightDpeth = rightDepth(root); 30 | 31 | if (leftDepth == rightDpeth) { 32 | // if it's a full binary tree, then the result is 2^h - 1 33 | return (1 << leftDepth) - 1; 34 | } else { 35 | // if it isn't full binary tree, we call it recursively 36 | // left-subtree and right-subtree and plus 1. 37 | return countNodes(root.left) + countNodes(root.right) + 1; 38 | } 39 | } 40 | 41 | // get the left-subtree's height (including root node) 42 | private int leftDepth(TreeNode root) { 43 | int height = 0; 44 | while (root != null) { 45 | height++; 46 | root = root.left; 47 | } 48 | return height; 49 | } 50 | 51 | // get the right-subtree's height (including root node) 52 | private int rightDepth(TreeNode root) { 53 | int height = 0; 54 | while (root != null) { 55 | height++; 56 | root = root.right; 57 | } 58 | return height; 59 | } 60 | } -------------------------------------------------------------------------------- /Count Number of Nice Subarrays.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers nums and an integer k. A subarray is called nice if there are k odd numbers on it. 3 | Return the number of nice sub-arrays. 4 | 5 | Example 1: 6 | Input: nums = [1,1,2,1,1], k = 3 7 | Output: 2 8 | Explanation: The only sub-arrays with 3 odd numbers are [1,1,2,1] and [1,2,1,1]. 9 | 10 | Example 2: 11 | Input: nums = [2,4,6], k = 1 12 | Output: 0 13 | Explanation: There is no odd numbers in the array. 14 | 15 | Example 3: 16 | Input: nums = [2,2,2,1,2,2,1,2,2,2], k = 2 17 | Output: 16 18 | 19 | Constraints: 20 | 1. 1 <= nums.length <= 50000 21 | 2. 1 <= nums[i] <= 10^5 22 | 3. 1 <= k <= nums.length 23 | */ 24 | 25 | /** 26 | * Approach: Sliding Window with Reduction 27 | * 与问题 Subarrays with K Different Integers 非常类似。 28 | * 29 | * 时间复杂度:O(n) 30 | * 空间复杂度:O(1) 31 | * 32 | * Reference: 33 | * https://github.com/cherryljr/LeetCode/blob/master/Subarrays%20with%20K%20Different%20Integers.java 34 | * 35 | * PS. 这道问题还可以通过将 偶数看作0,奇数看作1。从而将问题转换成:求SubArray Sum等于 K 的子数组个数。 36 | * 对此使用 PreSum + HashMap 即可解决。但是明显这不是本题想要考察的,且空间复杂度也非最优,这里大家只需要知道即可。 37 | */ 38 | class Solution { 39 | public int numberOfSubarrays(int[] nums, int k) { 40 | return slidingWindow(nums, k) - slidingWindow(nums, k - 1); 41 | } 42 | 43 | private int slidingWindow(int[] nums, int k) { 44 | int count = 0, ans = 0; 45 | for (int begin = 0, end = 0; end < nums.length; end++) { 46 | if ((nums[end] & 1) == 1) { 47 | count++; 48 | } 49 | while (count > k) { 50 | if ((nums[begin++] & 1) == 1) { 51 | count--; 52 | } 53 | } 54 | ans += end - begin + 1; 55 | } 56 | return ans; 57 | } 58 | } -------------------------------------------------------------------------------- /Count Primes.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cherryljr/LeetCode/1b1868961adc8500b0d3bff95033ebf7c56e320f/Count Primes.java -------------------------------------------------------------------------------- /Daily Temperatures.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a list of daily temperatures, produce a list that, for each day in the input, 3 | tells you how many days you would have to wait until a warmer temperature. 4 | If there is no future day for which this is possible, put 0 instead. 5 | 6 | For example, given the list temperatures = [73, 74, 75, 71, 69, 72, 76, 73], 7 | your output should be [1, 1, 4, 2, 1, 1, 0, 0]. 8 | 9 | Note: The length of temperatures will be in the range [1, 30000]. 10 | Each temperature will be an integer in the range [30, 100]. 11 | */ 12 | 13 | /** 14 | * Approach: Monotonic Stack 15 | * 题目的实质就是找到当前数右边第一个比它大的数。 16 | * 因此可以使用 单调栈 在 O(n) 的时间内解决问题。 17 | * 值得注意的是: 18 | * 这里使用了 ArrayDeque 而不是 Stack. 19 | * 原因是 ArrayDeque 的效率会更高一些,并且 Java Doc 中也明确指出应该优先选择 ArrayDeque. 20 | * 当然如果你直接使用 数组 进行进一步优化的话可以更快。 21 | * 一些关于 ArrayDeque 的补充: 22 | * ArrayDeque 是 Deque 接口的一种具体实现,是依赖于可变数组来实现的。 23 | * ArrayDeque 没有容量限制,可根据需求自动进行扩容。 24 | * ArrayDeque 可以作为栈来使用,效率要高于 Stack; 25 | * ArrayDeque 也可以作为队列来使用,效率相较于基于双向链表的 LinkedList 也要更好一些。 26 | * 但是注意,ArrayDeque 不支持为 null 的元素。 27 | * 28 | * 类似问题: 29 | * https://github.com/cherryljr/LintCode/blob/master/Largest%20Rectangle%20in%20Histogram.java 30 | * https://github.com/cherryljr/LeetCode/blob/master/Online%20Stock%20Span.java 31 | * https://github.com/cherryljr/LeetCode/blob/master/Sum%20of%20Subarray%20Minimums.java 32 | */ 33 | class Solution { 34 | public int[] dailyTemperatures(int[] temperatures) { 35 | Deque stack = new ArrayDeque<>(); 36 | int[] rst = new int[temperatures.length]; 37 | for (int i = 0; i < temperatures.length; i++) { 38 | while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) { 39 | int index = stack.pop(); 40 | rst[index] = i - index; 41 | } 42 | stack.push(i); 43 | } 44 | return rst; 45 | } 46 | } -------------------------------------------------------------------------------- /Day of the Week.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a date, return the corresponding day of the week for that date. 3 | The input is given as three integers representing the day, month and year respectively. 4 | Return the answer as one of the following values {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}. 5 | 6 | Example 1: 7 | Input: day = 31, month = 8, year = 2019 8 | Output: "Saturday" 9 | 10 | Example 2: 11 | Input: day = 18, month = 7, year = 1999 12 | Output: "Sunday" 13 | 14 | Example 3: 15 | Input: day = 15, month = 8, year = 1993 16 | Output: "Sunday" 17 | 18 | Constraints: 19 | The given dates are valid dates between the years 1971 and 2100. 20 | */ 21 | 22 | /** 23 | * Approach: Zeller's Formula 24 | * 蔡勒公式:给定年月日,通过该公式可以计算得到当天是星期几。公式如下所示: 25 | * w = x + [x / 4] + [c / 4] - 2c + [26(m + 1) / 10] + d - 1 26 | * 其中,c表示年份前两位,x表示年份后两位,m表示月,1月和2月看成上一年的13月和14月,d表示日。方括号表示向下取整。 27 | * 对w对7进行取模即可知道是星期几,余数是0表示星期日,余数是1到6分别表示星期一到星期六。 28 | * 需要注意的是W可能是负值,因此需要对 w 进行 (w%7+7)%7 的操作来保证其结果落在 0~6 上面。 29 | * 30 | * 注意:适用于1582年10月15日之后, 因为罗马教皇格里高利十三世在这一天启用新历法。 31 | * 32 | * 时间复杂度:O(1) 33 | * 空间复杂度:O(1) 34 | */ 35 | class Solution { 36 | public String dayOfTheWeek(int day, int month, int year) { 37 | final String[] DAYS = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 38 | int dayIndex = getDayIndex(day, month, year); 39 | return DAYS[dayIndex]; 40 | } 41 | 42 | public int getDayIndex(int day, int month, int year) { 43 | if (month < 3) { 44 | month += 12; 45 | year--; 46 | } 47 | int century = year / 100; 48 | year %= 100; 49 | int w = year + year / 4 + century / 4 - 2 * century + 26 * (month + 1) / 10 + day - 1; 50 | return (w % 7 + 7) % 7; 51 | } 52 | } -------------------------------------------------------------------------------- /Defanging an IP Address/Defanging an IP Address.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a valid (IPv4) IP address, return a defanged version of that IP address. 3 | A defanged IP address replaces every period "." with "[.]". 4 | 5 | Example 1: 6 | Input: address = "1.1.1.1" 7 | Output: "1[.]1[.]1[.]1" 8 | 9 | Example 2: 10 | Input: address = "255.100.50.0" 11 | Output: "255[.]100[.]50[.]0" 12 | 13 | Constraints: 14 | 1. The given address is a valid IPv4 address. 15 | */ 16 | 17 | /** 18 | * Approach 1: Replace Function of String 19 | * 为什么我要把一道这么简单的题目放上来呢。。。 20 | * 不过大家可以去看下 String 中的 replace 和 replaceAll 这两个方法的源码, 21 | * 相信会有所收获的(replace 实际上调用了 replaceAll 方法) 22 | * 23 | * 时间复杂度:O(n) 24 | * 空间复杂度:O(n) 25 | */ 26 | class Solution { 27 | public String defangIPaddr(String address) { 28 | // return address.replace(".", "[.]"); 29 | return address.replaceAll("\\.", "[.]"); 30 | } 31 | } 32 | 33 | /** 34 | * Approach 2: Using StringBuilder 35 | * 如果你认真去看了 replaceAll 函数的实现,那么你应该很容易明白为什么这个解法在速度上快了一倍。 36 | * 37 | * 时间复杂度:O(n) 38 | * 空间复杂度:O(n) 39 | */ 40 | class Solution { 41 | public String defangIPaddr(String address) { 42 | StringBuilder ans = new StringBuilder(); 43 | for (char c : address.toCharArray()) { 44 | if (c != '.') { 45 | ans.append(c); 46 | } else { 47 | ans.append("[.]"); 48 | } 49 | } 50 | return ans.toString(); 51 | } 52 | } -------------------------------------------------------------------------------- /Defanging an IP Address/Defanging an IP Address.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a binary string S (a string consisting only of '0' and '1's) and a positive integer N, 3 | return true if and only if for every integer X from 1 to N, the binary representation of X is a substring of S. 4 | 5 | Example 1: 6 | Input: S = "0110", N = 3 7 | Output: true 8 | 9 | Example 2: 10 | Input: S = "0110", N = 4 11 | Output: false 12 | 13 | Note: 14 | 1. 1 <= S.length <= 1000 15 | 2. 1 <= N <= 10^9 16 | ''' 17 | 18 | # Approach: 19 | # 解法详解参考同名 java 文件 20 | class Solution: 21 | def defangIPaddr(self, address: str) -> str: 22 | return address.replace('.', '[.]') -------------------------------------------------------------------------------- /Delete Nodes And Return Forest/Delete Nodes And Return Forest.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the root of a binary tree, each node in the tree has a distinct value. 3 | After deleting all nodes with a value in to_delete, we are left with a forest (a disjoint union of trees). 4 | Return the roots of the trees in the remaining forest. You may return the result in any order. 5 | 6 | https://leetcode.com/problems/delete-nodes-and-return-forest/ 7 | Example 1: 8 | Input: root = [1,2,3,4,5,6,7], to_delete = [3,5] 9 | Output: [[1,2,null,4],[6],[7]] 10 | 11 | Constraints: 12 | 1. The number of nodes in the given tree is at most 1000. 13 | 2. Each node has a distinct value between 1 and 1000. 14 | 3. to_delete.length <= 1000 15 | 4. to_delete contains distinct values between 1 and 1000. 16 | ''' 17 | 18 | # Approach: Divide and Conquer 19 | # 时间复杂度:O(n) 20 | # 空间复杂度:O(n) 21 | # 解法详解参考同名 java 文件 22 | 23 | # Definition for a binary tree node. 24 | # class TreeNode: 25 | # def __init__(self, x): 26 | # self.val = x 27 | # self.left = None 28 | # self.right = None 29 | class Solution: 30 | def delNodes(self, root: TreeNode, to_delete: List[int]) -> List[TreeNode]: 31 | deleteSet = set(to_delete) 32 | ans = [] 33 | 34 | def dfs(root: TreeNode, isNewRoot: bool) -> TreeNode: 35 | if not root: return None 36 | shouldDelete = root.val in deleteSet 37 | if not shouldDelete and isNewRoot: 38 | ans.append(root) 39 | root.left = dfs(root.left, shouldDelete) 40 | root.right = dfs(root.right, shouldDelete) 41 | return None if shouldDelete else root 42 | 43 | dfs(root, True) 44 | return ans -------------------------------------------------------------------------------- /Distance Between Bus Stops.java: -------------------------------------------------------------------------------- 1 | /* 2 | A bus has n stops numbered from 0 to n - 1 that form a circle. 3 | We know the distance between all pairs of neighboring stops where distance[i] is the distance between the stops number i and (i + 1) % n. 4 | 5 | The bus goes along both directions i.e. clockwise and counterclockwise. 6 | Return the shortest distance between the given start and destination stops. 7 | 8 | Example 1: 9 | Input: distance = [1,2,3,4], start = 0, destination = 1 10 | Output: 1 11 | Explanation: Distance between 0 and 1 is 1 or 9, minimum is 1. 12 | 13 | 14 | Example 2: 15 | Input: distance = [1,2,3,4], start = 0, destination = 2 16 | Output: 3 17 | Explanation: Distance between 0 and 2 is 3 or 7, minimum is 3. 18 | 19 | Example 3: 20 | Input: distance = [1,2,3,4], start = 0, destination = 3 21 | Output: 4 22 | Explanation: Distance between 0 and 3 is 6 or 4, minimum is 4. 23 | 24 | Constraints: 25 | 1. 1 <= n <= 10^4 26 | 2. distance.length == n 27 | 3. 0 <= start, destination < n 28 | 4. 0 <= distance[i] <= 10^4 29 | */ 30 | 31 | /** 32 | * Approach: Traversal 33 | * 1. Make sure start comes before end; 34 | * 2. Calculate the sum of target interval as well as the total sum; 35 | * 3. The result will be the min of target interval sum and the remaining interval sum. 36 | * 37 | * Time Complexity: O(n) 38 | * Space Complexity: O(1) 39 | */ 40 | class Solution { 41 | public int distanceBetweenBusStops(int[] distance, int start, int destination) { 42 | if (start > destination) { 43 | int temp = start; 44 | start = destination; 45 | destination = temp; 46 | } 47 | 48 | int totalSum = 0, intervalSum = 0; 49 | for (int i = 0; i < distance.length; i++) { 50 | if (start <= i && i < destination) { 51 | intervalSum += distance[i]; 52 | } 53 | totalSum += distance[i]; 54 | } 55 | return Math.min(intervalSum, totalSum - intervalSum); 56 | } 57 | } -------------------------------------------------------------------------------- /Distant Barcodes/Distant Barcodes.py: -------------------------------------------------------------------------------- 1 | ''' 2 | In a warehouse, there is a row of barcodes, where the i-th barcode is barcodes[i]. 3 | Rearrange the barcodes so that no two adjacent barcodes are equal. 4 | You may return any answer, and it is guaranteed an answer exists. 5 | 6 | Example 1: 7 | Input: [1,1,1,2,2,2] 8 | Output: [2,1,2,1,2,1] 9 | 10 | Example 2: 11 | Input: [1,1,1,1,2,2,3,3] 12 | Output: [1,3,1,3,2,1,2,1] 13 | 14 | Note: 15 | 1. 1 <= barcodes.length <= 10000 16 | 2. 1 <= barcodes[i] <= 10000 17 | ''' 18 | 19 | # Approach: 01 Backpack 20 | # 时间复杂度:O(n) 21 | # 空间复杂度:O(n) 22 | # 解法详解参考同名 java 文件 23 | class Solution: 24 | def lastStoneWeightII(self, stones: List[int]) -> int: 25 | s = sum(stones) 26 | dp = [False] * (s // 2 + 1) 27 | dp[0] = True 28 | for i in range(len(stones)): 29 | for j in range(s >> 1, stones[i] - 1, -1): 30 | dp[j] |= dp[j - stones[i]] 31 | return min(s - i - i for i in range(s // 2 + 1) if dp[i]) -------------------------------------------------------------------------------- /Divisor Game/Divisor Game.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Alice and Bob take turns playing a game, with Alice starting first. 3 | Initially, there is a number N on the chalkboard. On each player's turn, that player makes a move consisting of: 4 | 5 | Choosing any x with 0 < x < N and N % x == 0. 6 | Replacing the number N on the chalkboard with N - x. 7 | Also, if a player cannot make a move, they lose the game. 8 | 9 | Return True if and only if Alice wins the game, assuming both players play optimally. 10 | 11 | Example 1: 12 | Input: 2 13 | Output: true 14 | Explanation: Alice chooses 1, and Bob has no more moves. 15 | 16 | Example 2: 17 | Input: 3 18 | Output: false 19 | Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more moves. 20 | 21 | Note: 22 | 1. 1 <= N <= 1000 23 | ''' 24 | 25 | # Approach: Mathematics 26 | # 解法详解参考同名 java 文件 27 | class Solution: 28 | def divisorGame(self, N: int) -> bool: 29 | return (N & 1) == 0 -------------------------------------------------------------------------------- /Domino and Tromino Tiling.java: -------------------------------------------------------------------------------- 1 | /* 2 | We have two types of tiles: a 2x1 domino shape, and an "L" tromino shape. These shapes may be rotated. 3 | XX <- domino 4 | XX <- "L" tromino 5 | X 6 | Given N, how many ways are there to tile a 2 x N board? Return your answer modulo 10^9 + 7. 7 | 8 | (In a tiling, every square must be covered by a tile. Two tilings are different 9 | if and only if there are two 4-directionally adjacent cells on the board 10 | such that exactly one of the tilings has both squares occupied by a tile.) 11 | 12 | Example: 13 | Input: 3 14 | Output: 5 15 | Explanation: 16 | The five different ways are listed below, different letters indicates different tiles: 17 | XYZ XXZ XYY XXY XYY 18 | XYZ YYZ XZZ XYY XXY 19 | 20 | Note: 21 | N will be in range [1, 1000]. 22 | */ 23 | 24 | /** 25 | * Approach: Sequence DP 26 | * 这类题刚刚开始看并没有什么想法,需要写出初始的几个状态,然后试着递推看看。 27 | * 通常就能发现规律,然后根据这个写出 递推方程(动态规划方程)即可。 28 | * 29 | * dp[i][0]:表示到 ith 列,全部完全铺满的方案个数 30 | * dp[i][1]:表示到 ith 列,剩余 左上角/右小角 一个格子未铺满的方案个数。 31 | * 则当前状态依赖于: 32 | * dp[i-2][0]: 还差 两列 完全铺满,则再加两个横条便能够得到当前状态; 33 | * dp[i-1][0]: 还差 一列 完全铺满,则再加一个竖条便能够得到当前状态; 34 | * 2 * dp[i-1][1]: 还差一个 L 完全铺满(缺的位置可以是 右上角 或者是 右下角), 35 | * 则再加一个 L 便可以得到当前状态。 36 | * 37 | * 类似的问题还有: 38 | * Dyeing Problem: 39 | * https://github.com/cherryljr/LintCode/blob/master/Dyeing%20Problem.java 40 | * Find the Derangement of An Array: 41 | * https://github.com/cherryljr/LintCode/blob/master/Find%20the%20Derangement%20of%20An%20Array.java 42 | * 43 | * 参考资料:https://www.youtube.com/watch?v=S-fUTfqrdq8 44 | */ 45 | class Solution { 46 | private static final int MOD = 1000000007; 47 | 48 | public int numTilings(int N) { 49 | long[][] dp = new long[N + 1][2]; 50 | dp[0][0] = 1; 51 | dp[1][0] = 1; 52 | for (int i = 2; i <= N; i++) { 53 | // 因为这边使用了 long 所以在相加时不担心溢出,如果是 int 的话,运算过程中也需要取模才行 54 | dp[i][0] = (dp[i - 2][0] + dp[i - 1][0] + 2 * dp[i - 1][1]) % MOD; 55 | dp[i][1] = (dp[i - 2][0] + dp[i - 1][1]) % MOD; 56 | } 57 | return (int)dp[N][0]; 58 | } 59 | } -------------------------------------------------------------------------------- /Duplicate Zeros/Duplicate Zeros.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a fixed length array arr of integers, duplicate each occurrence of zero, shifting the remaining elements to the right. 3 | Note that elements beyond the length of the original array are not written. 4 | Do the above modifications to the input array in place, do not return anything from your function. 5 | 6 | Example 1: 7 | Input: [1,0,2,3,0,4,5,0] 8 | Output: null 9 | Explanation: After calling your function, the input array is modified to: [1,0,0,2,3,0,0,4] 10 | 11 | Example 2: 12 | Input: [1,2,3] 13 | Output: null 14 | Explanation: After calling your function, the input array is modified to: [1,2,3] 15 | 16 | Note: 17 | 1. 1 <= arr.length <= 10000 18 | 2. 0 <= arr[i] <= 9 19 | */ 20 | 21 | /** 22 | * Approach: Similar to Add Spaces 23 | * 题意:将数组中所有出现的 0 进行一次重复,即原本的 '0' 变成 "00",原本的 "00" 则会变成 "0000", 24 | * 而对于其他元素,就顺着往后移动即可。要求不能够使用额外空间,在原本的 arr 上进行操作。 25 | * 26 | * 对此,我们可以通过遍历两次该数据来解决这个问题。 27 | * 第一次遍历的时候,计算数组中有几个 0(记作 shift),这就意味着我们数组上的元素将会进行大小为 shift 的向右偏移。 28 | * 第二次遍历时,我们 从右向左 进行遍历,对于 非零的元素 将其进行一定的偏移放入合适的位置即可, 29 | * 对于 0,我们同样将其放入对应的位置后,需要对偏移量 shift 进行 -1 操作。 30 | * eg. [1,0,2,3,0,4,5,0] 进行重复0的扩展后将会得到 [1,0,0,2,3,0,0,4],5,0,0 而我们需要的答案就是前 8 个元素。 31 | * 将其放入对应的位置上即可。 32 | * 这里我们第二次遍历的方向时 从右向左,是因为我们无法使用额外空间,而 从左向右 遍历会使得填充时丢失信息。 33 | * 和 “不使用额外空间添加空格问题” 的所使用的技巧是一样的。 34 | * 35 | * 时间复杂度:O(n) 36 | * 空间复杂度:O(1) 37 | */ 38 | class Solution { 39 | public void duplicateZeros(int[] arr) { 40 | int shift = 0; 41 | // Count the number of 0s 42 | for (int i = 0; i < arr.length; i++) { 43 | shift += arr[i] == 0 ? 1 : 0; 44 | } 45 | 46 | for (int i = arr.length - 1; i >= 0; i--) { 47 | // if the current value can be fit 48 | if (shift + i < arr.length) { 49 | arr[shift + i] = arr[i]; 50 | } 51 | // if the current value is 0, shift-- 52 | // and arr[shift + i] should also be 0 (duplicate) 53 | if (arr[i] == 0 && --shift + i < arr.length) { 54 | arr[shift + i] = 0; 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Duplicate Zeros/Duplicate Zeros.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a fixed length array arr of integers, duplicate each occurrence of zero, shifting the remaining elements to the right. 3 | Note that elements beyond the length of the original array are not written. 4 | Do the above modifications to the input array in place, do not return anything from your function. 5 | 6 | Example 1: 7 | Input: [1,0,2,3,0,4,5,0] 8 | Output: null 9 | Explanation: After calling your function, the input array is modified to: [1,0,0,2,3,0,0,4] 10 | 11 | Example 2: 12 | Input: [1,2,3] 13 | Output: null 14 | Explanation: After calling your function, the input array is modified to: [1,2,3] 15 | 16 | Note: 17 | 1. 1 <= arr.length <= 10000 18 | 2. 0 <= arr[i] <= 9 19 | ''' 20 | 21 | # Approach: Similar to Add Spaces 22 | # 时间复杂度:O(n) 23 | # 空间复杂度:O(1) 24 | # 解法详解参考同名 java 文件 25 | class Solution: 26 | def duplicateZeros(self, arr: List[int]) -> None: 27 | """ 28 | Do not return anything, modify arr in-place instead. 29 | """ 30 | shift, n = 0, len(arr) 31 | for x in arr: 32 | if x == 0: 33 | shift += 1 34 | 35 | for i in range(n - 1, -1, -1): 36 | if i + shift < n: 37 | arr[i + shift] = arr[i] 38 | if arr[i] == 0: 39 | shift -= 1 40 | if shift + i < n: 41 | arr[shift + i] = arr[i] -------------------------------------------------------------------------------- /Find Peak Element.java: -------------------------------------------------------------------------------- 1 | 通过二分法来查找 局部最大值。 2 | 与 NowCoder 中的 二分法查找局部最小值 解法相同。 3 | 这道题给了我们一个启示: 4 | 只要是具有 排他性,都能够使用二分法。而不一定要经过排序。 5 | 6 | /* 7 | A peak element is an element that is greater than its neighbors. 8 | 9 | Given an input array where num[i] ≠ num[i+1], find a peak element and return its index. 10 | 11 | The array may contain multiple peaks, in that case return the index to any one of the peaks is fine. 12 | 13 | You may imagine that num[-1] = num[n] = -∞. 14 | 15 | For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2. 16 | */ 17 | 18 | class Solution { 19 | public int findPeakElement(int[] nums) { 20 | if (nums == null || nums.length <= 1) { 21 | return 0; 22 | } 23 | 24 | int len = nums.length; 25 | if (nums[0] > nums[1]) { 26 | return 0; 27 | } 28 | if (nums[len - 1] > nums[len - 2]) { 29 | return len - 1; 30 | } 31 | 32 | int start = 0; 33 | int end = len - 1; 34 | while (start + 1 < end) { 35 | int mid = start + (end - start) / 2; 36 | if (nums[mid] < nums[mid + 1]) { 37 | start = mid; 38 | } else { 39 | end = mid; 40 | } 41 | } 42 | 43 | return (nums[start] > nums[start + 1]) ? start : end; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /First Missing Positive.java: -------------------------------------------------------------------------------- 1 | First Method, we can deal with it by QuickSort. 2 | Then scan the array, find the first misssing positive. 3 | This method will cost O(nlogn) Time Complexity, O(1) Space Complexity. 4 | Can't meet the demand. 5 | 6 | Second Method, we can use HashMap to restore the number and its occurence. 7 | Then scan the array, find the first missing positive. 8 | As we all know, the operation of HashMap will cost O(1) time once. 9 | But this method will cost O(n) extra space. 10 | So, it can't meet the demand also. 11 | 12 | Third Method - Put each number in its right place. 13 | The first missing positive must be within [1, index + 1]. 14 | The reason is like you put index balls into index+1 bins, there must be a bin empty, the empty bin can be viewed as the missing number. 15 | 16 | The main idea is: nums[index] restore the number: index+1. 17 | each time we encounter an valid intger, 18 | find the correct position and swap, otherwise continue. 19 | Time Complexity: O(n) 20 | Space Complxity: O(1) 21 | 22 | /* 23 | Given an unsorted integer array, find the first missing positive integer. 24 | 25 | For example, 26 | Given [1,2,0] return 3, 27 | and [3,4,-1,1] return 2. 28 | 29 | Your algorithm should run in O(n) time and uses constant space. 30 | */ 31 | 32 | class Solution { 33 | public int firstMissingPositive(int[] nums) { 34 | if (nums == null || nums.length == 0) { 35 | return 1; 36 | } 37 | 38 | for (int i = 0; i < nums.length; i++) { 39 | // Swap the number until they are in the right position. 40 | while (nums[i] >= 1 && nums[i] <= nums.length && nums[i] != nums[nums[i] - 1]) { 41 | int temp = nums[nums[i] - 1]; 42 | nums[nums[i] - 1] = nums[i]; 43 | nums[i] = temp; 44 | } 45 | } 46 | 47 | for (int i = 0; i < nums.length; i++) { 48 | if (nums[i] != i + 1) { 49 | return i + 1; 50 | } 51 | } 52 | return nums.length + 1; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Flip Columns For Maximum Number of Equal Rows/Flip Columns For Maximum Number of Equal Rows.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a matrix consisting of 0s and 1s, we may choose any number of columns in the matrix and flip every cell in that column. 3 | Flipping a cell changes the value of that cell from 0 to 1 or from 1 to 0. 4 | 5 | Return the maximum number of rows that have all values equal after some number of flips. 6 | 7 | Example 1: 8 | Input: [[0,1],[1,1]] 9 | Output: 1 10 | Explanation: After flipping no values, 1 row has all values equal. 11 | 12 | Example 2: 13 | Input: [[0,1],[1,0]] 14 | Output: 2 15 | Explanation: After flipping values in the first column, both rows have equal values. 16 | 17 | Example 3: 18 | Input: [[0,0,0],[0,0,1],[1,1,0]] 19 | Output: 2 20 | Explanation: After flipping values in the first two columns, the last two rows have equal values. 21 | 22 | Note: 23 | 1. 1 <= matrix.length <= 300 24 | 2. 1 <= matrix[i].length <= 300 25 | 3. All matrix[i].length's are equal 26 | 4. matrix[i][j] is 0 or 1 27 | ''' 28 | 29 | # Approach 1: Find the Most Frequent Pattern and Opposite Pattern 30 | # 时间复杂度:O(N*M) 31 | # 空间复杂度:O(N*M) 32 | # 解法详解参考同名 java 文件 33 | class Solution: 34 | def maxEqualRowsAfterFlips(self, matrix: List[List[int]]) -> int: 35 | d = collections.defaultdict(int) 36 | for r in matrix: 37 | d[tuple(r)] += 1 38 | d[tuple([1 ^ i for i in r])] += 1 39 | return max(d.values()) 40 | 41 | # Approach 2: Python in One Line 42 | class Solution: 43 | def maxEqualRowsAfterFlips(self, matrix: List[List[int]]) -> int: 44 | return max(collections.Counter(tuple(x ^ r[0] for x in r) for r in matrix).values()) -------------------------------------------------------------------------------- /Flip String to Monotone Increasing.java: -------------------------------------------------------------------------------- 1 | /* 2 | A string of '0's and '1's is monotone increasing if it consists of some number of '0's (possibly 0), 3 | followed by some number of '1's (also possibly 0.) 4 | 5 | We are given a string S of '0's and '1's, and we may flip any '0' to a '1' or a '1' to a '0'. 6 | Return the minimum number of flips to make S monotone increasing. 7 | 8 | Example 1: 9 | Input: "00110" 10 | Output: 1 11 | Explanation: We flip the last digit to get 00111. 12 | 13 | Example 2: 14 | Input: "010110" 15 | Output: 2 16 | Explanation: We flip to get 011111, or alternatively 000111. 17 | 18 | Example 3: 19 | Input: "00011000" 20 | Output: 2 21 | Explanation: We flip to get 00000000. 22 | 23 | Note: 24 | 1 <= S.length <= 20000 25 | S only consists of '0' and '1' characters. 26 | */ 27 | 28 | /** 29 | * Approach: DP Prefix + Suffix 30 | */ 31 | class Solution { 32 | public int minFlipsMonoIncr(String S) { 33 | if (S == null || S.length() <= 1) { 34 | return 0; 35 | } 36 | 37 | int len = S.length(); 38 | // left[0] 代表不进行任何 '1'->'0' 的转换,left[len] 代表将S中的'1'全部转换成'0' 39 | int[] left = new int[len + 1]; 40 | // right[0] 代表将S中的'0'全部转换成'1',right[len]代表不进行任何 '0'->'1' 的转换 41 | int[] right = new int[len + 1]; 42 | // 将左半部分全部转换成'0',即计算左半部分有多少个'1'即可 43 | for (int i = 1; i <= len; i++) { 44 | left[i] = left[i - 1] + S.charAt(i - 1) - '0'; 45 | } 46 | // 将右半部分全部转换成'1',即计算右半部分有多少个'0'即可 47 | for (int i = len - 1; i >= 0; i--) { 48 | right[i] = right[i + 1] + '1' - S.charAt(i); 49 | } 50 | 51 | int rst = Integer.MAX_VALUE; 52 | for (int i = 0; i <= len; i++) { 53 | rst = Math.min(rst, left[i] + right[i]); 54 | } 55 | return rst; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Flower Planting With No Adjacent/Flower Planting With No Adjacent.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You have N gardens, labelled 1 to N. In each garden, you want to plant one of 4 types of flowers. 3 | paths[i] = [x, y] describes the existence of a bidirectional path from garden x to garden y. 4 | Also, there is no garden that has more than 3 paths coming into or leaving it. 5 | 6 | Your task is to choose a flower type for each garden such that, for any two gardens connected by a path, they have different types of flowers. 7 | Return any such a choice as an array answer, where answer[i] is the type of flower planted in the (i+1)-th garden. 8 | The flower types are denoted 1, 2, 3, or 4. It is guaranteed an answer exists. 9 | 10 | Example 1: 11 | Input: N = 3, paths = [[1,2],[2,3],[3,1]] 12 | Output: [1,2,3] 13 | 14 | Example 2: 15 | Input: N = 4, paths = [[1,2],[3,4]] 16 | Output: [1,2,1,2] 17 | 18 | Example 3: 19 | Input: N = 4, paths = [[1,2],[2,3],[3,4],[4,1],[1,3],[2,4]] 20 | Output: [1,2,3,4] 21 | 22 | Note: 23 | 1. 1 <= N <= 10000 24 | 2. 0 <= paths.size <= 20000 25 | 3. No garden has 4 or more paths coming into or leaving it. 26 | 4. It is guaranteed an answer exists. 27 | ''' 28 | 29 | # Approach: Greedy + BFS 30 | # 时间复杂度:O(paths) = O(1.5N) ==> O(N) 31 | # 空间复杂度:O(N) 32 | # 解法详解参考同名 java 文件 33 | class Solution: 34 | def gardenNoAdj(self, N: int, paths: List[List[int]]) -> List[int]: 35 | graph = [[] for _ in range(N)] 36 | # Build the graph 37 | for path in paths: 38 | graph[path[0] - 1].append(path[1] - 1) 39 | graph[path[1] - 1].append(path[0] - 1) 40 | 41 | ans = [0] * N 42 | for i in range(N): 43 | # 利用Python中 set 可以相减的操作,从可能的颜色中排除掉已被使用的颜色, 44 | # 然后从剩下的集合中 pop() 出一个作为当前的颜色即可 45 | ans[i] = ({1, 2, 3, 4} - {ans[j] for j in graph[i]}).pop() 46 | return ans -------------------------------------------------------------------------------- /Get Equal Substrings Within Budget.java: -------------------------------------------------------------------------------- 1 | /* 2 | You are given two strings s and t of the same length. You want to change s to t. 3 | Changing the i-th character of s to i-th character of t costs |s[i] - t[i]| that is, 4 | the absolute difference between the ASCII values of the characters. 5 | 6 | You are also given an integer maxCost. 7 | 8 | Return the maximum length of a substring of s that can be changed to be the same as 9 | the corresponding substring of twith a cost less than or equal to maxCost. 10 | 11 | If there is no substring from s that can be changed to its corresponding substring from t, return 0. 12 | 13 | Example 1: 14 | Input: s = "abcd", t = "bcdf", maxCost = 3 15 | Output: 3 16 | Explanation: "abc" of s can change to "bcd". That costs 3, so the maximum length is 3. 17 | 18 | Example 2: 19 | Input: s = "abcd", t = "cdef", maxCost = 3 20 | Output: 1 21 | Explanation: Each character in s costs 2 to change to charactor in t, so the maximum length is 1. 22 | 23 | Example 3: 24 | Input: s = "abcd", t = "acde", maxCost = 0 25 | Output: 1 26 | Explanation: You can't make any change, so the maximum length is 1. 27 | 28 | Constraints: 29 | 1. 1 <= s.length, t.length <= 10^5 30 | 2. 0 <= maxCost <= 10^6 31 | 3. s and t only contain lower case English letters. 32 | */ 33 | 34 | /** 35 | * Approach: Sliding Window 36 | * Time Complexity: O(n) 37 | * Space Complexity: O(1) 38 | */ 39 | class Solution { 40 | public int equalSubstring(String s, String t, int maxCost) { 41 | int n = s.length(), cost = 0, ans = 0; 42 | for (int left = 0, right = 0; right < n; right++) { 43 | if (s.charAt(right) != t.charAt(right)) { 44 | cost += Math.abs(s.charAt(right) - t.charAt(right)); 45 | while (cost > maxCost) { 46 | cost -= Math.abs(s.charAt(left) - t.charAt(left)); 47 | left++; 48 | } 49 | } 50 | ans = Math.max(ans, right - left + 1); 51 | } 52 | return ans; 53 | } 54 | } -------------------------------------------------------------------------------- /Gray Code.java: -------------------------------------------------------------------------------- 1 | /* 2 | The gray code is a binary numeral system where two successive values differ in only one bit. 3 | Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. 4 | A gray code sequence must begin with 0. 5 | 6 | For example, given n = 2, return [0,1,3,2]. Its gray code sequence is: 7 | 00 - 0 8 | 01 - 1 9 | 11 - 3 10 | 10 - 2 11 | 12 | Note: 13 | For a given n, a gray code sequence is not uniquely defined. 14 | For example, [0,2,3,1] is also a valid gray code sequence according to the above definition. 15 | For now, the judge is able to judge based on one instance of gray code sequence. Sorry about that. 16 | */ 17 | 18 | // Before this, let's look at two functions about Gray Code first. 19 | /** 20 | * Funtion 1 21 | * The purpose of this function is to convert an unsigned 22 | * binary number to reflected binary Gray code. 23 | * The operator >> is shift right. The operator ^ is exclusive or. 24 | */ 25 | long binaryToGray(long num) 26 | { 27 | return (num >> 1) ^ num; 28 | } 29 | 30 | /** 31 | * Funtion 2 32 | * The purpose of this function is to convert a reflected binary 33 | * Gray code number to a binary number. 34 | * Each Gray code bit is exclusive-ored with all 35 | * more significant bits. 36 | */ 37 | long grayToBinary(long num) 38 | { 39 | long mask; 40 | for (mask = num >> 1; mask != 0; mask = mask >> 1) 41 | { 42 | num = num ^ mask; 43 | } 44 | return num; 45 | } 46 | 47 | // Now, we can write the solution easily. 48 | class Solution { 49 | public List grayCode(int n) { 50 | List rst = new ArrayList<>(); 51 | for (int i = 0; i < (1 << n); i++) { 52 | // convert an number to Gray Code. 53 | rst.add(i ^ (i >> 1)); 54 | } 55 | return rst; 56 | } 57 | } -------------------------------------------------------------------------------- /Greatest Common Divisor of Strings/Greatest Common Divisor of Strings.java: -------------------------------------------------------------------------------- 1 | /* 2 | For strings S and T, we say "T divides S" if and only if S = T + ... + T (T concatenated with itself 1 or more times) 3 | Return the largest string X such that X divides str1 and X divides str2. 4 | 5 | Example 1: 6 | Input: str1 = "ABCABC", str2 = "ABC" 7 | Output: "ABC" 8 | 9 | Example 2: 10 | Input: str1 = "ABABAB", str2 = "ABAB" 11 | Output: "AB" 12 | 13 | Example 3: 14 | Input: str1 = "LEET", str2 = "CODE" 15 | Output: "" 16 | 17 | Note: 18 | 1. 1 <= str1.length <= 1000 19 | 2. 1 <= str2.length <= 1000 20 | 3. str1[i] and str2[i] are English uppercase letters. 21 | */ 22 | 23 | /** 24 | * Approach: Imitate GCD Algorithm (Recursion) 25 | * 该解法直接模拟 GCD 的求法即可,步骤如下: 26 | * 1.如果较长的字符串是以较短的字符串为开头(startsWith),那么我们就从较长字符串中去除掉较短字符串的这部分; 27 | * 2.重复上述步骤,直到较短的字符串为空,此时说明较长的字符串就是我们要找的 GCD String。 28 | * 3.如果较长的字符串不是以较短的字符串作为开头,那么说明二者不存在 GCD String,返回 "" 即可。 29 | * 30 | * 时间复杂度: 31 | * 介于 Java 中字符串操作的特性,由于本解法递归使用了 startsWith 和 substring 函数。 32 | * 因此在最坏情况下(共同序列只有一个字符),时间复杂度为:1 + 2 + 3 + ... + n = n * (n + 1) / 2,即 O(n^2) 33 | * 空间复杂度:O(n^2),原因同时间复杂度分析。 34 | */ 35 | class Solution { 36 | public String gcdOfStrings(String str1, String str2) { 37 | if (str1.length() < str2.length()) { 38 | // make sure str1 is not shorter than str2 39 | return gcdOfStrings(str2, str1); 40 | } else if (!str1.startsWith(str2)) { 41 | // if shorter string is not common prefix, the answer not exists. 42 | return ""; 43 | } else if (str2.isEmpty()) { 44 | // gcd string found 45 | return str1; 46 | } else { 47 | // cut off the common prefix part of str1 48 | return gcdOfStrings(str1.substring(str2.length()), str2); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Greatest Common Divisor of Strings/Greatest Common Divisor of Strings.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a binary string S (a string consisting only of '0' and '1's) and a positive integer N, 3 | return true if and only if for every integer X from 1 to N, the binary representation of X is a substring of S. 4 | 5 | Example 1: 6 | Input: S = "0110", N = 3 7 | Output: true 8 | 9 | Example 2: 10 | Input: S = "0110", N = 4 11 | Output: false 12 | 13 | Note: 14 | 1. 1 <= S.length <= 1000 15 | 2. 1 <= N <= 10^9 16 | ''' 17 | 18 | # Approach: Imitate GCD Algorithm (Recursion) 19 | # 时间复杂度:O(n^2) 20 | # 空间复杂度:O(n^2) 21 | # 解法详解参考同名 java 文件 22 | class Solution: 23 | def gcdOfStrings(self, str1: str, str2: str) -> str: 24 | if len(str1) < len(str2): 25 | return self.gcdOfStrings(str2, str1) 26 | elif str1[:len(str2)] != str2: 27 | return "" 28 | elif len(str2) == 0: 29 | return str1 30 | else: 31 | return self.gcdOfStrings(str1[len(str2):], str2) -------------------------------------------------------------------------------- /Grumpy Bookstore Owner/Grumpy Bookstore Owner.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Today, the bookstore owner has a store open for customers.length minutes. 3 | Every minute, some number of customers (customers[i]) enter the store, and all those customers leave after the end of that minute. 4 | 5 | On some minutes, the bookstore owner is grumpy. 6 | If the bookstore owner is grumpy on the i-th minute, grumpy[i] = 1, otherwise grumpy[i] = 0. 7 | When the bookstore owner is grumpy, the customers of that minute are not satisfied, otherwise they are satisfied. 8 | 9 | The bookstore owner knows a secret technique to keep themselves not grumpy for X minutes straight, but can only use it once. 10 | Return the maximum number of customers that can be satisfied throughout the day. 11 | 12 | Example 1: 13 | Input: customers = [1,0,1,2,1,1,7,5], grumpy = [0,1,0,1,0,1,0,1], X = 3 14 | Output: 16 15 | Explanation: The bookstore owner keeps themselves not grumpy for the last 3 minutes. 16 | The maximum number of customers that can be satisfied = 1 + 1 + 1 + 1 + 7 + 5 = 16. 17 | 18 | Note: 19 | 1. 1 <= X <= customers.length == grumpy.length <= 20000 20 | 2. 0 <= customers[i] <= 1000 21 | 3. 0 <= grumpy[i] <= 1 22 | ''' 23 | 24 | # Approach: Sliding Window (Fixed Length) 25 | # 时间复杂度:O(n) 26 | # 空间复杂度:O(1) 27 | # 解法详解参考同名 java 文件 28 | class Solution: 29 | def maxSatisfied(self, customers: List[int], grumpy: List[int], X: int) -> int: 30 | satisfied, useTechnique, maxi = 0, 0, 0 31 | for i in range(len(customers)): 32 | if grumpy[i] == 0: 33 | satisfied += customers[i] 34 | else: 35 | useTechnique += customers[i] 36 | if i >= X: 37 | useTechnique -= grumpy[i - X] * customers[i - X] 38 | maxi = max(maxi, useTechnique) 39 | return satisfied + maxi -------------------------------------------------------------------------------- /Hamming Distance.java: -------------------------------------------------------------------------------- 1 | /* 2 | The Hamming distance between two integers is the number of positions at which the corresponding bits are different. 3 | Given two integers x and y, calculate the Hamming distance. 4 | 5 | Note: 6 | 0 ≤ x,y < 2^31. 7 | 8 | Example: 9 | Input: x = 1, y = 4 10 | Output: 2 11 | 12 | Explanation: 13 | 1 (0 0 0 1) 14 | 4 (0 1 0 0) 15 | ↑ ↑ 16 | 17 | The above arrows point to positions where the corresponding bits are different. 18 | */ 19 | 20 | /** 21 | * Approach: Bit Manipulation 22 | * 根据 Hamming distance 对于两个整数,它要求的是二进制有几个位上是不同的。 23 | * 对此我们很容易想到 异或运算。 24 | * 令 n = x^y,然后我们只需要求 n 的二进制表示中含有几个 1 即可。 25 | * 这样问题就转换成了 26 | * Count 1 in Binary: 27 | * https://github.com/cherryljr/LintCode/edit/master/Count%201%20in%20Binary.java 28 | * 29 | * 这道问题实际上与 LintCode 上的 Flip Bits 完全一样,只是换个方式问罢了: 30 | * https://github.com/cherryljr/LintCode/blob/master/Flip%20Bits.java 31 | */ 32 | class Solution { 33 | public int hammingDistance(int x, int y) { 34 | int count = 0; 35 | int n = x ^ y; 36 | while (n > 0) { 37 | n = n & (n - 1); 38 | count++; 39 | } 40 | return count; 41 | } 42 | } -------------------------------------------------------------------------------- /Height Checker/Height Checker.java: -------------------------------------------------------------------------------- 1 | /* 2 | Students are asked to stand in non-decreasing order of heights for an annual photo. 3 | Return the minimum number of students not standing in the right positions. 4 | (This is the number of students that must move in order for all students to be standing in non-decreasing order of height.) 5 | 6 | Example 1: 7 | Input: [1,1,4,2,1,3] 8 | Output: 3 9 | Explanation: 10 | Students with heights 4, 3 and the last 1 are not standing in the right positions. 11 | 12 | Note: 13 | 1. 1 <= heights.length <= 100 14 | 2. 1 <= heights[i] <= 100 15 | */ 16 | 17 | /** 18 | * Approach: Sort and Compare 19 | * 题目要求当前学生身高的排列有几个不在排列后的正确位置上(从小到大排列)。 20 | * 因为给出的数据量只有 100,所以可以采用排序然后遍历一遍进行比较的方法即可(非常直接的解法,没啥好说的)。 21 | * 22 | * 时间复杂度:O(nlogn) 23 | * 空间复杂度:O(n) 24 | */ 25 | class Solution { 26 | public int heightChecker(int[] heights) { 27 | int[] copy = heights.clone(); 28 | Arrays.sort(copy); 29 | int count = 0; 30 | for (int i = 0; i < heights.length; i++) { 31 | if (heights[i] != copy[i]) { 32 | count++; 33 | } 34 | } 35 | return count; 36 | } 37 | } -------------------------------------------------------------------------------- /Height Checker/Height Checker.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Students are asked to stand in non-decreasing order of heights for an annual photo. 3 | Return the minimum number of students not standing in the right positions. 4 | (This is the number of students that must move in order for all students to be standing in non-decreasing order of height.) 5 | 6 | Example 1: 7 | Input: [1,1,4,2,1,3] 8 | Output: 3 9 | Explanation: 10 | Students with heights 4, 3 and the last 1 are not standing in the right positions. 11 | 12 | Note: 13 | 1. 1 <= heights.length <= 100 14 | 2. 1 <= heights[i] <= 100 15 | ''' 16 | 17 | # Approach: Sort and Compare 18 | # 时间复杂度:O(nlogn) 19 | # 空间复杂度:O(n) 20 | # 解法详解参考同名 java 文件 21 | class Solution: 22 | def heightChecker(self, heights: List[int]) -> int: 23 | sorted_heights, count = sorted(heights), 0 24 | for i in range(len(heights)): 25 | if heights[i] != sorted_heights[i]: 26 | count += 1 27 | return count -------------------------------------------------------------------------------- /Implement Stack Using Array.java: -------------------------------------------------------------------------------- 1 | /* 2 | Description 3 | Implement a stack. You can use any data structure inside a stack except stack itself to implement it. 4 | 5 | Example 6 | push(1) 7 | pop() 8 | push(2) 9 | top() // return 2 10 | pop() 11 | isEmpty() // return true 12 | push(3) 13 | isEmpty() // return false 14 | Tags 15 | Array Stack 16 | */ 17 | 18 | /** 19 | * Approach: Using Array 20 | * 用 数组 模拟一个栈。 21 | * 我们只需要用一个 size 指针始终跟踪栈顶元素即可。 22 | * 因为所有的操作都发生在 数组的尾部(栈顶)。 23 | * 因此 size 还能代表数组的大小。 24 | * 25 | * 参考资料: 26 | * https://www.geeksforgeeks.org/stack-data-structure-introduction-program/ 27 | */ 28 | public class ArrayStack { 29 | private Integer[] arr; 30 | private Integer size; 31 | 32 | // 开辟一个固定大小的栈 33 | public ArrayStack(int initSize) { 34 | if (initSize < 0) { 35 | throw new IllegalArgumentException("The init size is less than 0"); 36 | } 37 | arr = new Integer[initSize]; 38 | size = 0; 39 | } 40 | 41 | public Integer peek() { 42 | if (size == 0) { 43 | return null; 44 | } 45 | return arr[size - 1]; 46 | } 47 | 48 | public void push(int value) { 49 | if (size == arr.length) { 50 | throw new ArrayIndexOutOfBoundsException("The stack is full"); 51 | } 52 | arr[size++] = value; 53 | } 54 | 55 | public Integer pop() { 56 | if (size == 0) { 57 | throw new ArrayIndexOutOfBoundsException("The stack is empty"); 58 | } 59 | return arr[--size]; 60 | } 61 | } -------------------------------------------------------------------------------- /Insufficient Nodes in Root to Leaf Paths/Insufficient Nodes in Root to Leaf Paths.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the root of a binary tree, consider all root to leaf paths: paths from the root to any leaf. (A leaf is a node with no children.) 3 | A node is insufficient if every such root to leaf path intersecting this node has sum strictly less than limit. 4 | Delete all insufficient nodes simultaneously, and return the root of the resulting binary tree. 5 | 6 | https://leetcode.com/problems/insufficient-nodes-in-root-to-leaf-paths/ 7 | Example 1: 8 | Input: root = [1,2,3,4,-99,-99,7,8,9,-99,-99,12,13,-99,14], limit = 1 9 | Output: [1,2,3,4,null,null,7,8,9,null,14] 10 | 11 | Example 2: 12 | Input: root = [5,4,8,11,null,17,4,7,1,null,null,5,3], limit = 22 13 | Output: [5,4,8,11,null,17,4,7,null,null,null,5] 14 | 15 | Example 3: 16 | Input: root = [1,2,-3,-5,null,4,null], limit = -1 17 | Output: [1,null,-3,4] 18 | 19 | Note: 20 | 1. The given tree will have between 1 and 5000 nodes. 21 | 2. -10^5 <= node.val <= 10^5 22 | 3. -10^9 <= limit <= 10^9 23 | ''' 24 | 25 | # Approach: Divide and Conquer (Top-Down) 26 | # 时间复杂度:O(n) 27 | # 空间复杂度:O(h) h is the height of tree 28 | # 解法详解参考同名 java 文件 29 | 30 | # Definition for a binary tree node. 31 | # class TreeNode: 32 | # def __init__(self, x): 33 | # self.val = x 34 | # self.left = None 35 | # self.right = None 36 | class Solution: 37 | def sufficientSubset(self, root: TreeNode, limit: int) -> TreeNode: 38 | if root == None: return None 39 | if root.left == root.right == None: 40 | return None if root.val < limit else root 41 | root.left = self.sufficientSubset(root.left, limit - root.val) 42 | root.right = self.sufficientSubset(root.right, limit - root.val) 43 | return None if root.left == root.right == None else root 44 | -------------------------------------------------------------------------------- /Integer to Roman.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer, convert it to a roman numeral. 3 | Input is guaranteed to be within the range from 1 to 3999. 4 | 5 | What is Roman numberals ? You can get it from wiki: 6 | https://en.wikipedia.org/wiki/Roman_numerals 7 | */ 8 | 9 | /** 10 | * Method 1 11 | * We can get from the description that: the range is from 1 to 3999. 12 | * So we can make a table for it according to the definition of Roman Numberals. 13 | * We just need to calculate the number of each digits, then append them. 14 | */ 15 | class Solution { 16 | public String intToRoman(int num) { 17 | String M[] = {"", "M", "MM", "MMM"}; 18 | String C[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; 19 | String X[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; 20 | String I[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; 21 | 22 | return M[num/1000] + C[(num%1000)/100] + X[(num%100)/10] + I[num%10]; 23 | } 24 | } 25 | 26 | /** 27 | * Method 2 28 | * There is a drawback in Method. 29 | * When we append the result string, it will cost more time and space. 30 | * So we can create a StringBuilder to solve it. 31 | */ 32 | class Solution { 33 | public String intToRoman(int num) { 34 | int[] values = {1000,900,500,400,100,90,50,40,10,9,5,4,1}; 35 | String[] strs = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}; 36 | StringBuilder sb = new StringBuilder(); 37 | 38 | for (int i = 0; i < values.length; i++) { 39 | while (num >= values[i]) { 40 | num -= values[i]; 41 | sb.append(strs[i]); 42 | } 43 | } 44 | return sb.toString(); 45 | } 46 | } -------------------------------------------------------------------------------- /Kth Smallest Element in a BST.java: -------------------------------------------------------------------------------- 1 | 该题应用到了这么一个知识点: 2 | 搜索二叉树按照中序遍历得到的序列,一定是一个递增序列。 3 | 所以可以利用这点来求得 第k小的数。 4 | 这里为了方便,我们使用了非递归方法来进行中序遍历。 5 | 解法思想同:Validate Binary Search Tree 6 | 7 | /* 8 | Given a binary search tree, write a function kthSmallest to find the kth smallest element in it. 9 | 10 | Note: 11 | You may assume k is always valid, 1 ≤ k ≤ BST's total elements. 12 | 13 | Follow up: 14 | What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? 15 | How would you optimize the kthSmallest routine? 16 | */ 17 | 18 | /** 19 | * Definition for a binary tree node. 20 | * public class TreeNode { 21 | * int val; 22 | * TreeNode left; 23 | * TreeNode right; 24 | * TreeNode(int x) { val = x; } 25 | * } 26 | */ 27 | class Solution { 28 | public int kthSmallest(TreeNode root, int k) { 29 | Stack stack = new Stack<>(); 30 | TreeNode curr = root; 31 | 32 | while (curr != null || !stack.isEmpty()) { 33 | while (curr != null) { 34 | stack.push(curr); 35 | curr = curr.left; 36 | } 37 | curr = stack.pop(); 38 | if (--k == 0) { 39 | break; 40 | } 41 | curr = curr.right; 42 | } 43 | return curr.val; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Kth Smallest Number in Multiplication Table.java: -------------------------------------------------------------------------------- 1 | The same as Kth Smallest Number in Sorted Matrix. 2 | You can get more details here: 3 | https://github.com/cherryljr/LeetCode/blob/master/Kth%20Smallest%20Element%20in%20a%20Sorted%20Matrix.java 4 | 5 | /* 6 | Nearly every one have used the Multiplication Table. 7 | But could you find out the k-th smallest number quickly from the multiplication table? 8 | 9 | Given the height m and the length n of a m * n Multiplication Table, 10 | and a positive integer k, you need to return the k-th smallest number in this table. 11 | 12 | Example 1: 13 | Input: m = 3, n = 3, k = 5 14 | 15 | Output: 16 | Explanation: 17 | The Multiplication Table: 18 | 1 2 3 19 | 2 4 6 20 | 3 6 9 21 | The 5-th smallest number is 3 (1, 2, 2, 3, 3). 22 | 23 | Example 2: 24 | Input: m = 2, n = 3, k = 6 25 | 26 | Output: 27 | Explanation: 28 | The Multiplication Table: 29 | 1 2 3 30 | 2 4 6 31 | 32 | The 6-th smallest number is 6 (1, 2, 2, 3, 4, 6). 33 | 34 | Note: 35 | The m and n will be in the range [1, 30000]. 36 | The k will be in the range [1, m * n] 37 | */ 38 | 39 | class Solution { 40 | public int findKthNumber(int m, int n, int k) { 41 | int start = 1; 42 | int end = m * n; 43 | 44 | while (start < end) { 45 | int mid = start + (end - start) / 2; 46 | int c = count(mid, m, n); 47 | if (c < k) { 48 | start = mid + 1; 49 | } else { 50 | end = mid; 51 | } 52 | } 53 | 54 | return start; 55 | } 56 | 57 | public int count(int x, int m, int n) { 58 | int count = 0; 59 | for (int i = 1; i <= m; i++) { 60 | int temp = Math.min(x / i, n); 61 | count += temp; 62 | } 63 | return count; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Largest Triangle Area.java: -------------------------------------------------------------------------------- 1 | /* 2 | You have a list of points in the plane. 3 | Return the area of the largest triangle that can be formed by any 3 of the points. 4 | 5 | Example: 6 | Input: points = [[0,0],[0,1],[1,0],[0,2],[2,0]] 7 | Output: 2 8 | Explanation: 9 | The five points are show in the figure below. The red triangle is the largest. 10 | Picture: 11 | https://s3-lc-upload.s3.amazonaws.com/uploads/2018/04/04/1027.png 12 | 13 | Notes: 14 | 3 <= points.length <= 50. 15 | No points will be duplicated. 16 | -50 <= points[i][j] <= 50. 17 | Answers within 10^-6 of the true value will be accepted as correct. 18 | */ 19 | 20 | /** 21 | * Approach: Using Cross Product 22 | * 关于三角形的面积计算,有非常多的公式.... 23 | * 而在计算机计算中通常使用的就是 Area = 1/2 * |AB| * |AC| * sinA 24 | * 而 |AB| * |AC| * sinA 就是向量 AB 与 AC 的叉积(外积) 25 | * 本题提供了各个点的坐标,因此我可以计算出各个向量,然后再计算出 1/2*向量的外积 就是三角形的面积了。 26 | * 这里用到了 行列式 的计算,不会的快去面壁... 27 | * 枚举三角形三个点所有组合的方法,计算出最大面积。 28 | * 时间复杂度为:O(n^3) 29 | * 30 | * 对于三角形面积计算这一点,知乎上有个专栏,大家有兴趣可以去看一看: 31 | * https://zhuanlan.zhihu.com/p/25599977 32 | * 33 | * 向量外积的其他应用: 34 | * https://github.com/cherryljr/LeetCode/blob/master/Convex%20Polygon.java 35 | * https://github.com/cherryljr/NowCoder/blob/master/%E7%BA%BF%E6%AE%B5%E7%9B%B8%E4%BA%A4%E7%82%B9%E4%B8%AA%E6%95%B0.java 36 | */ 37 | class Solution { 38 | public double largestTriangleArea(int[][] points) { 39 | double area = 0; 40 | for (int[] A : points) { 41 | for (int[] B : points) { 42 | for (int[] C : points) { 43 | area = Math.max(area, 0.5 * calculateArea(A, B, C)); 44 | } 45 | } 46 | } 47 | return area; 48 | } 49 | 50 | private double calculateArea(int[] A, int[] B, int[] C) { 51 | int ABx = B[0] - A[0]; 52 | int ABy = B[1] - A[1]; 53 | int ACx = C[0] - A[0]; 54 | int ACy = C[1] - A[1]; 55 | return Math.abs(ABx * ACy - ABy * ACx); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Largest Values From Labels/Largest Values From Labels.py: -------------------------------------------------------------------------------- 1 | ''' 2 | We have a set of items: the i-th item has value values[i] and label labels[i]. 3 | Then, we choose a subset S of these items, such that: 4 | |S| <= num_wanted 5 | For every label L, the number of items in S with label L is <= use_limit. 6 | Return the largest possible sum of the subset S. 7 | 8 | Example 1: 9 | Input: values = [5,4,3,2,1], labels = [1,1,2,2,3], num_wanted = 3, use_limit = 1 10 | Output: 9 11 | Explanation: The subset chosen is the first, third, and fifth item. 12 | 13 | Example 2: 14 | Input: values = [5,4,3,2,1], labels = [1,3,3,3,2], num_wanted = 3, use_limit = 2 15 | Output: 12 16 | Explanation: The subset chosen is the first, second, and third item. 17 | 18 | Example 3: 19 | Input: values = [9,8,8,7,6], labels = [0,0,0,1,1], num_wanted = 3, use_limit = 1 20 | Output: 16 21 | Explanation: The subset chosen is the first and fourth item. 22 | 23 | Example 4: 24 | Input: values = [9,8,8,7,6], labels = [0,0,0,1,1], num_wanted = 3, use_limit = 2 25 | Output: 24 26 | Explanation: The subset chosen is the first, second, and fourth item. 27 | 28 | Note: 29 | 1. 1 <= values.length == labels.length <= 20000 30 | 2. 0 <= values[i], labels[i] <= 20000 31 | 3. 1 <= num_wanted, use_limit <= values.length 32 | ''' 33 | 34 | # Approach: Map and Sorting with ZIP Function 35 | # 时间复杂度:O(nlogn) 36 | # 空间复杂度:O(n) 37 | # 解法详解参考同名 java 文件 38 | # 39 | # 关于 zip 和 zip(*) 函数的使用可以参考: 40 | # https://blog.csdn.net/weixin_41599977/article/details/89386629 41 | class Solution: 42 | def largestValsFromLabels(self, values: List[int], labels: List[int], num_wanted: int, use_limit: int) -> int: 43 | limit = collections.defaultdict(int) 44 | nodes = sorted(zip(values, labels)) 45 | ans = 0 46 | while nodes and num_wanted: 47 | value, label = nodes.pop() 48 | if limit[label] < use_limit: 49 | ans += value 50 | limit[label] += 1 51 | num_wanted -= 1 52 | return ans -------------------------------------------------------------------------------- /Last Stone Weight II/Last Stone Weight II.py: -------------------------------------------------------------------------------- 1 | ''' 2 | We have a collection of rocks, each rock has a positive integer weight. 3 | Each turn, we choose any two rocks and smash them together. 4 | Suppose the stones have weights x and y with x <= y. The result of this smash is: 5 | 6 | If x == y, both stones are totally destroyed; 7 | If x != y, the stone of weight x is totally destroyed, and the stone of weight y has new weight y-x. 8 | At the end, there is at most 1 stone left. 9 | Return the smallest possible weight of this stone (the weight is 0 if there are no stones left.) 10 | 11 | Example 1: 12 | Input: [2,7,4,1,8,1] 13 | Output: 1 14 | Explanation: 15 | We can combine 2 and 4 to get 2 so the array converts to [2,7,1,8,1] then, 16 | we can combine 7 and 8 to get 1 so the array converts to [2,1,1,1] then, 17 | we can combine 2 and 1 to get 1 so the array converts to [1,1,1] then, 18 | we can combine 1 and 1 to get 0 so the array converts to [1] then that's the optimal value. 19 | 20 | Note: 21 | 1. 1 <= stones.length <= 30 22 | 2. 1 <= stones[i] <= 100 23 | ''' 24 | 25 | # Approach: 01 Backpack 26 | # 时间复杂度:O(n) 27 | # 空间复杂度:O(n) 28 | # 解法详解参考同名 java 文件 29 | class Solution: 30 | def lastStoneWeightII(self, stones: List[int]) -> int: 31 | s = sum(stones) 32 | dp = [False] * (s // 2 + 1) 33 | dp[0] = True 34 | for i in range(len(stones)): 35 | for j in range(s >> 1, stones[i] - 1, -1): 36 | dp[j] |= dp[j - stones[i]] 37 | return min(s - i - i for i in range(s // 2 + 1) if dp[i]) -------------------------------------------------------------------------------- /Last Stone Weight/Last Stone Weight.java: -------------------------------------------------------------------------------- 1 | /* 2 | We have a collection of rocks, each rock has a positive integer weight. 3 | Each turn, we choose the two heaviest rocks and smash them together. 4 | Suppose the stones have weights x and y with x <= y. The result of this smash is: 5 | If x == y, both stones are totally destroyed; 6 | If x != y, the stone of weight x is totally destroyed, and the stone of weight y has new weight y-x. 7 | At the end, there is at most 1 stone left. Return the weight of this stone (or 0 if there are no stones left.) 8 | 9 | Example 1: 10 | Input: [2,7,4,1,8,1] 11 | Output: 1 12 | Explanation: 13 | We combine 7 and 8 to get 1 so the array converts to [2,4,1,1,1] then, 14 | we combine 2 and 4 to get 2 so the array converts to [2,1,1,1] then, 15 | we combine 2 and 1 to get 1 so the array converts to [1,1,1] then, 16 | we combine 1 and 1 to get 0 so the array converts to [1] then that's the value of last stone. 17 | 18 | Note: 19 | 1. 1 <= stones.length <= 30 20 | 2. 1 <= stones[i] <= 1000 21 | */ 22 | 23 | /** 24 | * Approach: PriorityQueue 25 | * 题目要求:每次取出最大的两个数,用较大值-较小值,然后将差值重新放入集合中进行排序。 26 | * (如果当前最大的两个数相等,则放入0,这是因为 0 必定是最小的,同时也符合题目要求的返回结果) 27 | * 每次操作之后,都需要对集合进行一次重新排序。 28 | * 毫无疑问,上述情况非常使用于 最大堆(Heap) 这个数据结构。 29 | * 在 Java 中直接使用 PriorityQueue 即可解决。 30 | * 31 | * 时间复杂度:O(nlogn) 32 | * 空间复杂度:O(n) 33 | */ 34 | class Solution { 35 | public int lastStoneWeight(int[] stones) { 36 | // 构建最大堆(从大到小的顺序) 37 | PriorityQueue pq = new PriorityQueue<>((a, b) -> b - a); 38 | for (int stone : stones) { 39 | pq.offer(stone); 40 | } 41 | // N个石头,会发生 N-1 次Collisions 42 | for (int i = 0; i < stones.length - 1; i++) { 43 | pq.offer(pq.poll() - pq.poll()); 44 | } 45 | return pq.poll(); 46 | } 47 | } -------------------------------------------------------------------------------- /Last Stone Weight/Last Stone Weight.py: -------------------------------------------------------------------------------- 1 | ''' 2 | We have a collection of rocks, each rock has a positive integer weight. 3 | Each turn, we choose the two heaviest rocks and smash them together. 4 | Suppose the stones have weights x and y with x <= y. The result of this smash is: 5 | If x == y, both stones are totally destroyed; 6 | If x != y, the stone of weight x is totally destroyed, and the stone of weight y has new weight y-x. 7 | At the end, there is at most 1 stone left. Return the weight of this stone (or 0 if there are no stones left.) 8 | 9 | Example 1: 10 | Input: [2,7,4,1,8,1] 11 | Output: 1 12 | Explanation: 13 | We combine 7 and 8 to get 1 so the array converts to [2,4,1,1,1] then, 14 | we combine 2 and 4 to get 2 so the array converts to [2,1,1,1] then, 15 | we combine 2 and 1 to get 1 so the array converts to [1,1,1] then, 16 | we combine 1 and 1 to get 0 so the array converts to [1] then that's the value of last stone. 17 | 18 | Note: 19 | 1. 1 <= stones.length <= 30 20 | 2. 1 <= stones[i] <= 1000 21 | ''' 22 | 23 | # Approach: Heapify 24 | # Python中需要使用 heapq 来进行堆的操作。 25 | # 这里为了方便起见,将数值转换成对应的负数,然后构建 最小堆。 26 | # 最后返回的结果为负数,加个负号即可 27 | # 28 | # 时间复杂度:O(nlogn) 29 | # 空间复杂度:O(n) 30 | # 解法详解参考同名 java 文件 31 | class Solution: 32 | def lastStoneWeight(self, stones: List[int]) -> int: 33 | pq = [-x for x in stones] 34 | heapq.heapify(pq) 35 | for i in range(len(stones) - 1): 36 | heapq.heappush(pq, heapq.heappop(pq) - heapq.heappop(pq)) 37 | return -pq[0] -------------------------------------------------------------------------------- /Letter Case Permutation.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a string S, we can transform every letter individually to be lowercase or uppercase to create another string. 3 | Return a list of all possible strings we could create. 4 | 5 | Examples: 6 | Input: S = "a1b2" 7 | Output: ["a1b2", "a1B2", "A1b2", "A1B2"] 8 | 9 | Input: S = "3z4" 10 | Output: ["3z4", "3Z4"] 11 | 12 | Input: S = "12345" 13 | Output: ["12345"] 14 | 15 | Note: 16 | S will be a string with length at most 12. 17 | S will consist only of letters or digits. 18 | */ 19 | 20 | /** 21 | * Approach: DFS / Backtracking 22 | * 直接使用 DFS 就能够解决。参考代码注释即可。 23 | * 24 | * 这边对本题应用到的一个技巧进行一下说明: 25 | * 因为同一个英文字符的 ASCII 码所对应的大小写之间差值为 32. 26 | * 而 2^5 = 32.因此我们可以通过 ch ^= 1 << 5. 27 | * 来实现将字母 ch 进行大小写的转换。即将其二进制 第五位 上的数与 1 进行异或, 28 | * 这样原来的 小写 可转为 大写,而 大写字母 就会被转为 小写字母。 29 | * 30 | * 时间复杂度:O(2^n) 31 | */ 32 | class Solution { 33 | public List letterCasePermutation(String S) { 34 | List rst = new ArrayList<>(); 35 | dfs(S.toCharArray(), 0, rst); 36 | return rst; 37 | } 38 | 39 | private void dfs(char[] S, int index, List rst) { 40 | if (index == S.length) { 41 | rst.add(String.valueOf(S)); 42 | return; 43 | } 44 | 45 | // 不管该位上字符是什么,都存在一种不改变当前字符直接向后移动的情况 46 | dfs(S, index + 1, rst); 47 | // 当该位上字符是 英文字符,则存在另外一种情况,即将其改变为 大写/小写 字母 48 | if (Character.isLetter(S[index])) { 49 | S[index] ^= 1 << 5; 50 | dfs(S, index + 1, rst); 51 | // Backtracking 52 | S[index] ^= 1 << 5; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /Letter Tile Possibilities/Letter Tile Possibilities.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You have a set of tiles, where each tile has one letter tiles[i] printed on it. 3 | Return the number of possible non-empty sequences of letters you can make. 4 | 5 | Example 1: 6 | Input: "AAB" 7 | Output: 8 8 | Explanation: The possible sequences are "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA". 9 | 10 | Example 2: 11 | Input: "AAABBC" 12 | Output: 188 13 | 14 | Note: 15 | 1. 1 <= tiles.length <= 7 16 | 2. tiles consists of uppercase English letters. 17 | ''' 18 | 19 | # Approach: Backtracking (By Counting Values) 20 | # 时间复杂度:O(1! + 2! + 3! + 4! + ... + n!) 21 | # 空间复杂度:O(n) 22 | # 解法详解参考同名 java 文件 23 | class Solution: 24 | def numTilePossibilities(self, tiles: str) -> int: 25 | counter = collections.Counter(tiles) 26 | 27 | def dfs(counter) -> int: 28 | ans = 0 29 | for k, v in counter.items(): 30 | if v == 0: continue 31 | counter[k] -= 1 32 | ans += 1 33 | ans += dfs(counter) 34 | counter[k] += 1 35 | return ans 36 | 37 | return dfs(counter) 38 | 39 | # Approach: Using itertools.permutations Method 40 | # 时间复杂度:O(1! + 2! + 3! + 4! + ... + n!) 41 | # 空间复杂度:O(n) 42 | # 解法详解参考同名 java 文件 43 | # 44 | # itertools.permutations的用法可以参考: 45 | # https://docs.python.org/zh-cn/3/library/itertools.html#itertools.permutations 46 | class Solution: 47 | def numTilePossibilities(self, tiles: str) -> int: 48 | ans = 0 49 | for i in range(1, len(tiles) + 1): 50 | p = itertools.permutations(tiles, i) 51 | ans += len(collections.Counter(p)) 52 | return ans -------------------------------------------------------------------------------- /Longest Arithmetic Sequence/Longest Arithmetic Sequence.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array A of integers, return the length of the longest arithmetic subsequence in A. 3 | Recall that a subsequence of A is a list A[i_1], A[i_2], ..., A[i_k] with 0 <= i_1 < i_2 < ... < i_k <= A.length - 1, 4 | and that a sequence B is arithmetic if B[i+1] - B[i] are all the same value (for 0 <= i < B.length - 1). 5 | 6 | Example 1: 7 | Input: [3,6,9,12] 8 | Output: 4 9 | Explanation: 10 | The whole array is an arithmetic sequence with steps of length = 3. 11 | 12 | Example 2: 13 | Input: [9,4,7,2,10] 14 | Output: 3 15 | Explanation: 16 | The longest arithmetic subsequence is [4,7,10]. 17 | 18 | Example 3: 19 | Input: [20,1,15,3,10,5,8] 20 | Output: 4 21 | Explanation: 22 | The longest arithmetic subsequence is [20,15,10,5]. 23 | 24 | Note: 25 | 1. 2 <= A.length <= 2000 26 | 2. 0 <= A[i] <= 10000 27 | ''' 28 | 29 | # Appraoch: DP 30 | # 解法详细解释可以参见同名 java 文件 31 | # 得益于 python 的自由性,我们可以利用 字典 来完成数据的存储。(类似 Java 中的 Map) 32 | # 但是我们可以在 dict 中存储 [i, diff] 的元组,从而直观地完成数据的存储与解析。 33 | # dp[i, diff] 对应的就是以 A[i] 作为结尾,差值为 diff 的最长等差数列的长度了 34 | # 可能大家会抱怨这样的代码执行效率不高...但是我使用Python会更加偏向于代码的优美性和利用该语言本身的优势... 35 | # 36 | # 时间复杂度:O(N^2) 37 | # 空间复杂度:O(N*M) 38 | class Solution: 39 | def longestArithSeqLength(self, A: List[int]) -> int: 40 | dp = {} 41 | for i in range(len(A) - 1): 42 | for j in range(i + 1, len(A)): 43 | dp[j, A[j] - A[i]] = dp.get((i, A[j] - A[i]), 1) + 1 44 | return max(dp.values()) -------------------------------------------------------------------------------- /Longest Arithmetic Subsequence of Given Difference.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer array arr and an integer difference, 3 | return the length of the longest subsequence in arr which is an arithmetic sequence 4 | such that the difference between adjacent elements in the subsequence equals difference. 5 | 6 | Example 1: 7 | Input: arr = [1,2,3,4], difference = 1 8 | Output: 4 9 | Explanation: The longest arithmetic subsequence is [1,2,3,4]. 10 | 11 | Example 2: 12 | Input: arr = [1,3,5,7], difference = 1 13 | Output: 1 14 | Explanation: The longest arithmetic subsequence is any single element. 15 | 16 | Example 3: 17 | Input: arr = [1,5,7,8,5,3,4,2,1], difference = -2 18 | Output: 4 19 | Explanation: The longest arithmetic subsequence is [7,5,3,1]. 20 | 21 | Constraints: 22 | 1. 1 <= arr.length <= 10^5 23 | 2. -10^4 <= arr[i], difference <= 10^4 24 | */ 25 | 26 | /** 27 | * Approach: Pre HashMap 28 | * SubSequence问题,解决方法不外乎 DP, Two Pointers, HashMap, Stack。 29 | * 这里很明显就是 PreSum + HashMap 考点的一个简化版本。(因为不要求连续了,所以不用使用 PreSum) 30 | * 31 | * 时间复杂度:O(n) 32 | * 空间复杂度:O(n) 33 | * 34 | * Reference: 35 | * https://github.com/cherryljr/LeetCode/blob/master/Remove%20Zero%20Sum%20Consecutive%20Nodes%20from%20Linked%20List.java 36 | */ 37 | class Solution { 38 | public int longestSubsequence(int[] arr, int difference) { 39 | Map map = new HashMap<>(); 40 | int ans = 1; 41 | for (int i = 0; i < arr.length; i++) { 42 | int len = map.getOrDefault(arr[i] - difference, 0) + 1; 43 | map.put(arr[i], len); 44 | ans = Math.max(ans, len); 45 | } 46 | return ans; 47 | } 48 | } -------------------------------------------------------------------------------- /Longest Chunked Palindrome Decomposition.java: -------------------------------------------------------------------------------- 1 | /* 2 | Return the largest possible k such that there exists a_1, a_2, ..., a_k such that: 3 | ·Each a_i is a non-empty string; 4 | ·Their concatenation a_1 + a_2 + ... + a_k is equal to text; 5 | ·For all 1 <= i <= k, a_i = a_{k+1 - i}. 6 | 7 | Example 1: 8 | Input: text = "ghiabcdefhelloadamhelloabcdefghi" 9 | Output: 7 10 | Explanation: We can split the string on "(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)". 11 | 12 | Example 2: 13 | Input: text = "merchant" 14 | Output: 1 15 | Explanation: We can split the string on "(merchant)". 16 | 17 | Example 3: 18 | Input: text = "antaprezatepzapreanta" 19 | Output: 11 20 | Explanation: We can split the string on "(a)(nt)(a)(pre)(za)(tpe)(za)(pre)(a)(nt)(a)". 21 | 22 | Example 4: 23 | Input: text = "aaa" 24 | Output: 3 25 | Explanation: We can split the string on "(a)(a)(a)". 26 | 27 | Constraints: 28 | 1. text consists only of lowercase English characters. 29 | 2. 1 <= text.length <= 1000 30 | */ 31 | 32 | /** 33 | * Approach: Iterative Greedy 34 | * 枚举长度 i(最大只能到 text.length/2),采用贪心的策略: 35 | * 只要 text.substring(i) 和 text.substring(n - i - 1) 相等,就说明能够组成一对回文。 36 | * 因此立刻将他们切割出来,结果+2,然后对剩下的字符串继续进行上述处理。 37 | * 直到字符串为空或者仅身下一个无法被切分的字符串。(这个过程可以使用递归进行处理) 38 | * 39 | * 时间复杂度:O(n * len(string)) 40 | * 空间复杂度:O(n) 41 | */ 42 | class Solution { 43 | public int longestDecomposition(String text) { 44 | int n = text.length(); 45 | for (int i = 0; i < n / 2; i++) { 46 | if (text.substring(0, i + 1).equals(text.substring(n - i - 1))) { 47 | return 2 + longestDecomposition(text.substring(i + 1, n - i - 1)); 48 | } 49 | } 50 | return n == 0 ? 0 : 1; 51 | } 52 | } -------------------------------------------------------------------------------- /Longest String Chain/Longest String Chain.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a list of words, each word consists of English lowercase letters. 3 | Let's say word1 is a predecessor of word2 if and only if we can add exactly one letter anywhere in word1 to make it equal to word2. 4 | For example, "abc" is a predecessor of "abac". 5 | A word chain is a sequence of words [word_1, word_2, ..., word_k] with k >= 1, 6 | where word_1 is a predecessor of word_2, word_2 is a predecessor of word_3, and so on. 7 | 8 | Return the longest possible length of a word chain with words chosen from the given list of words. 9 | 10 | Example 1: 11 | Input: ["a","b","ba","bca","bda","bdca"] 12 | Output: 4 13 | Explanation: one of the longest word chain is "a","ba","bda","bdca". 14 | 15 | Note: 16 | 1. 1 <= words.length <= 1000 17 | 2. 1 <= words[i].length <= 16 18 | 3. words[i] only consists of English lowercase letters. 19 | ''' 20 | 21 | # Approach: DP Based on Dictionary 22 | # 时间复杂度:O(N * K) (N为字符串个数,K为字符串长度) 23 | # 空间复杂度:O(N) 24 | # 解法详解参考同名 java 文件 25 | class Solution: 26 | def longestStrChain(self, words: List[str]) -> int: 27 | dp = {} 28 | for w in sorted(words, key=len): 29 | dp[w] = max(dp.get(w[:i] + w[i + 1:], 0) + 1 for i in range(len(w))) 30 | return max(dp.values()) -------------------------------------------------------------------------------- /Longest Turbulent Subarray.java: -------------------------------------------------------------------------------- 1 | /* 2 | A subarray A[i], A[i+1], ..., A[j] of A is said to be turbulent if and only if: 3 | For i <= k < j, A[k] > A[k+1] when k is odd, and A[k] < A[k+1] when k is even; 4 | OR, for i <= k < j, A[k] > A[k+1] when k is even, and A[k] < A[k+1] when k is odd. 5 | That is, the subarray is turbulent if the comparison sign flips between each adjacent pair of elements in the subarray. 6 | 7 | Return the length of a maximum size turbulent subarray of A. 8 | 9 | Example 1: 10 | Input: [9,4,2,10,7,8,8,1,9] 11 | Output: 5 12 | Explanation: (A[1] > A[2] < A[3] > A[4] < A[5]) 13 | 14 | Example 2: 15 | Input: [4,8,12,16] 16 | Output: 2 17 | 18 | Example 3: 19 | Input: [100] 20 | Output: 1 21 | 22 | Note: 23 | 1. 1 <= A.length <= 40000 24 | 2. 0 <= A[i] <= 10^9 25 | */ 26 | 27 | /** 28 | * Approach: Traverse Array 29 | * Time Complexity: O(n) 30 | * Space Complexity: O(1) 31 | */ 32 | class Solution { 33 | public int maxTurbulenceSize(int[] A) { 34 | // inc: The length of current valid sequence which ends with two increasing numbers 35 | // dec: The length of current valid sequence which ends with two decreasing numbers 36 | int inc = 1, dec = 1, res = 1; 37 | for (int i = 1; i < A.length; i++) { 38 | if (A[i] > A[i - 1]) { 39 | inc = dec + 1; 40 | dec = 1; 41 | } else if (A[i] < A[i - 1]) { 42 | dec = inc + 1; 43 | inc = 1; 44 | } else { 45 | inc = 1; 46 | dec = 1; 47 | } 48 | res = Math.max(res, Math.max(inc, dec)); 49 | } 50 | 51 | return res; 52 | } 53 | } -------------------------------------------------------------------------------- /Longest Well-Performing Interval/Longest Well-Performing Interval.py: -------------------------------------------------------------------------------- 1 | ''' 2 | We are given hours, a list of the number of hours worked per day for a given employee. 3 | A day is considered to be a tiring day if and only if the number of hours worked is (strictly) greater than 8. 4 | A well-performing interval is an interval of days for which the number of tiring days is strictly larger than the number of non-tiring days. 5 | 6 | Return the length of the longest well-performing interval. 7 | 8 | Example 1: 9 | Input: hours = [9,9,6,0,6,6,9] 10 | Output: 3 11 | Explanation: The longest well-performing interval is [9,9,6]. 12 | 13 | Constraints: 14 | 1. 1 <= hours.length <= 10000 15 | 2. 0 <= hours[i] <= 16 16 | ''' 17 | 18 | # Approach: PreSum + HashMap 19 | # 时间复杂度:O(n) 20 | # 空间复杂度:O(n) 21 | # 解法详解参考同名 java 文件 22 | class Solution: 23 | def longestWPI(self, hours: List[int]) -> int: 24 | ans = preSum = 0 25 | seen = {} 26 | for i, h in enumerate(hours): 27 | preSum = preSum + 1 if h > 8 else preSum - 1 28 | if preSum > 0: 29 | ans = i + 1 30 | seen.setdefault(preSum, i) 31 | if preSum - 1 in seen: 32 | ans = max(ans, i - seen[preSum - 1]) 33 | return ans -------------------------------------------------------------------------------- /Max Consecutive Ones II.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary array, find the maximum number of consecutive 1s in this array if you can flip at most one 0. 3 | 4 | Example 1: 5 | Input: [1,0,1,1,0] 6 | Output: 4 7 | Explanation: 8 | Flip the first zero will get the the maximum number of consecutive 1s. 9 | After flipping, the maximum number of consecutive 1s is 4. 10 | 11 | Note: 12 | 1. The input array will only contain 0 and 1. 13 | 2. The length of input array is a positive integer and will not exceed 10,000 14 | 15 | Follow up: 16 | What if the input numbers come in one by one as an infinite stream? 17 | In other words, you can't store all numbers coming from the stream as it's too large to hold in memory. 18 | Could you solve it efficiently? 19 | */ 20 | 21 | /** 22 | * Approach: Traversal 23 | * 这道题属于 Max Consecutive Ones 的 Follow Up, 24 | * 添加了一个条件:有一次将0翻转成1,求此时最大连续1的个数。 25 | * 再看看follow up中的说明,很明显是让我们只遍历一次数组, 26 | * 因此可以想到:需要用一个变量count来记录连续1的个数,那么当遇到了0的时候怎么处理呢? 27 | * 因为我们有一次0变1的机会,所以我们遇到0了还是要累加count, 28 | * 但是此时要利用另外一个变量 curr 来存储这个值,然后将 count 重置为0 (使得 count 表示真正的连续'1'的个数), 29 | * 最后使用 curr + count 来更新我们的结果:ans = max(ans, curr + count) 30 | * 31 | * 时间复杂度:O(n) 32 | * 空间复杂度:O(1) 33 | */ 34 | class Solution { 35 | public int findMaxConsecutiveOnes(int[] nums) { 36 | // curr:表示经过一次反转之后的最长连续'1'的个数 37 | // count:表示未经过反转最长的连续'1'的个数 38 | int ans = 0, curr = 0, count = 0; 39 | for (int num : nums) { 40 | count++; 41 | if (num == 0) { 42 | curr = count; 43 | count = 0; 44 | } 45 | ans = Math.max(ans, curr + count); 46 | } 47 | return ans; 48 | } 49 | } -------------------------------------------------------------------------------- /Max Consecutive Ones.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary array, find the maximum number of consecutive 1s in this array. 3 | 4 | Example 1: 5 | Input: [1,1,0,1,1,1] 6 | Output: 3 7 | Explanation: 8 | The first two digits or the last three digits are consecutive 1s. 9 | The maximum number of consecutive 1s is 3. 10 | 11 | Note: 12 | 1. The input array will only contain 0 and 1. 13 | 2. The length of input array is a positive integer and will not exceed 10,000 14 | */ 15 | 16 | /** 17 | * Approach: Traverse (Easy) 18 | * 直接遍历就好了...难度很低...不知道说啥好... 19 | * 20 | * 时间复杂度:O(n) 21 | * 空间复杂度:O(1) 22 | */ 23 | class Solution { 24 | public int findMaxConsecutiveOnes(int[] nums) { 25 | int ans = 0, count = 0; 26 | for (int num : nums) { 27 | if (num == 1) { 28 | ans = Math.max(ans, ++count); 29 | } else { 30 | count = 0; 31 | } 32 | } 33 | return ans; 34 | } 35 | } -------------------------------------------------------------------------------- /Maximum Difference Between Node and Ancestor/Maximum Difference Between Node and Ancestor.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given the root of a binary tree, find the maximum value V for which there exists different nodes A and B 3 | where V = |A.val - B.val| and A is an ancestor of B. 4 | (A node A is an ancestor of B if either: any child of A is equal to B, or any child of A is an ancestor of B.) 5 | 6 | Example 1: 7 | Input: [8,3,10,1,6,null,14,null,null,4,7,13] 8 | Output: 7 9 | Explanation: 10 | We have various ancestor-node differences, some of which are given below : 11 | |8 - 3| = 5 12 | |3 - 7| = 4 13 | |8 - 1| = 7 14 | |10 - 13| = 3 15 | Among all possible differences, the maximum value of 7 is obtained by |8 - 1| = 7. 16 | 17 | Note: 18 | 1. The number of nodes in the tree is between 2 and 5000. 19 | 2. Each node will have value between 0 and 100000. 20 | ''' 21 | 22 | # Appraoch: Divide and Conquer (Top-Down DFS) 23 | # 解法详解参考同名 java 文件 Approach 2 24 | # 介于 python 的特性,我们能重写函数名,避免创建新的 dfs函数 25 | # 并且可以把这些内容比较 geek 地写到一行中。但是算法上和 java 的做法是相同的 26 | # 27 | # 时间复杂度:O(n) 28 | # 空间复杂度:O(logn) 29 | 30 | # Definition for a binary tree node. 31 | # class TreeNode: 32 | # def __init__(self, x): 33 | # self.val = x 34 | # self.left = None 35 | # self.right = None 36 | class Solution: 37 | def maxAncestorDiff(self, root: TreeNode, mini = 0x3f3f3f3f, maxi = 0) -> int: 38 | return max(self.maxAncestorDiff(root.left, min(mini, root.val), max(maxi, root.val)), self.maxAncestorDiff(root.right, min(mini, root.val), max(maxi, root.val))) if root else maxi - mini -------------------------------------------------------------------------------- /Maximum Sum of Two Non-Overlapping Subarrays/Maximum Sum of Two Non-Overlapping Subarrays.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array A of non-negative integers, return the maximum sum of elements in two non-overlapping (contiguous) subarrays, 3 | which have lengths L and M. (For clarification, the L-length subarray could occur before or after the M-length subarray.) 4 | Formally, return the largest V for which V = (A[i] + A[i+1] + ... + A[i+L-1]) + (A[j] + A[j+1] + ... + A[j+M-1]) and either: 5 | 0 <= i < i + L - 1 < j < j + M - 1 < A.length, or 6 | 0 <= j < j + M - 1 < i < i + L - 1 < A.length. 7 | 8 | Example 1: 9 | Input: A = [0,6,5,2,2,5,1,9,4], L = 1, M = 2 10 | Output: 20 11 | Explanation: One choice of subarrays is [9] with length 1, and [6,5] with length 2. 12 | 13 | Example 2: 14 | Input: A = [3,8,1,3,2,1,8,9,0], L = 3, M = 2 15 | Output: 29 16 | Explanation: One choice of subarrays is [3,8,1] with length 3, and [8,9] with length 2. 17 | 18 | Example 3: 19 | Input: A = [2,1,5,6,0,9,5,0,3,8], L = 4, M = 3 20 | Output: 31 21 | Explanation: One choice of subarrays is [5,6,0,9] with length 4, and [3,8] with length 3. 22 | 23 | Note: 24 | 1. L >= 1 25 | 2. M >= 1 26 | 3. L + M <= A.length <= 1000 27 | 4. 0 <= A[i] <= 1000 28 | ''' 29 | 30 | # Approach: PreSum (Sliding Window) 31 | # 解法详解参考同名 java 文件 32 | # 时间复杂度:O(n) 33 | # 空间复杂度:O(1) 34 | class Solution: 35 | def maxSumTwoNoOverlap(self, A: List[int], L: int, M: int) -> int: 36 | preSum = [0] * (len(A) + 1) 37 | for i in range(1, len(preSum)): 38 | preSum[i] = preSum[i - 1] + A[i - 1] 39 | 40 | Lmax, Mmax, ans = preSum[L], preSum[M], preSum[L + M] 41 | for i in range(L + M + 1, len(preSum)): 42 | Lmax = max(Lmax, preSum[i - M] - preSum[i - M - L]) 43 | Mmax = max(Mmax, preSum[i - L] - preSum[i - L - M]) 44 | ans = max(ans, Lmax + preSum[i] - preSum[i - M], Mmax + preSum[i] - preSum[i - L]) 45 | return ans -------------------------------------------------------------------------------- /Minimum Increment to Make Array Unique.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers A, a move consists of choosing any A[i], and incrementing it by 1. 3 | Return the least number of moves to make every value in A unique. 4 | 5 | Example 1: 6 | Input: [1,2,2] 7 | Output: 1 8 | Explanation: After 1 move, the array could be [1, 2, 3]. 9 | 10 | Example 2: 11 | Input: [3,2,1,2,1,7] 12 | Output: 6 13 | Explanation: After 6 moves, the array could be [3, 4, 1, 2, 5, 7]. 14 | It can be shown with 5 or less moves that it is impossible for the array to have all unique values. 15 | 16 | Note: 17 | 1. 0 <= A.length <= 40000 18 | 2. 0 <= A[i] < 40000 19 | */ 20 | 21 | /** 22 | * Approach: Sort The Array 23 | * Compared with previous number, the current number need to be at least prev + 1. 24 | * 25 | * Time Complexity: O(NlogN) 26 | * Space Complexity: O(1) 27 | */ 28 | class Solution { 29 | public int minIncrementForUnique(int[] A) { 30 | if (A == null || A.length == 0) { 31 | return 0; 32 | } 33 | 34 | Arrays.sort(A); 35 | int rst = 0, prev = A[0]; 36 | for (int i = 1; i < A.length; i++) { 37 | int expect = prev + 1; 38 | rst += A[i] > expect ? 0 : expect - A[i]; 39 | prev = Math.max(expect, A[i]); 40 | } 41 | return rst; 42 | } 43 | } -------------------------------------------------------------------------------- /Minimum Moves to Equal Array Elements.java: -------------------------------------------------------------------------------- 1 | 将 n-1 个数 加1,相当于将所有数都 加1,再将其中一个数 减去1。 2 | 将所有数都加1这个操作,其实不会改变任何数的相对大小,也就是所有数两两之间的差都是不会变的, 3 | 这对于要使所有元素均相等的目标来说没有影响,所以可以忽略这一部分。 4 | 5 | 那么问题就变成每次选个数减1来达到目标的最小次数。 6 | 要使次数最小,而且每次只能将元素减1,故应当把所有数减到与最小值相等。 7 | 8 | 若n个元素为a(0),a(1),……,a(n-1),其中最小值为min,则答案为 a(0)+a(1)+……+a(n-1) - min*n。 9 | 只需求出n个数中的最小值以及它们的和来计算即可,时间复杂度为O(n)。 10 | 11 | /* 12 | Given a non-empty integer array of size n, find the minimum number of moves required to make all array elements equal, 13 | where a move is incrementing n - 1 elements by 1. 14 | 15 | Example: 16 | Input: 17 | [1,2,3] 18 | Output: 19 | 3 20 | 21 | Explanation: 22 | Only three moves are needed (remember each move increments two elements): 23 | [1,2,3] => [2,3,3] => [3,4,3] => [4,4,4] 24 | */ 25 | 26 | class Solution { 27 | public int minMoves(int[] nums) { 28 | if (nums == null || nums.length == 0) { 29 | return 0; 30 | } 31 | 32 | int sum = 0; 33 | int min = Integer.MAX_VALUE; 34 | for (int i : nums) { 35 | sum += i; 36 | min = Math.min(min, i); 37 | } 38 | 39 | return sum - min * nums.length; 40 | } 41 | } -------------------------------------------------------------------------------- /Minimum Number of K Consecutive Bit Flips/Minimum Number of K Consecutive Bit Flips.py: -------------------------------------------------------------------------------- 1 | ''' 2 | In an array A containing only 0s and 1s, a K-bit flip consists of choosing a (contiguous) subarray of length K 3 | and simultaneously changing every 0 in the subarray to 1, and every 1 in the subarray to 0. 4 | 5 | Return the minimum number of K-bit flips required so that there is no 0 in the array. 6 | If it is not possible, return -1. 7 | 8 | Example 1: 9 | Input: A = [0,1,0], K = 1 10 | Output: 2 11 | Explanation: Flip A[0], then flip A[2]. 12 | 13 | Example 2: 14 | Input: A = [1,1,0], K = 2 15 | Output: -1 16 | Explanation: No matter how we flip subarrays of size 2, we can't make the array become [1,1,1]. 17 | 18 | Example 3: 19 | Input: A = [0,0,0,1,0,1,1,0], K = 3 20 | Output: 3 21 | Explanation: 22 | Flip A[0],A[1],A[2]: A becomes [1,1,1,1,0,1,1,0] 23 | Flip A[4],A[5],A[6]: A becomes [1,1,1,1,1,0,0,0] 24 | Flip A[5],A[6],A[7]: A becomes [1,1,1,1,1,1,1,1] 25 | 26 | Note: 27 | 1. 1 <= A.length <= 30000 28 | 2. 1 <= K <= A.length 29 | ''' 30 | 31 | # Approach: Greedy with Status Record (No Extra Space) 32 | # 时间复杂度:O(N) 33 | # 空间复杂度:O(1) 34 | # 解法详解参考同名 java 文件的 Approach 3 35 | class Solution: 36 | def minKBitFlips(self, A: List[int], K: int) -> int: 37 | ans, flipStatus = 0, 0 38 | for i in range(len(A)): 39 | if i >= K and A[i - K] == 2: 40 | flipStatus ^= 1 41 | if flipStatus == A[i]: 42 | if i + K > len(A): return -1 43 | A[i] = 2 44 | flipStatus, ans = flipStatus ^ 1, ans + 1 45 | return ans -------------------------------------------------------------------------------- /Minimum Score Triangulation of Polygon/Minimum Score Triangulation of Polygon.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given N, consider a convex N-sided polygon with vertices labelled A[0], A[i], ..., A[N-1] in clockwise order. 3 | Suppose you triangulate the polygon into N-2 triangles. 4 | For each triangle, the value of that triangle is the product of the labels of the vertices, 5 | and the total score of the triangulation is the sum of these values over all N-2 triangles in the triangulation. 6 | 7 | Return the smallest possible total score that you can achieve with some triangulation of the polygon. 8 | 9 | Example 1: 10 | Input: [1,2,3] 11 | Output: 6 12 | Explanation: The polygon is already triangulated, and the score of the only triangle is 6. 13 | 14 | Example 2: 15 | Input: [3,7,4,5] 16 | Output: 144 17 | Explanation: There are two triangulations, with possible scores: 3*7*5 + 4*5*7 = 245, or 3*4*5 + 3*4*7 = 144. The minimum score is 144. 18 | 19 | Example 3: 20 | Input: [1,3,1,4,1,5] 21 | Output: 13 22 | Explanation: The minimum score triangulation has score 1*1*3 + 1*1*4 + 1*1*5 + 1*1*1 = 13. 23 | 24 | Note: 25 | 1. 3 <= A.length <= 50 26 | 2. 1 <= A[i] <= 100 27 | ''' 28 | 29 | # Approach: Interval DP 30 | # 时间复杂度:O(n^3) 31 | # 空间复杂度:O(n^2) 32 | # 解法详解参考同名 java 文件 33 | class Solution: 34 | def minScoreTriangulation(self, A: List[int]) -> int: 35 | n = len(A) 36 | dp = [[0] * n for _ in range(n)] 37 | for l in range(3, n + 1): 38 | for start in range(n - l + 1): 39 | end = start + l - 1 40 | dp[start][end] = min(dp[start][pivot] + dp[pivot][end] + A[start] * A[pivot] * A[end] for pivot in range(start + 1, end)) 41 | return dp[0][n - 1] -------------------------------------------------------------------------------- /Moving Stones Until Consecutive/Moving Stones Until Consecutive.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Three stones are on a number line at positions a, b, and c. 3 | Each turn, you pick up a stone at an endpoint (ie., either the lowest or highest position stone), 4 | and move it to an unoccupied position between those endpoints. 5 | Formally, let's say the stones are currently at positions x, y, z with x < y < z. 6 | You pick up the stone at either position x or position z, and move that stone to an integer position k, with x < k < z and k != y. 7 | 8 | The game ends when you cannot make any more moves, ie. the stones are in consecutive positions. 9 | When the game ends, what is the minimum and maximum number of moves that you could have made? 10 | Return the answer as an length 2 array: answer = [minimum_moves, maximum_moves] 11 | 12 | Example 1: 13 | Input: a = 1, b = 2, c = 5 14 | Output: [1,2] 15 | Explanation: Move the stone from 5 to 3, or move the stone from 5 to 4 to 3. 16 | 17 | Example 2: 18 | Input: a = 4, b = 3, c = 2 19 | Output: [0,0] 20 | Explanation: We cannot make any moves. 21 | 22 | Example 3: 23 | Input: a = 3, b = 5, c = 1 24 | Output: [1,2] 25 | Explanation: Move the stone from 1 to 4; or move the stone from 1 to 2 to 4. 26 | 27 | Note: 28 | 1. 1 <= a <= 100 29 | 2. 1 <= b <= 100 30 | 3. 1 <= c <= 100 31 | 4. a != b, b != c, c != a 32 | ''' 33 | 34 | # Approach: Sorting (May Use Sliding Window in N Stones) 35 | # 解法详解参考同名 java 文件 36 | # 时间复杂度:O(1) 37 | # 空间复杂度:O(1) 38 | class Solution: 39 | def numMovesStones(self, a: int, b: int, c: int) -> List[int]: 40 | mini, mid, maxi = sorted([a, b, c]) 41 | if maxi - mini == 2: 42 | return [0, 0] 43 | elif min(mid - mini, maxi - mid) <= 2: 44 | return [1, maxi - mini - 2] 45 | else: 46 | return [2, maxi - mini - 2] -------------------------------------------------------------------------------- /Multiply Strings.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2. 3 | 4 | Note: 5 | The length of both num1 and num2 is < 110. 6 | Both num1 and num2 contains only digits 0-9. 7 | Both num1 and num2 does not contain any leading zero. 8 | You must not use any built-in BigInteger library or convert the inputs to integer directly. 9 | */ 10 | 11 | /** 12 | * Remember how we do multiplication? 13 | * Start from right to left, perform multiplication on every pair of digits, and add them together. 14 | * Let’s draw the process! From the following draft, we can immediately conclude: 15 | * num1[i] * num2[j] will be placed at indices [i + j, i + j + 1] 16 | * It meas that: 17 | * rst[i+j] = sum / 10; 18 | * rst[i+j+1] = sum % 10; 19 | * 20 | * The image is here: 21 | * https://drscdn.500px.org/photo/130178585/m=2048/300d71f784f679d5e70fadda8ad7d68f 22 | */ 23 | class Solution { 24 | public String multiply(String num1, String num2) { 25 | int[] pos = new int[num1.length() + num2.length()]; 26 | 27 | // Calculate the result of each index in the pos array. 28 | for (int i = num1.length() - 1; i >= 0; i--) { 29 | for (int j = num2.length() - 1; j >= 0; j--) { 30 | int p1 = i + j, p2 = i + j + 1; 31 | int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0'); 32 | // The current sum equals mul plus the ten's digit from the last mul 33 | // (pos[p2], or you can find from the draft directly, they are in the same column) 34 | int sum = mul + pos[p2]; 35 | 36 | pos[p1] += sum / 10; 37 | pos[p2] = sum % 10; 38 | } 39 | } 40 | 41 | // Turn the pos array into String result 42 | StringBuilder sb = new StringBuilder(); 43 | for (int p : pos) { 44 | if (!(sb.length() == 0 && p == 0)) { 45 | sb.append(p); 46 | } 47 | } 48 | return sb.length() == 0 ? "0" : sb.toString(); 49 | } 50 | } -------------------------------------------------------------------------------- /Next Greater Element I/Next Greater Element I.py: -------------------------------------------------------------------------------- 1 | ''' 2 | You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subset of nums2. 3 | Find all the next greater numbers for nums1's elements in the corresponding places of nums2. 4 | 5 | The Next Greater Number of a number x in nums1 is the first greater number to its right in nums2. 6 | If it does not exist, output -1 for this number. 7 | 8 | Example 1: 9 | Input: nums1 = [4,1,2], nums2 = [1,3,4,2]. 10 | Output: [-1,3,-1] 11 | Explanation: 12 | For number 4 in the first array, you cannot find the next greater number for it in the second array, so output -1. 13 | For number 1 in the first array, the next greater number for it in the second array is 3. 14 | For number 2 in the first array, there is no next greater number for it in the second array, so output -1. 15 | 16 | Example 2: 17 | Input: nums1 = [2,4], nums2 = [1,2,3,4]. 18 | Output: [3,-1] 19 | Explanation: 20 | For number 2 in the first array, the next greater number for it in the second array is 3. 21 | For number 4 in the first array, there is no next greater number for it in the second array, so output -1. 22 | 23 | Note: 24 | 1. All elements in nums1 and nums2 are unique. 25 | 2. The length of both nums1 and nums2 would not exceed 1000. 26 | ''' 27 | 28 | # 解法详解参考同名 java 文件 29 | # Approach 1: Traverse 30 | # 因为题目数据量只有 1000 所以写得比较 geek,数据量上去的话这个做法是过不去的 31 | class Solution: 32 | def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]: 33 | return [next((y for y in nums2[nums2.index(x):] if y > x), -1) for x in nums1] 34 | 35 | 36 | # Approach 2: Monotonic Stack 37 | class Solution: 38 | def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]: 39 | allRes = {} 40 | stack = [] 41 | for num in nums2: 42 | while stack and num > stack[-1]: 43 | allRes[stack.pop()] = num 44 | stack.append(num) 45 | 46 | return [allRes.get(num, -1) for num in nums1] -------------------------------------------------------------------------------- /Next Greater Element II/Next Greater Element II.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a circular array (the next element of the last element is the first element of the array), print the Next Greater Number for every element. 3 | The Next Greater Number of a number x is the first greater number to its traversing-order next in the array, 4 | which means you could search circularly to find its next greater number. If it doesn't exist, output -1 for this number. 5 | 6 | Example 1: 7 | Input: [1,2,1] 8 | Output: [2,-1,2] 9 | Explanation: 10 | The first 1's next greater number is 2; 11 | The number 2 can't find next greater number; 12 | The second 1's next greater number needs to search circularly, which is also 2. 13 | 14 | Note: 15 | 1. The length of given array won't exceed 10000. 16 | */ 17 | 18 | /** 19 | * Approach: Monotonic Stack (Break the Circle) 20 | * 这道题目算是 Next Greater Element I 的一个 Follow Up. 21 | * 把原来的一维数组首尾相连组成了一个环形。 22 | * 但是对于 环形数组 的处理方法,其实特别简单,我们只需要将其进行 断开(展开),即 将其连续遍历两遍。 23 | * (在原本数组的后面添上一个原本数组的拷贝,这样对新数组进行遍历的时候可以保证所有环内的区间都被遍历过一遍) 24 | * 其他方面与 Next Greater Element I 一模一样,没啥好说的,单调栈问题。 25 | * 26 | * 时间复杂度:O(2n) => O(n) 27 | * 空间复杂度:O(n) 28 | * 29 | * References: 30 | * https://github.com/cherryljr/LeetCode/tree/master/Next%20Greater%20Element%20I 31 | */ 32 | class Solution { 33 | public int[] nextGreaterElements(int[] nums) { 34 | int n = nums.length; 35 | int[] ans = new int[n]; 36 | Arrays.fill(ans, -1); 37 | Deque stack = new ArrayDeque<>(); 38 | 39 | for (int i = 0; i < 2 * n; i++) { 40 | while (!stack.isEmpty() && nums[i % n] > nums[stack.peek()]) { 41 | ans[stack.pop()] = nums[i % n]; 42 | } 43 | stack.push(i % n); 44 | } 45 | return ans; 46 | } 47 | } -------------------------------------------------------------------------------- /Next Greater Element II/Next Greater Element II.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a circular array (the next element of the last element is the first element of the array), print the Next Greater Number for every element. 3 | The Next Greater Number of a number x is the first greater number to its traversing-order next in the array, 4 | which means you could search circularly to find its next greater number. If it doesn't exist, output -1 for this number. 5 | 6 | Example 1: 7 | Input: [1,2,1] 8 | Output: [2,-1,2] 9 | Explanation: 10 | The first 1's next greater number is 2; 11 | The number 2 can't find next greater number; 12 | The second 1's next greater number needs to search circularly, which is also 2. 13 | 14 | Note: 15 | 1. The length of given array won't exceed 10000. 16 | ''' 17 | 18 | # Approach: Monotonic Stack 19 | # 解法详解参考同名 java 文件 20 | class Solution: 21 | def nextGreaterElements(self, nums: List[int]) -> List[int]: 22 | n = len(nums) 23 | ans, stack = [-1] * n, [] 24 | for i in range(2 * n): 25 | while stack and nums[i % n] > nums[stack[-1]]: 26 | ans[stack.pop()] = nums[i % n] 27 | stack.append(i % n) 28 | return ans -------------------------------------------------------------------------------- /Next Greater Element III/Next Greater Element III.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a positive 32-bit integer n, you need to find the smallest 32-bit integer 3 | which has exactly the same digits existing in the integer n and is greater in value than n. 4 | If no such positive 32-bit integer exists, you need to return -1. 5 | 6 | Example 1: 7 | Input: 12 8 | Output: 21 9 | 10 | Example 2: 11 | Input: 21 12 | Output: -1 13 | ''' 14 | 15 | # Approach: Swap and Reverse 16 | # 解法详解参考同名 java 文件 17 | class Solution: 18 | def nextGreaterElement(self, n: int) -> int: 19 | nums = [c for c in str(n)] 20 | index = len(nums) - 2 21 | while index >= 0 and nums[index] >= nums[index + 1]: 22 | index -= 1 23 | 24 | if index < 0: 25 | return -1 26 | larger = len(nums) - 1 27 | while larger > 0 and nums[larger] <= nums[index]: 28 | larger -= 1 29 | # Swap 30 | nums[index], nums[larger] = nums[larger], nums[index] 31 | index += 1 32 | # Reverse 33 | nums[index:] = reversed(nums[index:]) 34 | 35 | ans = int(''.join(nums)) 36 | return ans if ans <= ((1 << 31) - 1) else -1 -------------------------------------------------------------------------------- /Next Greater Node In Linked List/Next Greater Node In Linked List.py: -------------------------------------------------------------------------------- 1 | ''' 2 | We are given a linked list with head as the first node. 3 | Let's number the nodes in the list: node_1, node_2, node_3, ... etc. 4 | 5 | Each node may have a next larger value: 6 | for node_i, next_larger(node_i) is the node_j.val such that j > i, node_j.val > node_i.val, and j is the smallest possible choice. 7 | If such a j does not exist, the next larger value is 0. 8 | 9 | Return an array of integers answer, where answer[i] = next_larger(node_{i+1}). 10 | 11 | Note that in the example inputs (not outputs) below, arrays such as [2,1,5] represent 12 | the serialization of a linked list with a head node value of 2, second node value of 1, and third node value of 5. 13 | 14 | Example 1: 15 | Input: [2,1,5] 16 | Output: [5,5,0] 17 | 18 | Example 2: 19 | Input: [2,7,4,3,5] 20 | Output: [7,0,5,5,0] 21 | 22 | Example 3: 23 | Input: [1,7,5,1,9,2,5,1] 24 | Output: [7,9,9,9,0,5,0,0] 25 | 26 | Note: 27 | 1. 1 <= node.val <= 10^9 for each node in the linked list. 28 | 2. The given list has length in the range [0, 10000]. 29 | ''' 30 | 31 | # 解法详解参考同名 java 文件 32 | 33 | # Definition for singly-linked list. 34 | # class ListNode: 35 | # def __init__(self, x): 36 | # self.val = x 37 | # self.next = None 38 | class Solution: 39 | def nextLargerNodes(self, head: ListNode) -> List[int]: 40 | nums = [] 41 | while head: 42 | nums.append(head.val) 43 | head = head.next 44 | 45 | ans, stack = [0] * len(nums), [] 46 | for i, x in enumerate(nums): 47 | while stack and x > nums[stack[-1]]: 48 | ans[stack.pop()] = x 49 | stack.append(i) 50 | return ans -------------------------------------------------------------------------------- /Number of Enclaves/Number of Enclaves.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a 2D array A, each cell is 0 (representing sea) or 1 (representing land) 3 | A move consists of walking from one land square 4-directionally to another land square, or off the boundary of the grid. 4 | 5 | Return the number of land squares in the grid for which we cannot walk off the boundary of the grid in any number of moves. 6 | 7 | Example 1: 8 | Input: [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]] 9 | Output: 3 10 | Explanation: 11 | There are three 1s that are enclosed by 0s, and one 1 that isn't enclosed because its on the boundary. 12 | 13 | Example 2: 14 | Input: [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]] 15 | Output: 0 16 | Explanation: 17 | All 1s are either on the boundary or can reach the boundary. 18 | 19 | Note: 20 | 1. 1 <= A.length <= 500 21 | 2. 1 <= A[i].length <= 500 22 | 3. 0 <= A[i][j] <= 1 23 | 4. All rows have the same size. 24 | ''' 25 | 26 | # 27 | class Solution: 28 | def numEnclaves(self, A: List[List[int]]) -> int: 29 | rows, cols = len(A), len(A[0]) 30 | 31 | def dfs(x, y): 32 | if x < 0 or x >= rows or y < 0 or y >= cols or A[x][y] != 1: 33 | return 34 | 35 | A[x][y] = 0 36 | dfs(x, y + 1), dfs(x, y - 1), dfs(x - 1, y), dfs(x + 1, y) 37 | 38 | for i in range(rows): 39 | dfs(i, 0), dfs(i, cols - 1) 40 | for j in range(1, cols - 1): 41 | dfs(0, j), dfs(rows - 1, j) 42 | 43 | return sum([sum(A[i]) for i in range(rows)]) -------------------------------------------------------------------------------- /Number of Equivalent Domino Pairs.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a list of dominoes, dominoes[i] = [a, b] is equivalent to dominoes[j] = [c, d] 3 | if and only if either (a==c and b==d), or (a==d and b==c) - that is, one domino can be rotated to be equal to another domino. 4 | 5 | Return the number of pairs (i, j) for which 0 <= i < j < dominoes.length, and dominoes[i] is equivalent to dominoes[j]. 6 | 7 | Example 1: 8 | Input: dominoes = [[1,2],[2,1],[3,4],[5,6]] 9 | Output: 1 10 | 11 | Constraints: 12 | 1. 1 <= dominoes.length <= 40000 13 | 2. 1 <= dominoes[i][j] <= 9 14 | */ 15 | 16 | /** 17 | * Approach 1: Decode value and Count Occurrence 18 | * 题目要求:一样的多米诺骨牌有多少对,每个骨牌是可以进行翻转的,因此只要 a,b 与 c,d 相等即可。 19 | * 20 | * 因为题目明确给出 1 <= dominoes[i][j] <= 9,因此我们可以利用 乘10 的方法进行编码来存储。(方式为:较小值*10+较大值) 21 | * 并且其编码后的最大值不会超过 99,因此没必要使用 HashMap 来存储编码后元素的出现次数,直接用数组即可。 22 | * 最后统计一样的多米诺骨牌的对数即可。 23 | * 统计方式有两种: 24 | * 1. 记各个相同骨牌的个数为 x, 则结果为:ans = sum(x*(x-1)/2) 25 | * 2. 直接在统计过程中进行累加,比如骨牌 [1,2] 的出现次数为 3,当改该骨牌再次出现时,说明已当前骨牌能够组成 3 对相同的,同时 count[12]++ 26 | * 27 | * 时间复杂度:O(n) 28 | * 空间复杂度:O(n) 29 | */ 30 | class Solution { 31 | public int numEquivDominoPairs(int[][] dominoes) { 32 | int[] count = new int[100]; 33 | int ans = 0; 34 | for (int[] dominoe : dominoes) { 35 | int num = dominoe[0] > dominoe[1] ? 10 * dominoe[1] + dominoe[0] : dominoe[0] * 10 + dominoe[1]; 36 | count[num]++; 37 | } 38 | for (int x : count) { 39 | ans += x * (x - 1) / 2; 40 | } 41 | return ans; 42 | } 43 | } 44 | 45 | /** 46 | * Approach 2: Decode value and Count Occurrence 47 | */ 48 | class Solution { 49 | public int numEquivDominoPairs(int[][] dominoes) { 50 | int[] count = new int[100]; 51 | int ans = 0; 52 | for (int[] dominoe : dominoes) { 53 | int num = dominoe[0] > dominoe[1] ? 10 * dominoe[1] + dominoe[0] : dominoe[0] * 10 + dominoe[1]; 54 | ans += count[num]++; 55 | } 56 | return ans; 57 | } 58 | } -------------------------------------------------------------------------------- /Number of Submatrices That Sum to Target/Number of Submatrices That Sum to Target.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a matrix, and a target, return the number of non-empty submatrices that sum to target. 3 | A submatrix x1, y1, x2, y2 is the set of all cells matrix[x][y] with x1 <= x <= x2 and y1 <= y <= y2. 4 | Two submatrices (x1, y1, x2, y2) and (x1', y1', x2', y2') are different 5 | if they have some coordinate that is different: for example, if x1 != x1'. 6 | 7 | Example 1: 8 | Input: matrix = [[0,1,0],[1,1,1],[0,1,0]], target = 0 9 | Output: 4 10 | Explanation: The four 1x1 submatrices that only contain 0. 11 | 12 | Example 2: 13 | Input: matrix = [[1,-1],[-1,1]], target = 0 14 | Output: 5 15 | Explanation: The two 1x2 submatrices, plus the two 2x1 submatrices, plus the 2x2 submatrix. 16 | 17 | Note: 18 | 1. 1 <= matrix.length <= 300 19 | 2. 1 <= matrix[0].length <= 300 20 | 3. -1000 <= matrix[i] <= 1000 21 | 4. -10^8 <= target <= 10^8 22 | ''' 23 | 24 | # Approach: Turn to Subarray Sum Equals Target 25 | # 时间复杂度:O(n^3) 26 | # 空间复杂度:O(n^2) 27 | # 解法详解参考同名 java 文件 28 | class Solution: 29 | def numSubmatrixSumTarget(self, matrix: List[List[int]], target: int) -> int: 30 | rows, cols = len(matrix) + 1, len(matrix[0]) + 1 31 | preSum = [[0] * cols for _ in range(rows)] 32 | for i in range(1, rows): 33 | for j in range(1, cols): 34 | preSum[i][j] = preSum[i - 1][j] + preSum[i][j - 1] - preSum[i - 1][j - 1] + matrix[i - 1][j - 1] 35 | 36 | count = 0 37 | for top in range(rows): 38 | for down in range(top + 1, rows): 39 | c = collections.Counter({0 : 1}) 40 | for k in range(1, cols): 41 | s = preSum[down][k] - preSum[top][k] 42 | count += c[s - target] 43 | c[s] += 1 44 | return count -------------------------------------------------------------------------------- /Occurrences After Bigram/Occurrences After Bigram.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given words first and second, consider occurrences in some text of the form "first second third", 3 | where second comes immediately after first, and third comes immediately after second. 4 | 5 | For each such occurrence, add "third" to the answer, and return the answer. 6 | 7 | Example 1: 8 | Input: text = "alice is a good girl she is a good student", first = "a", second = "good" 9 | Output: ["girl","student"] 10 | 11 | Example 2: 12 | Input: text = "we will we will rock you", first = "we", second = "will" 13 | Output: ["we","rock"] 14 | 15 | Note: 16 | 1. 1 <= text.length <= 1000 17 | 2. text consists of space separated words, where each word consists of lowercase English letters. 18 | 3. 1 <= first.length, second.length <= 10 19 | 4. first and second consist of lowercase English letters. 20 | */ 21 | 22 | /** 23 | * Approach: Split Text and Compare 24 | * 把给的 text 按照空格进行分割得到一个字符串数组。 25 | * 然后按照顺序遍历一遍,对比该单词的前两个单词是否分别于 first 和 second 相等即可。 26 | * 27 | * 时间复杂度:O(n) 28 | * 空间复杂度:O(n) 29 | * 30 | * Reference: 31 | * 对于 Collection.toArray(T[] a) 方法的解释与应用可以参考: 32 | * https://blog.csdn.net/zhangyunfei_happy/article/details/51153754 33 | */ 34 | class Solution { 35 | public String[] findOcurrences(String text, String first, String second) { 36 | List ans = new ArrayList<>(); 37 | String[] strs = text.split(" "); 38 | for (int i = 2; i < strs.length; i++) { 39 | if (strs[i - 2].equals(first) && strs[i - 1].equals(second)) { 40 | ans.add(strs[i]); 41 | } 42 | } 43 | // return ans.toArray(new String[0]); 这个写法也可以 44 | return ans.toArray(new String[ans.size()]); 45 | } 46 | } -------------------------------------------------------------------------------- /Occurrences After Bigram/Occurrences After Bigram.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a binary string S (a string consisting only of '0' and '1's) and a positive integer N, 3 | return true if and only if for every integer X from 1 to N, the binary representation of X is a substring of S. 4 | 5 | Example 1: 6 | Input: S = "0110", N = 3 7 | Output: true 8 | 9 | Example 2: 10 | Input: S = "0110", N = 4 11 | Output: false 12 | 13 | Note: 14 | 1. 1 <= S.length <= 1000 15 | 2. 1 <= N <= 10^9 16 | ''' 17 | 18 | # Approach: Split Text and Compare 19 | # 时间复杂度:O(n) 20 | # 空间复杂度:O(1) 21 | # 解法详解参考同名 java 文件 22 | class Solution: 23 | def findOcurrences(self, text: str, first: str, second: str) -> List[str]: 24 | ans = [] 25 | strs = text.split(" ") 26 | for i in range(2, len(strs)): 27 | if strs[i - 2] == first and strs[i - 1] == second: 28 | ans.append(strs[i]) 29 | return ans -------------------------------------------------------------------------------- /Parsing A Boolean Expression/Parsing A Boolean Expression.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Return the result of evaluating a given boolean expression, represented as a string. 3 | An expression can either be: 4 | "t", evaluating to True; 5 | "f", evaluating to False; 6 | "!(expr)", evaluating to the logical NOT of the inner expression expr; 7 | "&(expr1,expr2,...)", evaluating to the logical AND of 2 or more inner expressions expr1, expr2, ...; 8 | "|(expr1,expr2,...)", evaluating to the logical OR of 2 or more inner expressions expr1, expr2, ... 9 | 10 | Example 1: 11 | Input: expression = "!(f)" 12 | Output: true 13 | 14 | Example 2: 15 | Input: expression = "|(f,t)" 16 | Output: true 17 | 18 | Example 3: 19 | Input: expression = "&(t,f)" 20 | Output: false 21 | 22 | Example 4: 23 | Input: expression = "|(&(t,f,t),!(t))" 24 | Output: false 25 | 26 | Constraints: 27 | 1. 1 <= expression.length <= 20000 28 | 2. expression[i] consists of characters in {'(', ')', '&', '|', '!', 't', 'f', ','}. 29 | 3. expression is a valid expression representing a boolean, as given in the description. 30 | ''' 31 | 32 | # Approach: Using Stack + HashSet 33 | # 时间复杂度:O(n) 34 | # 空间复杂度:O(n) 35 | # 解法详解参考同名 java 文件 Approach 2 36 | class Solution: 37 | def parseBoolExpr(self, expression: str) -> bool: 38 | stack = [] 39 | for c in expression: 40 | if c == ')': 41 | seen = set() 42 | while stack[-1] != '(': 43 | seen.add(stack.pop()) 44 | stack.pop() 45 | operator = stack.pop() 46 | stack.append(all(seen) if operator == '&' else any(seen) if operator == '|' else not seen.pop()) 47 | elif c != ',': 48 | stack.append(True if c == 't' else False if c == 'f' else c) 49 | return stack.pop() -------------------------------------------------------------------------------- /Partition Array for Maximum Sum/Partition Array for Maximum Sum.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer array A, you partition the array into (contiguous) subarrays of length at most K. 3 | After partitioning, each subarray has their values changed to become the maximum value of that subarray. 4 | 5 | Return the largest sum of the given array after partitioning. 6 | 7 | Example 1: 8 | Input: A = [1,15,7,9,2,5,10], K = 3 9 | Output: 84 10 | Explanation: A becomes [15,15,15,9,10,10,10] 11 | 12 | Note: 13 | 1. 1 <= K <= A.length <= 500 14 | 2. 0 <= A[i] <= 10^6 15 | */ 16 | 17 | /** 18 | * Approach: DP 19 | * 刚刚看到这个问题的时候没有什么好的思路,因此从数据规模入手推测大概的时间复杂度为 O(n^2) 20 | * 因为是优化类的问题,想到使用 Greedy,从左向右进行修改,但是很容易就发现该策略是错的, 21 | * 而且时间复杂度是 O(n),同时该题无法排序解决。因此排除 Greedy 和 PriorityQueue 的解法。 22 | * 最后只剩下 DP 的解法(老实说一开始有考虑到 DP,但是没静下心去想 递推方程,就把 DP 给 Pass了,naive...) 23 | * 24 | * 确定从 DP 入手后,我们需要想好如何确定状态,已经状态之间的递推关系。 25 | * 当数组范围确定之后,题目的结果也已经确定了。因此可以从这里进行入手: 26 | * dp[i] 表示前 i 个元素的 maxSum 结果。 27 | * 则 dp[i] 的结果依赖于 [i-K, i] 这段数组的一个划分情况。(划分的子数组长度不得超过 K) 28 | * [i-K, i]区间中可以任意选取一段 [x, i] 来作为当前分割的最后一段,因此状态转移方程为: 29 | * dp[i] = max{dp[i - k] + currMax * k} (1 ≤k≤K) 30 | * 同时,在此过程中我们需要维护一个 currMax ([i-k, i] 的区间最大值) 31 | * 32 | * 时间复杂度:O(n^2) 33 | * 空间复杂度:O(n) 34 | * 35 | * Reference: 36 | * https://youtu.be/3M8q-wB2tmw 37 | */ 38 | class Solution { 39 | public int maxSumAfterPartitioning(int[] A, int K) { 40 | int n = A.length, dp[] = new int[n + 1]; 41 | // 关于数组元素下标的问题,如果感觉不确定可以直接举个例子即可 42 | for (int i = 1; i <= n; i++) { 43 | int currMax = Integer.MIN_VALUE; 44 | for (int k = 1; k <= Math.min(i, K); k++) { 45 | currMax = Math.max(currMax, A[i - k]); 46 | dp[i] = Math.max(dp[i], dp[i - k] + currMax * k); 47 | } 48 | } 49 | return dp[n]; 50 | } 51 | } -------------------------------------------------------------------------------- /Partition Array for Maximum Sum/Partition Array for Maximum Sum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an integer array A, you partition the array into (contiguous) subarrays of length at most K. 3 | After partitioning, each subarray has their values changed to become the maximum value of that subarray. 4 | 5 | Return the largest sum of the given array after partitioning. 6 | 7 | Example 1: 8 | Input: A = [1,15,7,9,2,5,10], K = 3 9 | Output: 84 10 | Explanation: A becomes [15,15,15,9,10,10,10] 11 | 12 | Note: 13 | 1. 1 <= K <= A.length <= 500 14 | 2. 0 <= A[i] <= 10^6 15 | ''' 16 | 17 | # Approach: DP 18 | # 时间复杂度:O(n^2) 19 | # 空间复杂度:O(n) 20 | # 解法详解参考同名 java 文件 21 | class Solution: 22 | def maxSumAfterPartitioning(self, A: List[int], K: int) -> int: 23 | n = len(A) 24 | dp =[0] * (n + 1) 25 | for i in range(1, n + 1): 26 | currMax = 0 27 | for k in range(1, min(i, K) + 1): 28 | currMax = max(currMax, A[i - k]) 29 | dp[i] = max(dp[i], dp[i - k] + currMax * k) 30 | return dp[n] -------------------------------------------------------------------------------- /Partition Equal Subset Sum.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a non-empty array containing only positive integers, 3 | find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal. 4 | 5 | Note: 6 | Each of the array element will not exceed 100. 7 | The array size will not exceed 200. 8 | 9 | Example 1: 10 | Input: [1, 5, 11, 5] 11 | Output: true 12 | Explanation: The array can be partitioned as [1, 5, 5] and [11]. 13 | 14 | Example 2: 15 | Input: [1, 2, 3, 5] 16 | Output: false 17 | Explanation: The array cannot be partitioned into equal sum subsets. 18 | */ 19 | 20 | /** 21 | * Approach: 01 Backpack 22 | * Subset 问题,因为可以无序,所以直接不考虑 Sliding Window / PreSum 等这些方法。 23 | * 因为要求能否将整个数组分成两个 sum 相等的 subArray. 24 | * 因此首先将整个数组的 sum 求出来,若不能被 2 整除直接返回 false 即可。 25 | * 如果可以,那么问题就变成了能否从数组中取出 几个数 使其和为 sum / 2. 26 | * 也就是典型的 01背包问题。 27 | * 因为过于典型...这里直接给出优化后的解法了... 28 | * 29 | * 不了解 01背包问题 的可以参考: 30 | * https://github.com/cherryljr/NowCoder/blob/master/%E6%95%B0%E7%BB%84%E5%92%8C%E4%B8%BAsum%E7%9A%84%E6%96%B9%E6%B3%95%E6%95%B0.java 31 | */ 32 | class Solution { 33 | public boolean canPartition(int[] nums) { 34 | if (nums == null || nums.length <= 1) { 35 | return false; 36 | } 37 | 38 | int sum = 0; 39 | for (int i = 0; i < nums.length; i++) { 40 | sum += nums[i]; 41 | } 42 | if ((sum & 1) == 0) { 43 | return backpack(nums, sum >> 1); 44 | } else { 45 | return false; 46 | } 47 | } 48 | 49 | private boolean backpack(int[] nums, int target) { 50 | boolean[] dp = new boolean[target + 1]; 51 | dp[0] = true; 52 | if (nums[0] <= target) { 53 | dp[nums[0]] = true; 54 | } 55 | 56 | for (int i = 1; i < nums.length; i++) { 57 | // Guarantee the size is big enough to put num[i] into the backpack. 58 | for (int j = target; j >= nums[i]; j--) { 59 | dp[j] |= dp[j - nums[i]]; 60 | } 61 | } 62 | return dp[target]; 63 | } 64 | } -------------------------------------------------------------------------------- /Partition Labels.java: -------------------------------------------------------------------------------- 1 | /* 2 | A string S of lowercase letters is given. We want to partition this string into as many parts as possible 3 | so that each letter appears in at most one part, and return a list of integers representing the size of these parts. 4 | 5 | Example 1: 6 | Input: S = "ababcbacadefegdehijhklij" 7 | Output: [9,7,8] 8 | Explanation: 9 | The partition is "ababcbaca", "defegde", "hijhklij". 10 | This is a partition so that each letter appears in at most one part. 11 | A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits S into less parts. 12 | 13 | Note: 14 | S will have length in range [1, 500]. 15 | S will consist of lowercase letters ('a' to 'z') only. 16 | */ 17 | 18 | /** 19 | * Approach: Greedy + HashMap (Array) 20 | * 这道题目实际上有一定贪心的思想在里面。 21 | * 为了保证每个元素在当前 subString 中出现次数最多, 22 | * 那就说明了在整个 String 中,subString 中的字符只会出现在这里面。 23 | * 因此我们可以使用一个 Map 来记录下每个字符最后一次的出现位置。 24 | * (这里因为数据确定只有字母,所以可以开一个数组来替代) 25 | * 然后再遍历一遍字符串,同时维护两个元素 start, end。 26 | * 只有当当前位置 i 等于 lastIndex[str[i]] 时,说明正好可以被切分。 27 | * 否则就继续向后走,更新 end 的值。 28 | * (必须保证前面所有元素都被子串包含,因此end为当前子串所有出现过字符最后一次出现的位置) 29 | * 30 | * 时间复杂度:O(n) 31 | * 空间复杂度:O(n) 32 | * 33 | * 参考资料: 34 | * http://zxi.mytechroad.com/blog/string/leetcode-763-partition-labels/ 35 | */ 36 | class Solution { 37 | public List partitionLabels(String S) { 38 | int[] lastIndex = new int[128]; 39 | // 记录所有字符最后一次出现的位置 40 | for (int i = 0; i < S.length(); i++) { 41 | lastIndex[S.charAt(i)] = i; 42 | } 43 | 44 | List rst = new LinkedList<>(); 45 | int start = 0, end = 0; 46 | for (int i = 0; i < S.length(); i++) { 47 | // Update end(end为当前子串所有出现过字符最后一次出现的位置) 48 | end = Math.max(end, lastIndex[S.charAt(i)]); 49 | if (i == end) { 50 | rst.add(end - start + 1); 51 | start = end + 1; 52 | } 53 | } 54 | return rst; 55 | } 56 | } -------------------------------------------------------------------------------- /Path In Zigzag Labelled Binary Tree/Path In Zigzag Labelled Binary Tree.java: -------------------------------------------------------------------------------- 1 | /* 2 | In an infinite binary tree where every node has two children, the nodes are labelled in row order. 3 | In the odd numbered rows (ie., the first, third, fifth,...), the labelling is left to right, 4 | while in the even numbered rows (second, fourth, sixth,...), the labelling is right to left. 5 | 6 | Given the label of a node in this tree, return the labels in the path from the root of the tree to the node with that label. 7 | 8 | https://leetcode.com/problems/path-in-zigzag-labelled-binary-tree/ 9 | Example 1: 10 | Input: label = 14 11 | Output: [1,3,4,14] 12 | 13 | Example 2: 14 | Input: label = 26 15 | Output: [1,2,6,10,26] 16 | 17 | Constraints: 18 | 1. 1 <= label <= 10^6 19 | */ 20 | 21 | /** 22 | * Approach: The Property of Full Binary Tree 23 | * 因为题目给出的是一棵无限的树,即我们可以把它看作是一颗满二叉树,或者是一颗完全二叉树。 24 | * 假设树的节点排列顺序是正常的,而非 Zigzag。则根据满二叉树的性质,我们可以知道它的父亲节点应该是 label/2。 25 | * 那么对于 Zigzag 排列的话,我们需要对节点进行一次逆序即可。 26 | * 那么,应该如何完成这个 Reverse 操作呢?如果对层内全部的元素进行逆序操作的话,时间复杂度将会太高。 27 | * 但是我们发现因为是 Zigzag 排列的,所以它当前的父亲节点应该是与 label/2 对称的。 28 | * 而我们知道当前层的 最大值 和 最小值 分别为:(1< pathInZigZagTree(int label) { 42 | int level = 1; 43 | while ((1 << level) <= label) { 44 | level++; 45 | } 46 | 47 | List ans = new ArrayList<>(); 48 | for (; label >= 1; label >>= 1, level--) { 49 | ans.add(0, label); 50 | // 计算出当前层 label 的对称点,从而通过 label/2 得到其Zigzag排列的父亲节点 51 | label = (1 << level) - 1 + (1 << level - 1) - label; 52 | } 53 | return ans; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Path In Zigzag Labelled Binary Tree/Path In Zigzag Labelled Binary Tree.py: -------------------------------------------------------------------------------- 1 | ''' 2 | In an infinite binary tree where every node has two children, the nodes are labelled in row order. 3 | In the odd numbered rows (ie., the first, third, fifth,...), the labelling is left to right, 4 | while in the even numbered rows (second, fourth, sixth,...), the labelling is right to left. 5 | 6 | Given the label of a node in this tree, return the labels in the path from the root of the tree to the node with that label. 7 | 8 | https://leetcode.com/problems/path-in-zigzag-labelled-binary-tree/ 9 | Example 1: 10 | Input: label = 14 11 | Output: [1,3,4,14] 12 | 13 | Example 2: 14 | Input: label = 26 15 | Output: [1,2,6,10,26] 16 | 17 | Constraints: 18 | 1. 1 <= label <= 10^6 19 | ''' 20 | 21 | # Approach: The Property of Full Binary Tree 22 | # 时间复杂度:O(logn) 23 | # 空间复杂度:O(1) 24 | # 解法详解参考同名 java 文件 25 | class Solution: 26 | def pathInZigZagTree(self, label: int) -> List[int]: 27 | level = 1 28 | while ((1 << level) <= label): level += 1 29 | ans = [] 30 | while label >= 1: 31 | ans.append(label) 32 | label = ((1 << level) - 1 + (1 << level - 1) - label) >> 1 33 | level -= 1 34 | return ans[::-1] -------------------------------------------------------------------------------- /Peak Index in a Mountain Array/Peak Index in a Mountain Array.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Let's call an array A a mountain if the following properties hold: 3 | ·A.length >= 3 4 | ·There exists some 0 < i < A.length - 1 such that A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] 5 | Given an array that is definitely a mountain, return any i such that A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]. 6 | 7 | Example 1: 8 | Input: [0,1,0] 9 | Output: 1 10 | 11 | Example 2: 12 | Input: [0,2,1,0] 13 | Output: 1 14 | 15 | Note: 16 | 1. 3 <= A.length <= 10000 17 | 2. 0 <= A[i] <= 10^6 18 | 3. A is a mountain, as defined above. 19 | ''' 20 | 21 | # Approach: Binary Search 22 | # 时间复杂度:O(logn) 23 | # 空间复杂度:O(1) 24 | # 解法详解参考同名 java 文件 25 | class Solution: 26 | def peakIndexInMountainArray(self, A: List[int]) -> int: 27 | left, right = 0, len(A) 28 | while left < right: 29 | mid = left + (right - left >> 1) 30 | if A[mid] < A[mid + 1]: 31 | left = mid + 1 32 | else: 33 | right = mid 34 | return left 35 | # Approach 2: Using Python's API 36 | # return A.index(max(A)) -------------------------------------------------------------------------------- /Perfect Rectangle/Perfect Rectangle.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given N axis-aligned rectangles where N > 0, determine if they all together form an exact cover of a rectangular region. 3 | Each rectangle is represented as a bottom-left point and a top-right point. For example, a unit square is represented as [1,1,2,2]. 4 | (coordinate of bottom-left point is (1, 1) and top-right point is (2, 2)). 5 | 6 | https://leetcode.com/problems/perfect-rectangle/ 7 | Example 1: 8 | rectangles = [ 9 | [1,1,3,3], 10 | [3,1,4,2], 11 | [3,2,4,4], 12 | [1,3,2,4], 13 | [2,3,3,4] 14 | ] 15 | Return true. All 5 rectangles together form an exact cover of a rectangular region. 16 | 17 | Example 2: 18 | rectangles = [ 19 | [1,1,2,3], 20 | [1,3,2,4], 21 | [3,1,4,2], 22 | [3,2,4,4] 23 | ] 24 | Return false. Because there is a gap between the two rectangular regions. 25 | 26 | Example 3: 27 | rectangles = [ 28 | [1,1,3,3], 29 | [3,1,4,2], 30 | [1,3,2,4], 31 | [3,2,4,4] 32 | ] 33 | Return false. Because there is a gap in the top center. 34 | 35 | Example 4: 36 | rectangles = [ 37 | [1,1,3,3], 38 | [3,1,4,2], 39 | [1,3,2,4], 40 | [2,2,4,4] 41 | ] 42 | Return false. Because two of the rectangles overlap with each other. 43 | ''' 44 | 45 | # Approach: Geometry 46 | # 时间复杂度:O(n) 47 | # 空间复杂度:O(n) 48 | # 解法详解参考同名 java 文件 49 | class Solution: 50 | def isRectangleCover(self, rectangles: List[List[int]]) -> bool: 51 | area = 0 52 | pointSet = set() 53 | a, c = lambda: (X - x) * (Y - y), lambda: {(x, y), (x, Y), (X, y), (X, Y)} 54 | for x, y, X, Y in rectangles: 55 | area += a() 56 | pointSet ^= c() 57 | x, y, X, Y = (f(z) for f, z in zip((min, min, max, max), zip(*rectangles))) 58 | return area == a() and pointSet == c() -------------------------------------------------------------------------------- /Play with Chips.java: -------------------------------------------------------------------------------- 1 | /* 2 | There are some chips, and the i-th chip is at position chips[i]. 3 | You can perform any of the two following types of moves any number of times (possibly zero) on any chip: 4 | Move the i-th chip by 2 units to the left or to the right with a cost of 0. 5 | Move the i-th chip by 1 unit to the left or to the right with a cost of 1. 6 | There can be two or more chips at the same position initially. 7 | 8 | Return the minimum cost needed to move all the chips to the same position (any position). 9 | 10 | Example 1: 11 | Input: chips = [1,2,3] 12 | Output: 1 13 | Explanation: Second chip will be moved to positon 3 with cost 1. First chip will be moved to position 3 with cost 0. Total cost is 1. 14 | 15 | Example 2: 16 | Input: chips = [2,2,2,3,3] 17 | Output: 2 18 | Explanation: Both fourth and fifth chip will be moved to position two with cost 1. Total minimum cost will be 2. 19 | 20 | Constraints: 21 | 1. 1 <= chips.length <= 100 22 | 2. 1 <= chips[i] <= 10^9 23 | */ 24 | 25 | /** 26 | * Approach: Mathematics 27 | * 分析下来很明显...计算偶数和奇数位置的个数即可...最后的结果就是把个数较少的全部移到较多的那边去。 28 | * 29 | * 时间复杂度:O(n) 30 | * 空间复杂度:O(n) 31 | */ 32 | class Solution { 33 | public int minCostToMoveChips(int[] chips) { 34 | int odd = 0, even = 0; 35 | for (int chip : chips) { 36 | if (chip % 2 == 0) { 37 | even += 1; 38 | } else { 39 | odd += 1; 40 | } 41 | } 42 | return Math.min(even, odd); 43 | } 44 | } -------------------------------------------------------------------------------- /Plus One.java: -------------------------------------------------------------------------------- 1 | From end to start, 2 | if the number[index] != 9, we plus one directly then quit the loop. 3 | if the number[index] == 9, we set it to 0, and continue the loop until we encounter the number don't equals to 9. 4 | After the loop, if number[0] == 0, it means that we need a bigger array to represent the number. 5 | so we create a new array rst, and set rst[0] to 1. 6 | 7 | /* 8 | Given a non-negative integer represented as a non-empty array of digits, plus one to the integer. 9 | You may assume the integer do not contain any leading zero, except the number 0 itself. 10 | The digits are stored such that the most significant digit is at the head of the list. 11 | 12 | The description of this question is poor. 13 | You can look the explianation here for better understanding: 14 | 15 | suppose you have a number in your list/array such that adding 1 would make it a two digit number, 16 | eg: [9] 17 | output: [1,0] 18 | Plusone(9) would be [10], but the expected output should be [1,0] such that the most significant digit is on the head 19 | */ 20 | 21 | class Solution { 22 | public int[] plusOne(int[] digits) { 23 | for (int i = digits.length - 1; i >= 0; i--) { 24 | if (digits[i] != 9) { 25 | digits[i]++; 26 | break; 27 | } else { 28 | digits[i] = 0; 29 | } 30 | } 31 | if (digits[0] == 0) { 32 | int[] rst = new int[digits.length + 1]; 33 | rst[0] = 1; 34 | return rst; 35 | } 36 | return digits; 37 | } 38 | } -------------------------------------------------------------------------------- /Power of Four.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer (signed 32 bits), write a function to check whether it is a power of 4. 3 | 4 | Example: 5 | Given num = 16, return true. Given num = 5, return false. 6 | 7 | Follow up: Could you solve it without loops/recursion? 8 | */ 9 | 10 | /** 11 | * Approach 1: Loop Iteration 12 | * 采用 while 循环一次次地将 n 除以 4,并判断其余数是否为 0. 13 | * 该方法适用于所有该类型题目,时间复杂度为:O(log4(n)) 14 | */ 15 | class Solution { 16 | public boolean isPowerOfFour(int num) { 17 | if (num < 1) { 18 | return false; 19 | } 20 | 21 | while ((num & 3) == 0) { // 对 4 取余,等同于 num % 4 == 0 22 | num >>= 2; // 除以 4,等同于 num /= 4 23 | } 24 | 25 | return num == 1 ? true : false; 26 | } 27 | } 28 | 29 | /** 30 | * Approach 2: Bit Operation 31 | * 在 Power of Two 中,我们使用了 位运算 对其进行了加速。 32 | * 而 4 和 2 比较类似,4^n 的二进制也具备:第一位(最高位)为1,其余位均为 0 的这么一个特点, 33 | * 因此我们想我们是否也可以采用同样的方法来解决呢? 34 | * 并且我们知道 4 作为 2 的倍数,因此有些 2^n 并不是 4^n. 35 | * 因此我们需要对 4^n 进行观察,我们可以发现有如下 3 点特点: 36 | * 1. 首先必须大于 0; 37 | * 2. 其次与 2^n 的二进制相同,只有最高位为 1. 这一点可以同样利用 (n & (n-1)) == 0 来判断 38 | * 3. 4^n 的二进制最高位的 1 只在 奇数位 上。 39 | * 比如:16, 二进制为:00010000. 1 在第 5 位上(从左往右). 40 | * 因此我们可以将 n 和 0x55555555 进行 与操作 来判断 最高位的1 是否在 奇数位 上。 41 | * 注:&0x55555555 的作用就是取 int 类型的数的二进制 奇数位上的数,因为 5 的二进制就是 0101 42 | * 同样的还有取 偶数位 上的数等:如 &0xaaaaaaaa. 43 | * 应用的题目有:https://github.com/cherryljr/LeetCode/blob/master/Reverse%20Bits.java 44 | */ 45 | class Solution { 46 | public boolean isPowerOfFour(int num) { 47 | if (num < 1) { 48 | return false; 49 | } 50 | 51 | return num > 0 && (num & (num -1)) == 0 && (num & 0x55555555) != 0; 52 | } 53 | } -------------------------------------------------------------------------------- /Power of Three.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer, write a function to determine if it is a power of three. 3 | 4 | Follow up: 5 | Could you do it without using any loop / recursion? 6 | */ 7 | 8 | /** 9 | * Approach 1: Loop Iteration 10 | * 采用 while 循环一次次地将 n 除以 3,并判断其余数是否为 0. 11 | * 该方法适用于所有该类型题目,时间复杂度为:O(log3(n)) 12 | */ 13 | class Solution { 14 | public boolean isPowerOfThree(int n) { 15 | if (n < 1) { 16 | return false; 17 | } 18 | 19 | while (n % 3 == 0) { 20 | n /= 3; 21 | } 22 | return n == 1 ? true : false; 23 | } 24 | } 25 | 26 | /** 27 | * Approach 2: Integer Limitations 28 | * 该解法是从网上看来的...利用了 Integer 类型的最大值去计算... 29 | * 反正我是没想出来啦... 30 | * 参考资料: 31 | * https://leetcode.com/problems/power-of-three/solution/ 32 | */ 33 | class Solution { 34 | public boolean isPowerOfThree(int n) { 35 | return n > 0 && 1162261467 % n == 0; 36 | } 37 | } -------------------------------------------------------------------------------- /Power of Two.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer, write a function to determine if it is a power of two. 3 | */ 4 | 5 | /** 6 | * Approach: Bit Operation 7 | * 编程中优化运算速度的常见技巧之一 8 | * 使用了 Bit Manipulation : n & (n - 1) 9 | * 其效果为:去掉 一个数二进制的 最右边 的一个1 10 | * 该运算也在下面两个问题中应用到了 11 | * 1. 求 n 的二进制的最后一位为1的位数。 log2(n - (n & (n-1))) == log2(n & -n) 12 | * 上面式子的简化如果不懂的话可以参考:Binary Index Tree Template 中 LowBit(index) 函数 的解析 13 | * https://github.com/cherryljr/LeetCode/blob/master/Binary%20Index%20Tree%20Template.java 14 | * 2. 求 n 的二进制中 1 的个数 15 | * 16 | * Note: 17 | * == has higher priority than &. You might want to wrap your operations in () to specify your own priority. 18 | */ 19 | class Solution { 20 | public boolean isPowerOfTwo(int n) { 21 | if (n <= 0) { 22 | return false; 23 | } 24 | 25 | return (n & (n - 1)) == 0 ? true : false; 26 | } 27 | } -------------------------------------------------------------------------------- /Previous Permutation With One Swap/Previous Permutation With One Swap.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given an array A of positive integers (not necessarily distinct), 3 | return the lexicographically largest permutation that is smaller than A, 4 | that can be made with one swap (A swap exchanges the positions of two numbers A[i] and A[j]). 5 | If it cannot be done, then return the same array. 6 | 7 | Example 1: 8 | Input: [3,2,1] 9 | Output: [3,1,2] 10 | Explanation: Swapping 2 and 1. 11 | 12 | Example 2: 13 | Input: [1,1,5] 14 | Output: [1,1,5] 15 | Explanation: This is already the smallest permutation. 16 | 17 | Example 3: 18 | Input: [1,9,4,6,7] 19 | Output: [1,7,4,6,9] 20 | Explanation: Swapping 9 and 7. 21 | 22 | Example 4: 23 | Input: [3,1,1,3] 24 | Output: [1,3,1,3] 25 | Explanation: Swapping 1 and 3. 26 | 27 | Note: 28 | 1. 1 <= A.length <= 10000 29 | 2. 1 <= A[i] <= 10000 30 | ''' 31 | 32 | # Approach: Traverse and Swap (Similar to Next Permutation) 33 | # 时间复杂度:O(n) 34 | # 空间复杂度:O(1) 35 | # 解法详解参考同名 java 文件 36 | class Solution: 37 | def prevPermOpt1(self, A: List[int]) -> List[int]: 38 | if not A or len(A) <= 1: 39 | return A 40 | 41 | n, index = len(A), len(A) - 2 42 | while index >= 0 and A[index] <= A[index + 1]: 43 | index -= 1 44 | if index >= 0: 45 | smaller = n - 1 46 | while smaller >= 0 and A[smaller] >= A[index]: 47 | smaller -= 1 48 | while smaller >= 1 and A[smaller] == A[smaller - 1]: 49 | smaller -= 1 50 | A[index], A[smaller] = A[smaller], A[index] 51 | return A -------------------------------------------------------------------------------- /Prime Arrangements.java: -------------------------------------------------------------------------------- 1 | /* 2 | Return the number of permutations of 1 to n so that prime numbers are at prime indices (1-indexed.) 3 | (Recall that an integer is prime if and only if it is greater than 1, 4 | and cannot be written as a product of two positive integers both smaller than it.) 5 | 6 | Since the answer may be large, return the answer modulo 10^9 + 7. 7 | 8 | Example 1: 9 | Input: n = 5 10 | Output: 12 11 | Explanation: For example [1,2,5,4,3] is a valid permutation, 12 | but [5,2,3,4,1] is not because the prime number 5 is at index 1. 13 | 14 | Example 2: 15 | Input: n = 100 16 | Output: 682289015 17 | 18 | Constraints: 19 | 1. 1 <= n <= 100 20 | */ 21 | 22 | /** 23 | * Approach: Sieve method 24 | */ 25 | class Solution { 26 | private static final int MOD = 1000000007; 27 | 28 | public int numPrimeArrangements(int n) { 29 | boolean[] isPrime = new boolean[n + 1]; 30 | Arrays.fill(isPrime, 2, n + 1, true); 31 | for (int i = 2; i * i <= n; i++) { 32 | if (isPrime[i]) { 33 | for (int j = i * i; j <= n; j += i) { 34 | isPrime[j] = false; 35 | } 36 | } 37 | } 38 | int primeCount = 0; 39 | for (int i = 0; i < isPrime.length; i++) { 40 | primeCount += isPrime[i] ? 1 : 0; 41 | } 42 | return (int)(permutation(primeCount) * permutation(n - primeCount) % MOD); 43 | } 44 | 45 | private long permutation(int n) { 46 | long count = 1L; 47 | while (n > 0) { 48 | count = count * n-- % MOD; 49 | } 50 | return count; 51 | } 52 | } -------------------------------------------------------------------------------- /Product of Array Exclude Itself.java: -------------------------------------------------------------------------------- 1 | 前后遍历的方法 2 | Solution : O(N) 3 | 首先对List进行一次 从前往后 的一次遍历。得到除去第 i 个数值的,左边 i-1 个数值的积。 4 | 然后对List进行一次 从后往前 的一次遍历。得到出去第 i 个数值的,右边 i-1 个数字的积。 5 | 最后将各个位置上对应的 左边数值积 乘以 右边数值积 便可以得到最终的结果。 6 | 7 | /* 8 | Given an array of n integers where n > 1, nums, 9 | return an array output such that output[i] is equal to the product of all the elements of nums except nums[i]. 10 | 11 | Solve it without division and in O(n). 12 | 13 | For example, given [1,2,3,4], return [24,12,8,6]. 14 | 15 | Follow up: 16 | Could you solve it with constant space complexity? 17 | (Note: The output array does not count as extra space for the purpose of space complexity analysis.) 18 | */ 19 | 20 | class Solution { 21 | public int[] productExceptSelf(int[] nums) { 22 | int[] rst = new int[nums.length]; 23 | if (nums == null || nums.length == 0) { 24 | return rst; 25 | } 26 | 27 | rst[0] = 1; 28 | for (int i = 1; i < nums.length; i++) { 29 | rst[i] = rst[i - 1] * nums[i - 1]; 30 | } 31 | int right = 1; 32 | for (int i = nums.length - 1; i >= 0; i--) { 33 | rst[i] *= right; 34 | right *= nums[i]; 35 | } 36 | 37 | return rst; 38 | } 39 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LeetCode 2 | ======== 3 | 4 | ### LeetCode Algorithm 5 | 6 | The Solutions of problems in LeetCode with deatial Explanations 7 | 8 | | # | Title | Solution | Difficulty | 9 | |---| ----- | -------- | ---------- | 10 | |1|[Add Two Sum](https://oj.leetcode.com/problems/two-sum/)| [Java](https://github.com/cherryljr/LeetCode/blob/master/Add%20Two%20Numbers.java)|Medium| 11 | -------------------------------------------------------------------------------- /Random Pick Index.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers with possible duplicates, randomly output the index of a given target number. 3 | You can assume that the given target number must exist in the array. 4 | 5 | Note: 6 | The array size can be very large. Solution that uses too much extra space will not pass the judge. 7 | 8 | Example: 9 | 10 | int[] nums = new int[] {1,2,3,3,3}; 11 | Solution solution = new Solution(nums); 12 | 13 | // pick(3) should return either index 2, 3, or 4 randomly. Each index should have equal probability of returning. 14 | solution.pick(3); 15 | 16 | // pick(1) should return 0. Since in the array only nums[0] is equal to 1. 17 | solution.pick(1); 18 | */ 19 | 20 | /** 21 | * Approach: Reservoir Sampling 22 | * 蓄水池抽样算法. 23 | * 与 Linked List Random Node 是同一类型的题目。 24 | * 关于该算法的讲解与证明可以参考: 25 | * https://github.com/cherryljr/LeetCode/blob/master/Linked%20List%20Random%20Node.java 26 | */ 27 | class Solution { 28 | int[] nums; 29 | Random random; 30 | 31 | public Solution(int[] nums) { 32 | this.nums = nums; 33 | this.random = new Random(); 34 | } 35 | 36 | public int pick(int target) { 37 | int rst = -1; 38 | int count = 0; 39 | for (int i = 0; i < nums.length; i++) { 40 | // 如果与该 target 相等,count++,此处的 count 相当于元素总个数 N 41 | // 蓄水池大小仍然只有 1. 42 | if (nums[i] == target) { 43 | // nums[i] 有 1/(count+1) 的概率进入池子 44 | if (random.nextInt(++count) == 0) { 45 | rst = i; 46 | } 47 | } 48 | } 49 | return rst; 50 | } 51 | } 52 | 53 | /** 54 | * Your Solution object will be instantiated and called as such: 55 | * Solution obj = new Solution(nums); 56 | * int param_1 = obj.pick(target); 57 | */ 58 | -------------------------------------------------------------------------------- /Range Sum Query - Immutable.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. 3 | 4 | Example: 5 | Given nums = [-2, 0, 3, -5, 2, -1] 6 | 7 | sumRange(0, 2) -> 1 8 | sumRange(2, 5) -> -1 9 | sumRange(0, 5) -> -3 10 | 11 | Note: 12 | You may assume that the array does not change. 13 | There are many calls to sumRange function. 14 | */ 15 | 16 | /** 17 | * Approach: Prefix Sum 18 | */ 19 | class NumArray { 20 | private int[] preSum; 21 | 22 | public NumArray(int[] nums) { 23 | if (nums.length != 0) { 24 | preSum = new int[nums.length]; 25 | 26 | preSum[0] = nums[0]; 27 | for(int i = 1; i < nums.length; i++){ 28 | preSum[i] = preSum[i - 1] + nums[i]; 29 | } 30 | } 31 | } 32 | 33 | public int sumRange(int i, int j) { 34 | return i == 0 ? preSum[j] : preSum[j] - preSum[i - 1]; 35 | } 36 | } -------------------------------------------------------------------------------- /Rectangle Area.java: -------------------------------------------------------------------------------- 1 | /* 2 | Find the total area covered by two rectilinear rectangles in a 2D plane. 3 | Each rectangle is defined by its bottom left corner and top right corner as shown in the figure. 4 | 5 | Rectangle Area 6 | https://leetcode.com/problems/rectangle-area/description/ 7 | 8 | Example: 9 | Input: A = -3, B = 0, C = 3, D = 4, E = 0, F = -1, G = 9, H = 2 10 | Output: 45 11 | 12 | Note: 13 | Assume that the total area is never beyond the maximum possible value of int. 14 | */ 15 | 16 | /** 17 | * Approach: Geometry 18 | * 单纯几何问题的计算,判断两个矩形是否相交, 19 | * 如果相交减去重叠部分的面积即可。 20 | * 21 | * 同时这里也提供了一种判断矩形是否相交的做法, 22 | * 除此之外我们还有其他的方法可以用来判断两个矩阵是否相交。 23 | * 详情可以参考: 24 | * https://github.com/cherryljr/LeetCode/blob/master/Rectangle%20Overlap.java 25 | */ 26 | class Solution { 27 | public int computeArea(int A, int B, int C, int D, int E, int F, int G, int H) { 28 | int left = Math.max(A, E); // 最靠近右侧的左端点 29 | int right = Math.min(C, G); // 最靠近左侧的右端点 30 | int bottom = Math.max(B, F);// 最靠近上方的下端点 31 | int top = Math.min(D, H); // 最靠近下方的上端点 32 | 33 | int overlap = 0; 34 | // 判断两个矩形是否相交 35 | if (left < right && bottom < top) { 36 | overlap = (right - left) * (top - bottom); 37 | } 38 | return (C - A) * (D - B) + (G - E) * (H - F) - overlap; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Relative Sort Array.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given two arrays arr1 and arr2, the elements of arr2 are distinct, and all elements in arr2 are also in arr1. 3 | Sort the elements of arr1 such that the relative ordering of items in arr1 are the same as in arr2. 4 | Elements that don't appear in arr2 should be placed at the end of arr1 in ascending order. 5 | 6 | Example 1: 7 | Input: arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6] 8 | Output: [2,2,2,1,4,3,3,9,6,7,19] 9 | 10 | Constraints: 11 | 1. arr1.length, arr2.length <= 1000 12 | 2. 0 <= arr1[i], arr2[i] <= 1000 13 | 3. Each arr2[i] is distinct. 14 | 4. Each arr2[i] is in arr1. 15 | */ 16 | 17 | /** 18 | * Approach: Similar to BucketSort 19 | * 因为题目明确给出了数值的范围 0~1000 20 | * 因此可以利用类似桶排序的方法进行解决。 21 | * 首先统计 arr1 中各个元素出现的次数,然后遍历 arr2 22 | * 先把 arr2 中出现的元素,按照顺序填到结果中,然后再遍历一次 count[] 23 | * 把剩余的元素按照从小到大填入结果中即可。 24 | * 25 | * 时间复杂度:O(1001) ==> O(1) 26 | * 空间复杂度:O(1001) ==> O(1) 27 | * 28 | * PS.如果题目没有给出具体的数值范围,则利用 TreeMap 进行统计即可。 29 | */ 30 | class Solution { 31 | public int[] relativeSortArray(int[] arr1, int[] arr2) { 32 | int[] count = new int[1001]; 33 | for (int num : arr1) { 34 | count[num] += 1; 35 | } 36 | 37 | int index = 0, ans[] = new int[arr1.length]; 38 | for (int num : arr2) { 39 | while (count[num]-- > 0) { 40 | ans[index++] = num; 41 | } 42 | } 43 | for (int i = 0; i < count.length; i++) { 44 | while (count[i]-- > 0) { 45 | ans[index++] = i; 46 | } 47 | } 48 | return ans; 49 | } 50 | } -------------------------------------------------------------------------------- /Remove All Adjacent Duplicates In String/Remove All Adjacent Duplicates In String.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string S of lowercase letters, a duplicate removal consists of choosing two adjacent and equal letters, and removing them. 3 | We repeatedly make duplicate removals on S until we no longer can. 4 | 5 | Return the final string after all such duplicate removals have been made. It is guaranteed the answer is unique. 6 | 7 | Example 1: 8 | Input: "abbaca" 9 | Output: "ca" 10 | Explanation: 11 | For example, in "abbaca" we could remove "bb" since the letters are adjacent and equal, and this is the only possible move. 12 | The result of this move is that the string is "aaca", of which only "aa" is possible, so the final string is "ca". 13 | 14 | Note: 15 | 1. 1 <= S.length <= 20000 16 | 2. S consists only of English lowercase letters. 17 | ''' 18 | 19 | # Approach: Stack 20 | # 时间复杂度:O(n) 21 | # 空间复杂度:O(n) 22 | # 解法详解参考同名 java 文件 23 | class Solution: 24 | def removeDuplicates(self, S: str) -> str: 25 | ans = [] 26 | for c in S: 27 | if ans and ans[-1] == c: 28 | ans.pop() 29 | else: 30 | ans.append(c) 31 | return "".join(ans) -------------------------------------------------------------------------------- /Remove Duplicate Letters/Remove Duplicate Letters.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a string which contains only lowercase letters, remove duplicate letters so that every letter appear once and only once. 3 | You must make sure your result is the smallest in lexicographical order among all possible results. 4 | 5 | Example 1: 6 | Input: "bcabc" 7 | Output: "abc" 8 | 9 | Example 2: 10 | Input: "cbacdcbc" 11 | Output: "acdb" 12 | ''' 13 | 14 | # Approach: Monotonic Stack (Same as Smallest Subsequence of Distinct Characters) 15 | # 时间复杂度:O(n) 16 | # 空间复杂度:O(n) 17 | # 解法详解参考同名 java 文件 18 | class Solution: 19 | def removeDuplicateLetters(self, s: str) -> str: 20 | lastIndex = {c : i for i, c in enumerate(s)} 21 | stack = [] 22 | for i, c in enumerate(s): 23 | if c in stack: continue 24 | while stack and stack[-1] > c and lastIndex[stack[-1]] > i: 25 | stack.pop() 26 | stack.append(c) 27 | return "".join(stack) -------------------------------------------------------------------------------- /Remove Outermost Parentheses/Remove Outermost Parentheses.py: -------------------------------------------------------------------------------- 1 | ''' 2 | A valid parentheses string is either empty (""), "(" + A + ")", or A + B, where A and B are valid parentheses strings, 3 | and + represents string concatenation. For example, "", "()", "(())()", and "(()(()))" are all valid parentheses strings. 4 | 5 | A valid parentheses string S is primitive if it is nonempty, and there does not exist a way to split it into S = A+B, 6 | with A and B nonempty valid parentheses strings. 7 | 8 | Given a valid parentheses string S, consider its primitive decomposition: S = P_1 + P_2 + ... + P_k, 9 | where P_i are primitive valid parentheses strings. 10 | 11 | Return S after removing the outermost parentheses of every primitive string in the primitive decomposition of S. 12 | 13 | Example 1: 14 | Input: "(()())(())" 15 | Output: "()()()" 16 | Explanation: 17 | The input string is "(()())(())", with primitive decomposition "(()())" + "(())". 18 | After removing outer parentheses of each part, this is "()()" + "()" = "()()()". 19 | 20 | Example 2: 21 | Input: "(()())(())(()(()))" 22 | Output: "()()()()(())" 23 | Explanation: 24 | The input string is "(()())(())(()(()))", with primitive decomposition "(()())" + "(())" + "(()(()))". 25 | After removing outer parentheses of each part, this is "()()" + "()" + "()(())" = "()()()()(())". 26 | 27 | Example 3: 28 | Input: "()()" 29 | Output: "" 30 | Explanation: 31 | The input string is "()()", with primitive decomposition "()" + "()". 32 | After removing outer parentheses of each part, this is "" + "" = "". 33 | 34 | Note: 35 | 1. S.length <= 10000 36 | 2. S[i] is "(" or ")" 37 | 3. S is a valid parentheses string 38 | ''' 39 | 40 | # Approach: Count Opened Parentheses 41 | # 该解法与 同名java 文件 的 Approach 2 相同 42 | class Solution: 43 | def removeOuterParentheses(self, S: str) -> str: 44 | ans, count = [], 0 45 | for c in S: 46 | count += 1 if c == '(' else -1 47 | if c == '(' and count > 1: ans.append(c) 48 | if c == ')' and count > 0: ans.append(c) 49 | return "".join(ans) -------------------------------------------------------------------------------- /Reorder List.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a singly linked list L: L0→L1→…→Ln-1→Ln, 3 | reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… 4 | 5 | You may not modify the values in the list's nodes, only nodes itself may be changed. 6 | 7 | Example 1: 8 | Given 1->2->3->4, reorder it to 1->4->2->3. 9 | 10 | Example 2: 11 | Given 1->2->3->4->5, reorder it to 1->5->2->4->3. 12 | */ 13 | 14 | /** 15 | * Approach: Split, Reverse and Merge LinkedList 16 | * 这道题目难度不高,但是是一道对链表考察得比较综合的题目,值得一练。 17 | * 看完题目和范例,基本就能想出怎么做了,答案得最终格式为: L0→Ln→L1→Ln-1→L2→Ln-2→… 18 | * 因此,解题步骤可以分为如下三步: 19 | * 1. 首先利用 find middle point in LinkedList 的方法,找出链表得中点; 20 | * 2. 将后半段的链表进行一次 reverse 操作; 21 | * 3. 将这两个链表交替 merge 起来 22 | * 23 | * 时间复杂度:O(n) 24 | * 空间复杂度:O(1) 25 | * 26 | * Reference: 27 | * https://github.com/cherryljr/LintCode/blob/master/Reorder%20List.java 28 | */ 29 | 30 | /** 31 | * Definition for singly-linked list. 32 | * public class ListNode { 33 | * int val; 34 | * ListNode next; 35 | * ListNode(int x) { val = x; } 36 | * } 37 | */ 38 | class Solution { 39 | public void reorderList(ListNode head) { 40 | if (head == null || head.next == null) { 41 | return; 42 | } 43 | 44 | ListNode slow = head, fast = head; 45 | while (fast != null && fast.next != null) { 46 | slow = slow.next; 47 | fast = fast.next.next; 48 | } 49 | 50 | ListNode head2 = reverse(slow.next); 51 | slow.next = null; 52 | while (head != null && head2 != null) { 53 | ListNode next1 = head.next; 54 | ListNode next2 = head2.next; 55 | head.next = head2; 56 | head2.next = next1; 57 | head = next1; 58 | head2 = next2; 59 | } 60 | } 61 | 62 | private ListNode reverse(ListNode node) { 63 | ListNode prev = null; 64 | while (node != null) { 65 | ListNode next = node.next; 66 | node.next = prev; 67 | prev = node; 68 | node = next; 69 | } 70 | return prev; 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /Reverse Bits.java: -------------------------------------------------------------------------------- 1 | /* 2 | Reverse bits of a given 32 bits unsigned integer. 3 | 4 | For example, given input 43261596 (represented in binary as 00000010100101000001111010011100), 5 | return 964176192 (represented in binary as 00111001011110000010100101000000). 6 | 7 | Follow up: 8 | If this function is called many times, how would you optimize it? 9 | 10 | Related problem: Reverse Integer 11 | */ 12 | 13 | // Approach 1 14 | /** 15 | * 该方法是一个非常直接的方法 16 | * 首先令结果 rst = num 17 | * 然后每次 rst 左移一位为腾出空位, 18 | * 先通过与操作取出num的最低位,再通过或操作将其赋值为 rst 的最高位。 19 | * 最后 num 右移一位。 20 | * 循环 32 次即可。 21 | * 22 | * 注意点:Java中不存在无符号整数,所以我们必须通过 无符号右移>>> 来实现 23 | */ 24 | public class Solution { 25 | // you need treat n as an unsigned value 26 | public int reverseBits(int num) { 27 | int rst = num; 28 | for (int i = 31; i >= 0; i--) { 29 | rst <<= 1; 30 | rst |= num & 1; 31 | num >>>= 1; // must do unsigned shift 32 | } 33 | return rst; 34 | } 35 | } 36 | 37 | // Approach 2 38 | /** 39 | * 分治法 40 | * 逆序32位分解为两个逆序16位的 41 | * 逆序16位分解为两个逆序8位的 42 | * 逆序8位分解为两个逆序4位的 43 | * 逆序4位分解为两个逆序2位的 44 | * 最后一个2位的逆序,直接交换即可。也就是分治递归的终止条件。 45 | * 46 | * 代码也很好理解,比如:最后一步的 -- ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1) 47 | * n & 0xaaaaaaaa 是取偶数位 (a的二进制为:1010); n & 0x55555555 是取偶数位(5的二进制为:0101) 48 | * 然后偶数位无符号右移一位,奇数位左移一位,再取或,这样便实现了交换奇数偶数位。 49 | * 50 | * 以上过程经过4步,逆序完成。 51 | * 推而广之,总的时间复杂度为O(logn),n是二进制的位数。这个方法可以推广到任意位。 52 | */ 53 | public class Solution { 54 | // you need treat n as an unsigned value 55 | public int reverseBits(int n) { 56 | n = (n >>> 16) | (n << 16); 57 | n = ((n & 0xff00ff00) >>> 8) | ((n & 0x00ff00ff) << 8); 58 | n = ((n & 0xf0f0f0f0) >>> 4) | ((n & 0x0f0f0f0f) << 4); 59 | n = ((n & 0xcccccccc) >>> 2) | ((n & 0x33333333) << 2); 60 | n = ((n & 0xaaaaaaaa) >>> 1) | ((n & 0x55555555) << 1); 61 | return n; 62 | } 63 | } -------------------------------------------------------------------------------- /Robot Bounded In Circle/Robot Bounded In Circle.py: -------------------------------------------------------------------------------- 1 | ''' 2 | On an infinite plane, a robot initially stands at (0, 0) and faces north. The robot can receive one of three instructions: 3 | "G": go straight 1 unit; 4 | "L": turn 90 degrees to the left; 5 | "R": turn 90 degress to the right. 6 | The robot performs the instructions given in order, and repeats them forever. 7 | 8 | Return true if and only if there exists a circle in the plane such that the robot never leaves the circle. 9 | 10 | Example 1: 11 | Input: "GGLLGG" 12 | Output: true 13 | Explanation: 14 | The robot moves from (0,0) to (0,2), turns 180 degrees, and then returns to (0,0). 15 | When repeating these instructions, the robot remains in the circle of radius 2 centered at the origin. 16 | 17 | Example 2: 18 | Input: "GG" 19 | Output: false 20 | Explanation: 21 | The robot moves north indefinetely. 22 | 23 | Example 3: 24 | Input: "GL" 25 | Output: true 26 | Explanation: 27 | The robot moves from (0, 0) -> (0, 1) -> (-1, 1) -> (-1, 0) -> (0, 0) -> ... 28 | 29 | Note: 30 | 1. 1 <= instructions.length <= 100 31 | 2. instructions[i] is in {'G', 'L', 'R'} 32 | ''' 33 | 34 | # Approach: Judge Repeated Route In Circle 35 | # 时间复杂度:O(n) 36 | # 空间复杂度:O(1) 37 | # 解法详解参考同名 java 文件 38 | class Solution: 39 | def isRobotBounded(self, instructions: str) -> bool: 40 | DIRS = [[-1, 0], [0, 1], [1, 0], [0, -1]] 41 | index, x, y = 0, 0, 0 42 | for c in instructions: 43 | if c == 'L': index = (index + 3) % 4 44 | elif c == 'R': index = (index + 1) % 4 45 | else: x, y = x + DIRS[index][0], y + DIRS[index][1] 46 | return (x == 0 and y == 0) or index > 0 -------------------------------------------------------------------------------- /Roman to Integer.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a roman numeral, convert it to an integer. 3 | 4 | Input is guaranteed to be within the range from 1 to 3999. 5 | */ 6 | 7 | // It would help a lot for those who are not familiar with Roman numerals if the conversion rule is provided, 8 | // or a conversion table similar to Roman Numerals Chart is given. 9 | // Dislike this question!!! 10 | 11 | class Solution { 12 | public int romanToInt(String s) { 13 | int nums[] = new int[s.length()]; 14 | for(int i = 0; i < s.length(); i++){ 15 | switch (s.charAt(i)) { 16 | case 'M': 17 | nums[i] = 1000; 18 | break; 19 | case 'D': 20 | nums[i] = 500; 21 | break; 22 | case 'C': 23 | nums[i] = 100; 24 | break; 25 | case 'L': 26 | nums[i] = 50; 27 | break; 28 | case 'X' : 29 | nums[i] = 10; 30 | break; 31 | case 'V': 32 | nums[i] = 5; 33 | break; 34 | case 'I': 35 | nums[i] = 1; 36 | break; 37 | } 38 | } 39 | 40 | int sum = 0; 41 | for(int i=0; i selfDividingNumbers(int left, int right) { 25 | List rst = new LinkedList<>(); 26 | for (int num = left; num <= right; num++) { 27 | int i = num; 28 | for (; i > 0; i /= 10) { 29 | if ((i % 10 == 0) || (num % (i % 10) != 0)) { 30 | break; 31 | } 32 | } 33 | if (i == 0) { 34 | rst.add(num); 35 | } 36 | } 37 | return rst; 38 | } 39 | } -------------------------------------------------------------------------------- /Shift 2D Grid.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a 2D grid of size m x n and an integer k. You need to shift the grid k times. 3 | In one shift operation: 4 | Element at grid[i][j] becomes at grid[i][j + 1]. 5 | Element at grid[i][n - 1] becomes at grid[i + 1][0]. 6 | Element at grid[n - 1][n - 1] becomes at grid[0][0]. 7 | Return the 2D grid after applying shift operation k times. 8 | 9 | Example 1: 10 | Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 1 11 | Output: [[9,1,2],[3,4,5],[6,7,8]] 12 | 13 | Example 2: 14 | Input: grid = [[3,8,1,9],[19,7,2,5],[4,6,11,10],[12,0,21,13]], k = 4 15 | Output: [[12,0,21,13],[3,8,1,9],[19,7,2,5],[4,6,11,10]] 16 | 17 | Example 3: 18 | Input: grid = [[1,2,3],[4,5,6],[7,8,9]], k = 9 19 | Output: [[1,2,3],[4,5,6],[7,8,9]] 20 | 21 | Constraints: 22 | 1. m == grid.length 23 | 2. n == grid[i].length 24 | 3. 1 <= m <= 50 25 | 4. 1 <= n <= 50 26 | 5. -1000 <= grid[i][j] <= 1000 27 | 6. 0 <= k <= 100 28 | */ 29 | 30 | /** 31 | * Approach: MOD 32 | * Time Complexity: O(m * n) 33 | * Space Complexity: O(m * n) 34 | * av76080725 35 | */ 36 | class Solution { 37 | public List> shiftGrid(int[][] grid, int k) { 38 | int m = grid.length, n = grid[0].length, mod = m * n; 39 | k = k % mod; 40 | Integer[][] newGrid = new Integer[m][n]; 41 | for (int i = 0 ; i < mod; i++) { 42 | int pre = (i - k + mod) % mod; 43 | newGrid[i / n][i % n] = grid[pre / n][pre % n]; 44 | } 45 | 46 | List> ans = new ArrayList<>(); 47 | for (int i = 0; i < m; i++) { 48 | ans.add(Arrays.asList(newGrid[i])); 49 | } 50 | return ans; 51 | } 52 | } -------------------------------------------------------------------------------- /Shifting Letters.java: -------------------------------------------------------------------------------- 1 | /* 2 | We have a string S of lowercase letters, and an integer array shifts. 3 | Call the shift of a letter, the next letter in the alphabet, (wrapping around so that 'z' becomes 'a'). 4 | For example, shift('a') = 'b', shift('t') = 'u', and shift('z') = 'a'. 5 | Now for each shifts[i] = x, we want to shift the first i+1 letters of S, x times. 6 | Return the final string after all such shifts to S are applied. 7 | 8 | Example 1: 9 | Input: S = "abc", shifts = [3,5,9] 10 | Output: "rpl" 11 | Explanation: 12 | We start with "abc". 13 | After shifting the first 1 letters of S by 3, we have "dbc". 14 | After shifting the first 2 letters of S by 5, we have "igc". 15 | After shifting the first 3 letters of S by 9, we have "rpl", the answer. 16 | 17 | Note: 18 | 1 <= S.length = shifts.length <= 20000 19 | 0 <= shifts[i] <= 10 ^ 9 20 | */ 21 | 22 | /** 23 | * Approach: Reverse Calculation (Suffix Sum) 24 | * 比较简单的一道题目,个人认为定为 Medium 有点高了。 25 | * 根据题目要求,我们应该从后面往前进行计算。 26 | * 即 最后一位 应该移动 shifts[len-1] 次, 27 | * 倒数第二位移动 shifts[len-1] + shifts[len-2] 次。 28 | * 典型的使用 后缀和 解决的题目,但是根据题意 shifts[i] <= 10^9 所以相加时我们需要进行一次 %26 操作。 29 | * 然后我们还需要完成 字符类型 与 整形之间的转换。 30 | * 31 | * 总结本题的考点在于: 32 | * 1. 后缀和 33 | * 2. 根据题意进行取模运算(考虑到溢出情况) 34 | * 3. 字符类型与整数类型的转换 35 | * 36 | * 时间复杂度:O(n) 37 | */ 38 | class Solution { 39 | public String shiftingLetters(String S, int[] shifts) { 40 | char[] chars = S.toCharArray(); 41 | int shift = 0; 42 | for (int i = shifts.length - 1; i >= 0; i--) { 43 | // 取模运算,防止溢出 44 | shift = (shift + shifts[i]) % 26; 45 | // 利用 int 进行 shift 计算,完成后转回 char 类型 46 | chars[i] = (char)((chars[i] - 'a' + shift) % 26 + 'a'); 47 | } 48 | return String.valueOf(chars); 49 | } 50 | } -------------------------------------------------------------------------------- /Shortest Common Supersequence/Shortest Common Supersequence.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given two strings str1 and str2, return the shortest string that has both str1 and str2 as subsequences. 3 | If multiple answers exist, you may return any of them. 4 | 5 | (A string S is a subsequence of string T if deleting some number of characters from T 6 | (possibly 0, and the characters are chosen anywhere from T) results in the string S.) 7 | 8 | Example 1: 9 | Input: str1 = "abac", str2 = "cab" 10 | Output: "cabac" 11 | Explanation: 12 | str1 = "abac" is a substring of "cabac" because we can delete the first "c". 13 | str2 = "cab" is a substring of "cabac" because we can delete the last "ac". 14 | The answer provided is the shortest such string that satisfies these properties. 15 | 16 | Note: 17 | 1. 1 <= str1.length, str2.length <= 1000 18 | 2. str1 and str2 consist of lowercase English letters. 19 | ''' 20 | 21 | # Approach: DP (Similar to LCS) 22 | # 时间复杂度:O(m*n) 23 | # 空间复杂度:O(m*n) 24 | # 解法详解参考同名 java 文件 25 | class Solution: 26 | def shortestCommonSupersequence(self, str1: str, str2: str) -> str: 27 | m, n = len(str1), len(str2) 28 | def longestCommonSubSeq(str1: str, str2: str) -> str: 29 | dp = [[""] * (n + 1) for _ in range(m + 1)] 30 | for i in range(1, m + 1): 31 | for j in range(1, n + 1): 32 | if str1[i - 1] == str2[j - 1]: 33 | dp[i][j] = dp[i - 1][j - 1] + str1[i - 1] 34 | else: 35 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1], key = len) 36 | return dp[m][n] 37 | 38 | ans, p1, p2 = "", 0, 0 39 | for c in longestCommonSubSeq(str1, str2): 40 | while p1 < m and str1[p1] != c: 41 | ans += str1[p1] 42 | p1 += 1 43 | while p2 < n and str2[p2] != c: 44 | ans += str2[p2] 45 | p2 += 1 46 | ans += c 47 | p1, p2 = p1 + 1, p2 + 1 48 | return ans + str1[p1:] + str2[p2:] -------------------------------------------------------------------------------- /Shortest Distance to a Character.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a string S and a character C, return an array of integers representing 3 | the shortest distance from the character C in the string. 4 | 5 | Example 1: 6 | Input: S = "loveleetcode", C = 'e' 7 | Output: [3, 2, 1, 0, 1, 0, 0, 1, 2, 2, 1, 0] 8 | 9 | Note: 10 | S string length is in [1, 10000]. 11 | C is a single character, and guaranteed to be in string S. 12 | All letters in S and C are lowercase. 13 | */ 14 | 15 | /** 16 | * Approach: Traverse Twice 17 | * When going left to right, we'll remember the index prev of the last character C we've seen. 18 | * Then the answer is i - prev. 19 | * When going right to left, we'll remember the index prev of the last character C we've seen. 20 | * Then the answer is prev - i. 21 | * We take the minimum of these two answers to create our final answer. 22 | * 23 | * Time Complexity : O(N), where N is the length of S. We scan through the string twice. 24 | * Space Complexity: O(1) 25 | */ 26 | class Solution { 27 | public int[] shortestToChar(String S, char C) { 28 | int len = S.length(); 29 | int[] rst = new int[len]; 30 | int prev = -0x3f3f3f3f; 31 | 32 | // left to right 33 | for (int i = 0; i < len; i++) { 34 | if (S.charAt(i) == C) { 35 | prev = i; 36 | } 37 | rst[i] = i - prev; 38 | } 39 | 40 | // right to left 41 | prev = 0x3f3f3f3f; 42 | for (int i = len-1; i >= 0; i--) { 43 | if (S.charAt(i) == C) { 44 | prev = i; 45 | } 46 | // get the smaller one of the two answers 47 | rst[i] = Math.min(rst[i], prev - i); 48 | } 49 | 50 | return rst; 51 | } 52 | } -------------------------------------------------------------------------------- /Shortest Path in Binary Matrix/Shortest Path in Binary Matrix.py: -------------------------------------------------------------------------------- 1 | ''' 2 | In an N by N square grid, each cell is either empty (0) or blocked (1). 3 | A clear path from top-left to bottom-right has length k if and only if it is composed of cells C_1, C_2, ..., C_k such that: 4 | Adjacent cells C_i and C_{i+1} are connected 8-directionally (ie., they are different and share an edge or corner) 5 | C_1 is at location (0, 0) (ie. has value grid[0][0]) 6 | C_k is at location (N-1, N-1) (ie. has value grid[N-1][N-1]) 7 | If C_i is located at (r, c), then grid[r][c] is empty (ie. grid[r][c] == 0). 8 | Return the length of the shortest such clear path from top-left to bottom-right. If such a path does not exist, return -1. 9 | 10 | Example 1: 11 | Input: [[0,1],[1,0]] 12 | Output: 2 13 | 14 | Example 2: 15 | Input: [[0,0,0],[1,1,0],[1,1,0]] 16 | Output: 4 17 | 18 | Note: 19 | 1. 1 <= grid.length == grid[0].length <= 100 20 | 2. grid[r][c] is 0 or 1 21 | ''' 22 | 23 | # Approach: BFS 24 | # 解法详解参考同名 java 文件 25 | class Solution: 26 | def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int: 27 | n = len(grid) 28 | if grid[0][0] == 1 or grid[n - 1][n - 1] == 1: 29 | return -1 30 | 31 | # row, column, step 32 | queue = [[0, 0, 1]] 33 | for r, c, step in queue: 34 | if r == n - 1 and c == n - 1: 35 | return step 36 | for i, j in [[-1, 0], [-1, 1], [0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1]]: 37 | nextR, nextC = r + i, c + j 38 | if 0 <= nextR < n and 0 <= nextC < n and grid[nextR][nextC] == 0: 39 | queue.append([nextR, nextC, step + 1]) 40 | grid[nextR][nextC] = 2 41 | return -1 42 | -------------------------------------------------------------------------------- /Single Element in a Sorted Array.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a sorted array consisting of only integers where every element appears twice except for one element which appears once. 3 | Find this single element that appears only once. 4 | 5 | Example 1: 6 | Input: [1,1,2,3,3,4,4,8,8] 7 | Output: 2 8 | Example 2: 9 | Input: [3,3,7,7,10,11,11] 10 | Output: 10 11 | 12 | Note: Your solution should run in O(log n) time and O(1) space. 13 | */ 14 | 15 | /** 16 | * Approach: Binary Search 17 | * LintCode 上的 Single Number IV 换了个问法罢了。 18 | * 实质就在于: 19 | * 1. 所有相同的元素都是相邻的 20 | * 2. 重复元素出现次数必定为 2 次 21 | * 22 | * 具体解析可以参考: 23 | * https://github.com/cherryljr/LintCode/blob/master/Single%20Number%20IV.java 24 | * https://www.youtube.com/watch?v=uJa9Q-05JxY 25 | */ 26 | class Solution { 27 | public int singleNonDuplicate(int[] nums) { 28 | int left = 0, right = nums.length - 1; 29 | while (left < right) { 30 | int mid = left + ((right - left) >> 1); 31 | int index = mid ^ 1; 32 | if (nums[mid] == nums[index]) { 33 | left = mid + 1; 34 | } else { 35 | right = mid; 36 | } 37 | } 38 | return nums[left]; 39 | } 40 | } -------------------------------------------------------------------------------- /Smallest Subsequence of Distinct Characters/Smallest Subsequence of Distinct Characters.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Return the lexicographically smallest subsequence of text 3 | that contains all the distinct characters of text exactly once. 4 | 5 | Example 1: 6 | Input: "cdadabcc" 7 | Output: "adbc" 8 | 9 | Example 2: 10 | Input: "abcd" 11 | Output: "abcd" 12 | 13 | Example 3: 14 | Input: "ecbacba" 15 | Output: "eacb" 16 | 17 | Example 4: 18 | Input: "leetcode" 19 | Output: "letcod" 20 | 21 | Note: 22 | 1. 1 <= text.length <= 1000 23 | 2. text consists of lowercase English letters. 24 | ''' 25 | 26 | # Approach: Monotonic Stack 27 | # 时间复杂度:O(n) 28 | # 空间复杂度:O(n) 29 | # 解法详解参考同名 java 文件 30 | class Solution: 31 | def smallestSubsequence(self, text: str) -> str: 32 | lastIndex = {c : i for i, c in enumerate(text)} 33 | stack = [] 34 | for i, c in enumerate(text): 35 | if c in stack: continue 36 | while stack and stack[-1] > c and lastIndex[stack[-1]] > i: 37 | stack.pop() 38 | stack.append(c) 39 | return "".join(stack) -------------------------------------------------------------------------------- /String Without AAA or BBB.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given two integers A and B, return any string S such that: 3 | 4 | S has length A + B and contains exactly A 'a' letters, and exactly B 'b' letters; 5 | The substring 'aaa' does not occur in S; 6 | The substring 'bbb' does not occur in S. 7 | 8 | Example 1: 9 | Input: A = 1, B = 2 10 | Output: "abb" 11 | Explanation: "abb", "bab" and "bba" are all correct answers. 12 | 13 | Example 2: 14 | Input: A = 4, B = 1 15 | Output: "aabaa" 16 | 17 | Note: 18 | 1. 0 <= A <= 100 19 | 2. 0 <= B <= 100 20 | 3. It is guaranteed such an S exists for the given A and B. 21 | */ 22 | 23 | /** 24 | * Approach: Greedy 25 | * 这里使用的是一个贪心的解法。 26 | * 因为保证解是存在的,所以我们可以尽量地在结果中 append 数量较多的那个字符。 27 | * 当两者字符一样多的话,那么就交替地各放一个即可。 28 | * 比如 'a' 比 'b' 多,那么我们就先放 "aab",直到二者数量相等了,在交替放入 "ab" 29 | * 直到个数满足要求。 30 | * 31 | * Time Complexity: O(m + n) 32 | * Space Complexity: O(1) 33 | */ 34 | class Solution { 35 | public String strWithout3a3b(int A, int B) { 36 | StringBuilder res = new StringBuilder(); 37 | // a 代表字母个数较多的字母; b 代表字母个数较少的字母; 38 | char a = 'a', b = 'b'; 39 | // countA 代表字母数较多的元素的个数; countB 代表字字母数较少的元素的个数 40 | int countA = A, countB = B; 41 | if (B > A) { 42 | countA = B; 43 | countB = A; 44 | a = 'b'; 45 | b = 'a'; 46 | } 47 | 48 | while (countA > 0 || countB > 0) { 49 | if (countA > 0) { 50 | res.append(a); 51 | countA--; 52 | } 53 | if (countA > countB) { 54 | res.append(a); 55 | countA--; 56 | } 57 | if (countB > 0) { 58 | res.append(b); 59 | countB--; 60 | } 61 | } 62 | 63 | return res.toString(); 64 | } 65 | } -------------------------------------------------------------------------------- /Subarray Sum Equals K.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers and an integer k, you need to find 3 | the total number of continuous subarrays whose sum equals to k. 4 | 5 | Example 1: 6 | Input:nums = [1,1,1], k = 2 7 | Output: 2 8 | 9 | Note: 10 | The length of the array is in range [1, 20,000]. 11 | The range of numbers in the array is [-1000, 1000] and the range of the integer k is [-1e7, 1e7]. 12 | */ 13 | 14 | /** 15 | * Approach: PreSum + HashMap 16 | * 这道题目与 Maximum Size Subarray Sum Equals k 十分类似。 17 | * https://github.com/cherryljr/LintCode/blob/master/Maximum%20Size%20Subarray%20Sum%20Equals%20k.java 18 | * 我们依旧引入 preSum 来优化我们的时间复杂度,并将其储存在 map 中。 19 | * 根据题目要求,在这里 key 为 preSum, value 为 preSum 出现的次数(因为我们要求的是次数,而不再是长度)。 20 | * 当 map.containsKey(preSum-k) 时,说明在 i 之前已经累加出现过 map.get(preSum-k) 次 k 的值。 21 | * 因此 count += map.get(preSum-k). 22 | * 同时将 preSum 与其对应的 index 加入到 map 中。 23 | * 注意: 24 | * 这里对于 map 的初始化为 (0, 1) 这意味着,当一个数都没有添加的时候,preSum 为 0,并且已经出现了 1 次。 25 | * (对于 map 等参数的初始化,都必须根据题目要求) 26 | * 27 | * 时间复杂度为:O(n) 28 | * 空间辅助度为:O(n) 29 | * 30 | * More Methods: https://leetcode.com/problems/subarray-sum-equals-k/solution/ 31 | */ 32 | class Solution { 33 | public int subarraySum(int[] nums, int k) { 34 | if (nums == null || nums.length == 0) { 35 | return -1; 36 | } 37 | 38 | Map map = new HashMap<>(); 39 | // Initailize the values 40 | map.put(0, 1); // very important 41 | int preSum = 0; 42 | int count = 0; 43 | 44 | for (int i = 0; i < nums.length; i++) { 45 | preSum += nums[i]; 46 | if (map.containsKey(preSum - k)) { 47 | count += map.get(preSum - k); 48 | } 49 | map.put(preSum, map.getOrDefault(preSum, 0) + 1); 50 | } 51 | 52 | return count; 53 | } 54 | } -------------------------------------------------------------------------------- /Sum of Root To Leaf Binary Numbers/Sum of Root To Leaf Binary Numbers.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Given a binary tree, each node has value 0 or 1. Each root-to-leaf path represents a binary number starting with the most significant bit. 3 | For example, if the path is 0 -> 1 -> 1 -> 0 -> 1, then this could represent 01101 in binary, which is 13. 4 | 5 | For all leaves in the tree, consider the numbers represented by the path from the root to that leaf. 6 | 7 | Return the sum of these numbers. 8 | 9 | Example 1: 10 | Input: [1,0,1,0,1,0,1] 11 | Output: 22 12 | Explanation: (100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22 13 | 14 | Note: 15 | 1. The number of nodes in the tree is between 1 and 1000. 16 | 2. node.val is 0 or 1. 17 | 3. The answer will not exceed 2^31 - 1. 18 | ''' 19 | 20 | # Approach: Divide and Conquer (Top-Down DFS) 21 | # 解法详解参考同名 java 文件 22 | # 时间复杂度:O(n) 23 | # 空间复杂度:O(logn) 24 | 25 | # Definition for a binary tree node. 26 | # class TreeNode: 27 | # def __init__(self, x): 28 | # self.val = x 29 | # self.left = None 30 | # self.right = None 31 | class Solution: 32 | def sumRootToLeaf(self, root: TreeNode, prevSum = 0) -> int: 33 | if not root: return 0 34 | prevSum = prevSum << 1 | root.val 35 | if not root.left and not root.right: 36 | return prevSum 37 | return self.sumRootToLeaf(root.left, prevSum) + self.sumRootToLeaf(root.right, prevSum) 38 | -------------------------------------------------------------------------------- /Sum of Square Numbers.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a non-negative integer c, your task is to decide whether there're two integers a and b such that a2 + b2 = c. 3 | 4 | Example 1: 5 | Input: 5 6 | Output: True 7 | Explanation: 1 * 1 + 2 * 2 = 5 8 | 9 | Example 2: 10 | Input: 3 11 | Output: False 12 | */ 13 | 14 | /** 15 | * Approach: Mathematics + Two Pointers 16 | * 是一道 Brute Force 的题目,需要注意判断范围从 0~sqrt(c) 即可。 17 | * 18 | * 时间复杂度:O(sqrt(c)) 19 | * 空间复杂度:O(1) 20 | */ 21 | class Solution { 22 | public boolean judgeSquareSum(int c) { 23 | int left = 0, right = (int) Math.sqrt(c); 24 | while (left <= right) { 25 | if (left * left + right * right == c) { 26 | return true; 27 | } else if (left * left + right * right < c) { 28 | left++; 29 | } else { 30 | right--; 31 | } 32 | } 33 | return false; 34 | } 35 | } -------------------------------------------------------------------------------- /Sum of Subarray Minimums.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given an array of integers A, find the sum of min(B), 3 | where B ranges over every (contiguous) subarray of A. 4 | Since the answer may be large, return the answer modulo 10^9 + 7. 5 | 6 | Example 1: 7 | Input: [3,1,2,4] 8 | Output: 17 9 | Explanation: Subarrays are [3], [1], [2], [4], [3,1], [1,2], [2,4], [3,1,2], [1,2,4], [3,1,2,4]. 10 | Minimums are 3, 1, 2, 4, 1, 1, 2, 1, 1, 1. Sum is 17. 11 | 12 | Note: 13 | 1 <= A.length <= 30000 14 | 1 <= A[i] <= 30000 15 | */ 16 | 17 | /** 18 | * Approach: Monotonic Stack 19 | * 这道题目与 最小数字乘以区间和的最大值 这道题目非常的类似。说是变形题也不为过。 20 | * 根据题目的数据量可知算法的时间复杂度应该在 O(nlogn) 级别以下。 21 | * 这里我们需要确定以当前数 A[i] 作为最小值的 subarray 的范围。 22 | * 然后计算这些 subarray 有多少个,如果是 n 个的话, 23 | * 那么 A[i] 对于答案的贡献就是 A[i] * n. 24 | * 25 | * 那么对于寻找 A[i] 左边/右边 小于 A[i] 的第一个元素, 26 | * 毫无疑问就是使用到了我们 单调栈 了。 27 | * 同样的栈中存储数组的下标即可。 28 | * 然后我们就可以依次来划分以 A[i] 作为最小值的 subarray 的左右边界了。 29 | * 然后将 左边界可能的划分位置 * 右边界可能的划分位置 * A[i] 就是结果了。 30 | * 31 | * 时间复杂度:O(n) 32 | * 空间复杂度:O(n) 33 | * 34 | * 最小数字乘以区间和的最大值: 35 | * https://github.com/cherryljr/NowCoder/blob/master/%E6%9C%80%E5%B0%8F%E6%95%B0%E5%AD%97%E4%B9%98%E4%BB%A5%E5%8C%BA%E9%97%B4%E5%92%8C%E7%9A%84%E6%9C%80%E5%A4%A7%E5%80%BC.java 36 | */ 37 | class Solution { 38 | private static final int MOD = 1000000007; 39 | 40 | public int sumSubarrayMins(int[] A) { 41 | long rst = 0L; 42 | Stack stack = new Stack<>(); 43 | for (int i = 0; i <= A.length; i++) { 44 | int curr = i == A.length ? -1 : A[i]; 45 | while (!stack.isEmpty() && A[stack.peek()] >= curr) { 46 | // 需要被 pop() 出来元素的下标 47 | int index = stack.pop(); 48 | // 以 A[index] 为最小值的 subarray 左边界为 A[stack.peek()] 右边界为 A[i] 49 | if (stack.isEmpty()) { 50 | rst = (rst + A[index] * (index + 1) * (i - index)) % MOD; 51 | } else { 52 | rst = (rst + A[index] * (index - stack.peek()) * (i - index)) % MOD; 53 | } 54 | } 55 | stack.push(i); 56 | } 57 | return (int)rst; 58 | } 59 | } -------------------------------------------------------------------------------- /Surface Area of 3D Shapes.java: -------------------------------------------------------------------------------- 1 | /* 2 | On a N * N grid, we place some 1 * 1 * 1 cubes. 3 | Each value v = grid[i][j] represents a tower of v cubes placed on top of grid cell (i, j). 4 | Return the total surface area of the resulting shapes. 5 | 6 | Example 1: 7 | Input: [[2]] 8 | Output: 10 9 | 10 | Example 2: 11 | Input: [[1,2],[3,4]] 12 | Output: 34 13 | 14 | Example 3: 15 | Input: [[1,0],[0,2]] 16 | Output: 16 17 | 18 | Example 4: 19 | Input: [[1,1,1],[1,0,1],[1,1,1]] 20 | Output: 32 21 | 22 | Example 5: 23 | Input: [[2,2,2],[2,1,2],[2,2,2]] 24 | Output: 46 25 | 26 | Note: 27 | 1 <= N <= 50 28 | 0 <= grid[i][j] <= 50 29 | */ 30 | 31 | /** 32 | * Approach: Mathematics 33 | * 计算岛屿面积(表面积)的 3D 版本。 34 | * 同样根据求表面积的方法进行数学分析即可。 35 | * 36 | * 当 grid[i][j] > 0 时,说明该位置上存在一个 tower,因此首先加上 上表面 和 下表面 的面积 2. 37 | * 然后在分析旁边四个面的面积。 38 | * 我们不妨先将它们加起来,当存在两个相邻 tower 的时候,相邻部分的面积因为重合的原因需要减去。 39 | * 那么减去的面积就是 2 * Math.min(grid[i][j], neigh) 40 | * 这里 乘以2 是因为这部分的面积我们计算了两次,但是结果中它是不存在的。 41 | * 42 | * 时间复杂度:O(n^2) 43 | * 空间复杂度:O(1) 44 | * 45 | * 该问题的 2D 版本: 46 | * Island Perimeter: 47 | * https://github.com/cherryljr/LeetCode/blob/master/Island%20Perimeter.java 48 | */ 49 | class Solution { 50 | public int surfaceArea(int[][] grid) { 51 | if (grid == null || grid.length == 0) { 52 | return 0; 53 | } 54 | 55 | int result = 0; 56 | for (int i = 0; i < grid.length; i++) { 57 | for (int j = 0; j < grid[0].length; j++) { 58 | // 如果该位置存在 tower 59 | if (grid[i][j] > 0) { 60 | result += 2 + 4 * grid[i][j]; 61 | } 62 | // 减去重合部分的面积 63 | if (i > 0) { 64 | result -= Math.min(grid[i][j], grid[i - 1][j]) * 2; 65 | } 66 | if (j > 0) { 67 | result -= Math.min(grid[i][j], grid[i][j - 1]) * 2; 68 | } 69 | } 70 | } 71 | return result; 72 | } 73 | } -------------------------------------------------------------------------------- /Swap Nodes in Pairs.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a linked list, swap every two adjacent nodes and return its head. 3 | You may not modify the values in the list's nodes, only nodes itself may be changed. 4 | 5 | Example: 6 | Given 1->2->3->4, you should return the list as 2->1->4->3. 7 | */ 8 | 9 | /** 10 | * Approach: Reverse LinkedList (Dummy Node and Previous Node) 11 | * 涉及到链表节点交换的操作,如果不熟悉的话,最好画一下图。 12 | * 不仅可以帮助理清楚思路,在代码实现上也可以避免错误。 13 | * 同时因为本题的链表经过处理之后,headNode 就无法再确定了,对此可以使用 Dummy Node 来解决。 14 | * 这个技巧在 Reverse LinkedList 上是特别常见的。 15 | * 16 | * 剩下的其他方面可以参见代码注释即可。 17 | * 在实现思路上还是相当明确的,属于考察链表的操作能力和代码能力的题目。 18 | */ 19 | 20 | /** 21 | * Definition for singly-linked list. 22 | * public class ListNode { 23 | * int val; 24 | * ListNode next; 25 | * ListNode(int x) { val = x; } 26 | * } 27 | */ 28 | class Solution { 29 | public ListNode swapPairs(ListNode head) { 30 | ListNode dummyNode = new ListNode(0); 31 | // 涉及到 reverse 操作,因此首先需要一个 previous node 来做跟踪 32 | ListNode prev = dummyNode; 33 | prev.next = head; 34 | 35 | // 为了更加清楚地说明,这里以 0->1->2->3 为例说明 (0为prevNode) 36 | while (prev.next != null && prev.next.next != null) { 37 | ListNode first = prev.next; // first = 1 38 | ListNode second = prev.next.next; // second = 2 39 | first.next = second.next; // 1->3 40 | second.next = first; // 2->1 41 | // 至此已经完成了一个 pair 的翻转 42 | prev.next = second; // 将 0->2->1-3,作用为将两个 pair 连接起来 43 | prev = first; // 将 prevNode 向后移动, prev = 1 44 | } 45 | 46 | return dummyNode.next; 47 | } 48 | } -------------------------------------------------------------------------------- /Symmetric Tree.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). 3 | For example, this binary tree [1,2,2,3,4,4,3] is symmetric: 4 | 1 5 | / \ 6 | 2 2 7 | / \ / \ 8 | 3 4 4 3 9 | But the following [1,2,2,null,3,null,3] is not: 10 | 1 11 | / \ 12 | 2 2 13 | \ \ 14 | 3 3 15 | 16 | Note: 17 | Bonus points if you could solve it both recursively and iteratively. 18 | */ 19 | 20 | /** 21 | * Approach: Divide and Conquer 22 | * 这道题目刚刚看上去是考察 单棵树 的问题。 23 | * 但是因为考察的是判断这棵树是否是对称的,所以很显然我们可以将它转换成一道 两棵树 之间关系的题目。 24 | * 只不过这里的两棵树都是它本身。并且因为这里不涉及到数据的修改,所以不必对数据进行复制。 25 | * 之后我们只需要按照 Divide and Conquer 的做法去处理其左右子树即可。 26 | * 27 | * 时间复杂度:O(n) 28 | * 空间复杂度:O(h) 29 | * 30 | * Divide and Conquer 在 Tree 中的应用与模板总结可以参见: 31 | * https://github.com/cherryljr/LeetCode/blob/master/Same%20Tree.java 32 | */ 33 | 34 | /** 35 | * Definition for a binary tree node. 36 | * public class TreeNode { 37 | * int val; 38 | * TreeNode left; 39 | * TreeNode right; 40 | * TreeNode(int x) { val = x; } 41 | * } 42 | */ 43 | class Solution { 44 | public boolean isSymmetric(TreeNode root) { 45 | if (root == null) { 46 | return true; 47 | } 48 | return mirror(root, root); 49 | } 50 | 51 | private boolean mirror(TreeNode root1, TreeNode root2) { 52 | // 递归的终止条件 53 | if (root1 == null && root2 == null) { 54 | return true; 55 | } 56 | if (root1 == null || root2 == null || root1.val != root2.val) { 57 | return false; 58 | } 59 | 60 | // Divide 61 | boolean left = mirror(root1.left, root2.right); 62 | boolean right = mirror(root1.right, root2.left); 63 | // Conquer 64 | return left && right; 65 | } 66 | } -------------------------------------------------------------------------------- /Two City Scheduling/Two City Scheduling.py: -------------------------------------------------------------------------------- 1 | ''' 2 | There are 2N people a company is planning to interview. The cost of flying the i-th person to city A is costs[i][0], 3 | and the cost of flying the i-th person to city B is costs[i][1]. 4 | 5 | Return the minimum cost to fly every person to a city such that exactly N people arrive in each city. 6 | 7 | Example 1: 8 | Input: [[10,20],[30,200],[400,50],[30,20]] 9 | Output: 110 10 | Explanation: 11 | The first person goes to city A for a cost of 10. 12 | The second person goes to city A for a cost of 30. 13 | The third person goes to city B for a cost of 50. 14 | The fourth person goes to city B for a cost of 20. 15 | The total minimum cost is 10 + 30 + 50 + 20 = 110 to have half the people interviewing in each city. 16 | 17 | Note: 18 | 1. 1 <= costs.length <= 100 19 | 2. It is guaranteed that costs.length is even. 20 | 3. 1 <= costs[i][0], costs[i][1] <= 1000 21 | ''' 22 | 23 | # Approach: Greedy (Sorting) 24 | # 时间复杂度:O(nlogn) 25 | # 空间复杂度:O(1) 26 | # 解法详解参考同名 java 文件 27 | class Solution: 28 | def twoCitySchedCost(self, costs: List[List[int]]) -> int: 29 | # 利用 [0,N/2] 整除 N/2 的结果均为 0,[N/2+1, N] 整除 N/2 的结果均为 1 的特点,完成1行代码的压缩 30 | return sum([v[i // (len(costs)//2)] for i, v in enumerate(sorted(costs, key=lambda cost: cost[1] - cost[0], reverse=True))]) -------------------------------------------------------------------------------- /Ugly Number.java: -------------------------------------------------------------------------------- 1 | /* 2 | Write a program to check whether a given number is an ugly number. 3 | Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. 4 | 5 | Example 1: 6 | Input: 6 7 | Output: true 8 | Explanation: 6 = 2 × 3 9 | 10 | Example 2: 11 | Input: 8 12 | Output: true 13 | Explanation: 8 = 2 × 2 × 2 14 | 15 | Example 3: 16 | Input: 14 17 | Output: false 18 | Explanation: 14 is not ugly since it includes another prime factor 7. 19 | 20 | Note: 21 | 1. 1 is typically treated as an ugly number. 22 | 2. Input is within the 32-bit signed integer range: [−231, 231 − 1]. 23 | */ 24 | 25 | /** 26 | * Approach: Mathematics 27 | * 丑数的定义为 只包含质因子 2, 3, 5 的正整数。 28 | * 因此我们只需要将判断的数不断不断地除以 2, 3, 5 29 | * (如果余数为 0 的话),然后判断结果是否能被整除即可。 30 | * 31 | * 时间复杂度:O(log2(N) + logn3(N) + log5(N)) 32 | * 空间复杂度:O(1) 33 | * 34 | * Reference: https://www.bilibili.com/video/av31569881 35 | */ 36 | class Solution { 37 | private static final int[] factors = {2, 3, 5}; 38 | 39 | public boolean isUgly(int num) { 40 | if (num == 0) { 41 | return false; 42 | } 43 | for (int factor : factors) { 44 | while (num % factor == 0) { 45 | num /= factor; 46 | } 47 | } 48 | return num == 1; 49 | } 50 | } -------------------------------------------------------------------------------- /Uncrossed Lines/Uncrossed Lines.java: -------------------------------------------------------------------------------- 1 | /* 2 | We write the integers of A and B (in the order they are given) on two separate horizontal lines. 3 | Now, we may draw a straight line connecting two numbers A[i] and B[j] as long as A[i] == B[j], 4 | and the line we draw does not intersect any other connecting (non-horizontal) line. 5 | 6 | Return the maximum number of connecting lines we can draw in this way. 7 | 8 | Example 1: 9 | https://leetcode.com/problems/uncrossed-lines/ 10 | Input: A = [1,4,2], B = [1,2,4] 11 | Output: 2 12 | Explanation: We can draw 2 uncrossed lines as in the diagram. 13 | We cannot draw 3 uncrossed lines, because the line from A[1]=4 to B[2]=4 will intersect the line from A[2]=2 to B[1]=2. 14 | 15 | Example 2: 16 | Input: A = [2,5,1,2,5], B = [10,5,2,1,5,2] 17 | Output: 3 18 | 19 | Example 3: 20 | Input: A = [1,3,7,1,7,5], B = [1,9,2,5,1] 21 | Output: 2 22 | 23 | Note: 24 | 1. 1 <= A.length <= 500 25 | 2. 1 <= B.length <= 500 26 | 3. 1 <= A[i], B[i] <= 2000 27 | */ 28 | 29 | /** 30 | * Approach: Sequence DP (Same as Longest Common SubSequence) 31 | * 这道问题其实是 LCS 问题的一个包装。 32 | * 题目给了两个数组 A[], B[],要求我们将两个数组中相等的元素相连,并且要求连线不得相交。 33 | * 我们可以发现 A[], B[] 中相连的元素必定是 A[], B[] 的子序列。(这样就能够保证连线不会相交) 34 | * 因此问题到这里就转换成了求数组 A[], B[] 的最长公共子序列。 35 | * 典型的 DP 问题了...这里就不再赘述,不清楚的可以参考下方给出的链接。 36 | * 37 | * 时间复杂度:O(M * N) 38 | * 空间复杂度:O(M * N) 39 | * 40 | * Reference: 41 | * https://github.com/cherryljr/LintCode/blob/master/Longest%20Common%20Subsequence.java 42 | */ 43 | class Solution { 44 | public int maxUncrossedLines(int[] A, int[] B) { 45 | int[][] dp = new int[A.length + 1][B.length + 1]; 46 | for (int i = 1; i <= A.length; i++) { 47 | for (int j = 1; j <= B.length; j++) { 48 | if (A[i - 1] == B[j - 1]) { 49 | dp[i][j] = dp[i - 1][j - 1] + 1; 50 | } else { 51 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 52 | } 53 | } 54 | } 55 | return dp[A.length][B.length]; 56 | } 57 | } -------------------------------------------------------------------------------- /Uncrossed Lines/Uncrossed Lines.py: -------------------------------------------------------------------------------- 1 | ''' 2 | We write the integers of A and B (in the order they are given) on two separate horizontal lines. 3 | Now, we may draw a straight line connecting two numbers A[i] and B[j] as long as A[i] == B[j], 4 | and the line we draw does not intersect any other connecting (non-horizontal) line. 5 | 6 | Return the maximum number of connecting lines we can draw in this way. 7 | 8 | Example 1: 9 | https://leetcode.com/problems/uncrossed-lines/ 10 | Input: A = [1,4,2], B = [1,2,4] 11 | Output: 2 12 | Explanation: We can draw 2 uncrossed lines as in the diagram. 13 | We cannot draw 3 uncrossed lines, because the line from A[1]=4 to B[2]=4 will intersect the line from A[2]=2 to B[1]=2. 14 | 15 | Example 2: 16 | Input: A = [2,5,1,2,5], B = [10,5,2,1,5,2] 17 | Output: 3 18 | 19 | Example 3: 20 | Input: A = [1,3,7,1,7,5], B = [1,9,2,5,1] 21 | Output: 2 22 | 23 | Note: 24 | 1. 1 <= A.length <= 500 25 | 2. 1 <= B.length <= 500 26 | 3. 1 <= A[i], B[i] <= 2000 27 | ''' 28 | 29 | # Approach: Sequence DP (Same as Longest Common SubSequence) 30 | # 时间复杂度:O(M * N) 31 | # 空间复杂度:O(M * N) 32 | # 解法详解参考同名 java 文件 33 | class Solution: 34 | def maxUncrossedLines(self, A: List[int], B: List[int]) -> int: 35 | m, n = len(A) + 1, len(B) + 1 36 | dp = [[0] * n for _ in range(m)] 37 | for i in range(1, m): 38 | for j in range(1, n): 39 | # dp[i][j] = max(dp[i - 1][j - 1] + (A[i - 1] == B[j - 1]), dp[i - 1][j], dp[i][j - 1]) 40 | if A[i - 1] == B[j - 1]: 41 | dp[i][j] = dp[i - 1][j - 1] + 1 42 | else: 43 | dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) 44 | return dp[m - 1][n - 1] 45 | -------------------------------------------------------------------------------- /Unique Binary Search Trees.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given n, how many structurally unique BST's (binary search trees) that store values 1 ... n? 3 | 4 | Example: 5 | Input: 3 6 | Output: 5 7 | Explanation: 8 | Given n = 3, there are a total of 5 unique BST's: 9 | 1 3 3 2 1 10 | \ / / / \ \ 11 | 3 2 1 1 3 2 12 | / / \ \ 13 | 2 1 2 3 14 | */ 15 | 16 | /** 17 | * Approach: Catalan Number 18 | * 典型卡特兰数的应用问题... 19 | * 20 | * Reference: 21 | * 卡特兰数推理过程介绍:https://youtu.be/YDf982Lb84o 22 | * 卡特兰数的应用:http://www-math.mit.edu/~rstan/ec/catalan.pdf 23 | * 类似的问题:https://github.com/cherryljr/NowCoder/blob/master/Game%20of%20Connections.java 24 | */ 25 | class Solution { 26 | public int numTrees(int n) { 27 | // int[] ans = new int[n + 1]; 28 | // ans[0] = 1; 29 | // ans[1] = 1; 30 | // for (int i = 2; i <= n; i++) { 31 | // for (int j = 0; j < i; j++) { 32 | // ans[i] += ans[j] * ans[i - j - 1]; 33 | // } 34 | // } 35 | // return ans[n]; 36 | 37 | // 使用以下递推式时,考虑到精度问题,最好使用BigInteger来进行计算 38 | // 这里能过是因为题目的 test case 比较小,范围只有int 39 | double[] ans = new double[n + 1]; 40 | ans[0] = 1; 41 | for (int i = 1; i <= n; i++) { 42 | ans[i] = ans[i - 1] * (4 * i - 2) / (i + 1); 43 | } 44 | return (int)ans[n]; 45 | } 46 | } -------------------------------------------------------------------------------- /Vaild Square.java: -------------------------------------------------------------------------------- 1 | 题目要求我们判断四个点能否组成正方形,那么正方形有哪些特征呢。 2 | 我们容易想到,正方形四条边长度都相等,并且两条对角线长度也相等. 3 | 所以,我们只要求出这四个点两两之间的距离,进行从小到大排序之后, 4 | 如果这四个点能构成正方形,那么前面四个数就是四条边长的长度,后面两个数为两条对角线的长度, 5 | 因此我们只需要判断前四个数以及后两个数它们是否相等即可。 6 | 这题为避免四个点重叠,因此我们还需要判断一下对角线长度是否大于边长即可。 7 | 8 | /* 9 | Given the coordinates of four points in 2D space, return whether the four points could construct a square. 10 | The coordinate (x,y) of a point is represented by an integer array with two integers. 11 | 12 | Example: 13 | Input: p1 = [0,0], p2 = [1,1], p3 = [1,0], p4 = [0,1] 14 | Output: True 15 | 16 | Note: 17 | 1. All the input integers are in the range [-10000, 10000]. 18 | 2. A valid square has four equal sides with positive length and four equal angles (90-degree angles). 19 | 3. Input points have no order. 20 | */ 21 | class Solution { 22 | public boolean validSquare(int[] p1, int[] p2, int[] p3, int[] p4) { 23 | int[][] p = {{p1[0], p1[1]}, 24 | {p2[0], p2[1]}, 25 | {p3[0], p3[1]}, 26 | {p4[0], p4[1]}}; 27 | 28 | // calculate the length of four sides and diagonals, then sort them asending 29 | int[] len = new int[6]; 30 | int count = 0; 31 | for (int i = 0; i < 4; i++) { 32 | for (int j = i + 1; j < 4; j++) { 33 | len[count++] = (p[i][0] - p[j][0]) * (p[i][0] - p[j][0]) + (p[i][1] - p[j][1]) * (p[i][1] - p[j][1]); 34 | } 35 | } 36 | Arrays.sort(len); 37 | 38 | // if the four sides equals && diagonals equals && diagonals longer than sides, return true. 39 | if (len[0] == len[3] && len[4] == len[5] && len[0] < len[4]) { 40 | return true; 41 | } 42 | return false; 43 | } 44 | } -------------------------------------------------------------------------------- /Valid Anagram.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given two strings s and t, write a function to determine if t is an anagram of s. 3 | 4 | For example, 5 | s = "anagram", t = "nagaram", return true. 6 | s = "rat", t = "car", return false. 7 | 8 | Note: 9 | You may assume the string contains only lowercase alphabets. 10 | 11 | Follow up: 12 | What if the inputs contain unicode characters? How would you adapt your solution to such case? 13 | */ 14 | 15 | /* 16 | * The main idea is the same as: HashMap 17 | * It creates a size 26 int arrays as buckets for each letter in alphabet. 18 | * It increments the bucket value with String s and decrement with string t. 19 | * So if they are anagrams, all buckets should remain with initial value which is zero. 20 | * So just checking that and return 21 | * 22 | * Note: 23 | * This question is similar to: https://github.com/cherryljr/LintCode/blob/master/String%20Permutation.java 24 | * You can get more solutions and explianations in the URL. 25 | * 26 | * More Harder Related Problem: Permutation in String 27 | * https://github.com/cherryljr/LeetCode/blob/master/Permutation%20in%20String.java 28 | */ 29 | public class Solution { 30 | public boolean isAnagram(String s, String t) { 31 | int[] alphabet = new int[26]; 32 | 33 | for (int i = 0; i < s.length(); i++) { 34 | alphabet[s.charAt(i) - 'a']++; 35 | } 36 | for (int i = 0; i < t.length(); i++) { 37 | alphabet[t.charAt(i) - 'a']--; 38 | } 39 | for (int i : alphabet) { 40 | if (i != 0) { 41 | return false; 42 | } 43 | } 44 | 45 | return true; 46 | } 47 | } -------------------------------------------------------------------------------- /Valid Boomerang/Valid Boomerang.java: -------------------------------------------------------------------------------- 1 | /* 2 | A boomerang is a set of 3 points that are all distinct and not in a straight line. 3 | Given a list of three points in the plane, return whether these points are a boomerang. 4 | 5 | Example 1: 6 | Input: [[1,1],[2,3],[3,2]] 7 | Output: true 8 | 9 | Example 2: 10 | Input: [[1,1],[2,2],[3,3]] 11 | Output: false 12 | 13 | Note: 14 | 1. points.length == 3 15 | 2. points[i].length == 2 16 | 3. 0 <= points[i][j] <= 100 17 | */ 18 | 19 | /** 20 | * Approach: Mathematics (slope of 2 lines are not equal) 21 | * 题目要求三个点 各不相同 且 不在同一条直线上。即这三个点能组成一个三角形,记为ABC 22 | * 对此我们可以利用 斜率 判断三点是否共线。设: 23 | * A:Xa = p[0][0],Ya = p[0][1] 24 | * B:Xb = p[1][0],Yb = p[1][1] 25 | * C:Xc = p[2][0],Yc = p[2][1] 26 | * 任意取三角形的两条边,要求这两条直线的斜率不能相等,即 slope_AB != slope_AC 27 | * (Ya - Yb) / (Xa - Xb) != (Ya - Yc) / (Xa - Xc) 28 | * ==> (Xa - Xc) * (Ya - Yb) != (Xa - Xb) * (Ya - Yc) 29 | * 30 | * 这里对表达式进行了变换,从而利用 乘法运算 来替代 除法运算。 31 | * 原因为: 32 | * 1. 除法运算存在精确度问题,并且需要将 int 转换成 double 来进行计算,运行效率不高。 33 | * 2. 除法需要处理 斜率无穷大 和 两个点重复 的 Corner Case 不便于编码 34 | * 35 | * 时间复杂度:O(1) 36 | * 空间复杂度:O(1) 37 | */ 38 | class Solution { 39 | public boolean isBoomerang(int[][] p) { 40 | return (p[0][0] - p[2][0]) * (p[0][1] - p[1][1]) != (p[0][0] - p[1][0]) * (p[0][1] - p[2][1]); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Valid Boomerang/Valid Boomerang.py: -------------------------------------------------------------------------------- 1 | ''' 2 | A boomerang is a set of 3 points that are all distinct and not in a straight line. 3 | Given a list of three points in the plane, return whether these points are a boomerang. 4 | 5 | Example 1: 6 | Input: [[1,1],[2,3],[3,2]] 7 | Output: true 8 | 9 | Example 2: 10 | Input: [[1,1],[2,2],[3,3]] 11 | Output: false 12 | 13 | Note: 14 | 1. points.length == 3 15 | 2. points[i].length == 2 16 | 3. 0 <= points[i][j] <= 100 17 | ''' 18 | 19 | # Approach: Mathematics (slope of 2 lines are not equal) 20 | # 时间复杂度:O(1) 21 | # 空间复杂度:O(1) 22 | # 解法详解参考同名 java 文件 23 | class Solution: 24 | def isBoomerang(self, p: List[List[int]]) -> bool: 25 | return (p[0][0] - p[2][0]) * (p[0][1] - p[1][1]) != (p[0][0] - p[1][0]) * (p[0][1] - p[2][1]) -------------------------------------------------------------------------------- /Validate Stack Sequences.java: -------------------------------------------------------------------------------- 1 | /* 2 | Given two sequences pushed and popped with distinct values, 3 | return true if and only if this could have been the result of a sequence of push and pop operations on an initially empty stack. 4 | 5 | Example 1: 6 | Input: pushed = [1,2,3,4,5], popped = [4,5,3,2,1] 7 | Output: true 8 | Explanation: We might do the following sequence: 9 | push(1), push(2), push(3), push(4), pop() -> 4, 10 | push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1 11 | 12 | Example 2: 13 | Input: pushed = [1,2,3,4,5], popped = [4,3,5,1,2] 14 | Output: false 15 | Explanation: 1 cannot be popped before 2. 16 | 17 | Note: 18 | 1. 0 <= pushed.length == popped.length <= 1000 19 | 2. 0 <= pushed[i], popped[i] < 1000 20 | 3. pushed is a permutation of popped. 21 | 4. pushed and popped have distinct values. 22 | */ 23 | 24 | /** 25 | * Approach: Simulate stack operations (Using Stack) 26 | * Loop through the pushed array: 27 | * 1. Keep pushing pushed elements into stack if the top element on the stack is different from the current one of popped; 28 | * 2. Keep poping out of the top element if it is same as the current one of popped; 29 | * 3. Check if the stack is empty after loop. 30 | * 31 | * Time Complexity: O(n) 32 | * Space Complexity: O(n) 33 | */ 34 | class Solution { 35 | public boolean validateStackSequences(int[] pushed, int[] popped) { 36 | Deque stack = new ArrayDeque<>(); 37 | int index = 0; 38 | for (int num : pushed) { 39 | stack.push(num); 40 | while (!stack.isEmpty() && popped[index] == stack.peek()) { 41 | stack.pop(); 42 | index++; 43 | } 44 | } 45 | return stack.isEmpty(); 46 | } 47 | } -------------------------------------------------------------------------------- /Word Frequency.linux: -------------------------------------------------------------------------------- 1 | tr -s: truncate the string with target string, but only remaining one instance (e.g. multiple whitespaces) 2 | 3 | sort: To make the same string successive so that uniq could count the same string fully and correctly. 4 | 5 | uniq -c: uniq is used to filter out the repeated lines which are successive, -c means counting 6 | 7 | sort -r: -r means sorting in descending order 8 | 9 | awk '{ print $2, $1 }': To format the output 10 | 11 | /* 12 | Write a bash script to calculate the frequency of each word in a text file words.txt. 13 | For simplicity sake, you may assume: 14 | words.txt contains only lowercase characters and space ' ' characters. 15 | Each word must consist of lowercase characters only. 16 | Words are separated by one or more whitespace characters. 17 | 18 | For example, assume that words.txt has the following content: 19 | the day is sunny the the 20 | the sunny is is 21 | 22 | Your script should output the following, sorted by descending frequency: 23 | the 4 24 | is 3 25 | sunny 2 26 | day 1 27 | 28 | Note: 29 | Don't worry about handling ties, it is guaranteed that each word's frequency count is unique. 30 | 31 | Hint: 32 | Could you write it in one-line using Unix pipes? 33 | 34 | */ 35 | 36 | # Read from the file words.txt and output the word frequency list to stdout. 37 | cat words.txt | tr -s ' ' '\n' | sort | uniq -c | sort -r | awk '{ print $2, $1 }' --------------------------------------------------------------------------------