├── .gitignore ├── Java ├── Java.iml └── src │ └── com │ └── daily │ └── algothrim │ ├── Main.java │ ├── hashtable │ └── HashTable.java │ ├── linked │ ├── LinkedNode.java │ └── algo │ │ ├── Circle.java │ │ ├── DeleteLastN.java │ │ ├── LRU.java │ │ ├── MiddleNode.java │ │ ├── OrderMerge.java │ │ ├── Palindrome.java │ │ └── Reversal.java │ ├── lookup │ ├── BinarySearch.java │ ├── BinarySearchV1.java │ ├── BinarySearchV2.java │ ├── BinarySearchV3.java │ └── BinarySearchV4.java │ ├── queue │ └── CircleQueue.java │ ├── sort │ ├── BubbleSort.java │ ├── CountSort.java │ ├── InsertSort.java │ ├── MergeSort.java │ ├── QuickSort.java │ └── SelectSort.java │ └── stack │ ├── BackSpaceCompare.java │ ├── BaseballGame.java │ ├── Calculate.java │ ├── MinStack.java │ ├── NetGreaterElement.java │ └── ValidParenthesis.java ├── LICENSE ├── README.md ├── images ├── .DS_Store └── rouse.jpeg └── kotlin ├── kotlin.iml └── src └── com └── daily └── algothrim ├── Main.kt ├── backtracking ├── 01Backpack.kt ├── 01BackpackUpgrade.kt ├── MinDist.kt └── MinEdit.kt ├── bitmap └── BitMap.kt ├── dp ├── 01Backpack.kt ├── 01BackpackUpgrade.kt ├── MaxSameLength.kt ├── MinDist.kt ├── MinEdit.kt └── YangHuiTriangleVer.kt ├── graph ├── Graph.kt └── TopologySort.kt ├── hashtable ├── HashTable.kt └── LRU.kt ├── leetcode ├── AccountsMerge.kt ├── AddToArrayForm.kt ├── AddTwoNumbers.kt ├── AllCellsDistOrder.kt ├── Calculate.kt ├── CanCompleteCircuit.kt ├── CanPlaceFlowers.kt ├── CheckPossibility.kt ├── CheckStraightLine.kt ├── CommonChars.kt ├── Connect.kt ├── ContainsDuplicate.kt ├── CountNodes.kt ├── CountTriplets.kt ├── Decode.kt ├── EqualSubstring.kt ├── FairCandySwap.kt ├── FindCriticalAndPseudoCriticalEdges.kt ├── FindMaxAverage.kt ├── FindMaximumXOR.kt ├── FindMin.kt ├── FindTheDifference.kt ├── HasCycle.kt ├── InsertionSortList.kt ├── IsCousins.kt ├── KthLargestValue.kt ├── LeastInterval.kt ├── LengthOfLongestSubstring.kt ├── MaxNumEdgesToRemove.kt ├── MaxTurbulenceSize.kt ├── MaximumProduct.kt ├── MedianSlidingWindow.kt ├── MinCostConnectPoints.kt ├── MinWindow.kt ├── MinimumDifference.kt ├── MinimumEffortPath.kt ├── MoveZeroes.kt ├── NQueens.kt ├── NumEquivDominoPairs.kt ├── NumIslands.kt ├── NumWays.kt ├── OddEvenList.kt ├── Partition.kt ├── PivotIndex.kt ├── PredictPartyVictory.kt ├── RegionsBySlashes.kt ├── RelativeSortArray.kt ├── RemoveDuplicates.kt ├── RemoveKDigits.kt ├── ReorderList.kt ├── Search.kt ├── SortArrayByParityII.kt ├── StrangePrinter.kt ├── SubarraysWithKDistinct.kt ├── SummaryRanges.kt ├── TowSum.kt ├── Trap.kt ├── Trie.kt ├── WiggleMaxLength.kt ├── WordPattern.kt ├── XorOperation.kt ├── XorQueries.kt ├── easy │ ├── AddBinary.kt │ ├── AreAlmostEqual.kt │ ├── ClimbStairs.kt │ ├── ContainsNearbyDuplicate.kt │ ├── DeleteDuplicates.kt │ ├── Generate.kt │ ├── GetRow.kt │ ├── HammingWeight.kt │ ├── InorderTraversal.kt │ ├── InvertTree.kt │ ├── IsHappy.kt │ ├── IsIsomorphic.kt │ ├── IsPalindrome.kt │ ├── IsPalindromeForLink.kt │ ├── IsPowerOfTwo.kt │ ├── IsSameTree.kt │ ├── IsSymmetric.kt │ ├── IsValid.kt │ ├── LongestCommonPrefix.kt │ ├── MajorityElement.kt │ ├── MaxAscendingSum.kt │ ├── MergeTwoLists.kt │ ├── MyQueue.kt │ ├── MySqrt.kt │ ├── MyStack.kt │ ├── PlusOne.kt │ ├── PostorderTraversal.kt │ ├── PreorderTraversal.kt │ ├── RemoveDuplicates.kt │ ├── RemoveElement.kt │ ├── Reverse.kt │ ├── RomanToInt.kt │ ├── SearchInsert.kt │ └── SingleNumber.kt ├── hard │ ├── FindMedianSortedArrays.kt │ ├── LargestRectangleArea.kt │ ├── LongestValidParentheses.kt │ ├── MaximalRectangle.kt │ ├── MergeKLists.kt │ ├── MinDistance.kt │ └── MissingTwo.kt ├── medium │ ├── CanJump.kt │ ├── CanPartitionKSubsets.kt │ ├── CombinationSum.kt │ ├── CombinationSum2.kt │ ├── Convert.kt │ ├── CountAndSay.kt │ ├── Exist.kt │ ├── FourSum.kt │ ├── GenerateParenthesis.kt │ ├── GroupAnagrams.kt │ ├── IntToRoman.kt │ ├── IsValidSudoku.kt │ ├── Jump.kt │ ├── LetterCombinations.kt │ ├── LongestPalindrome.kt │ ├── MaxArea.kt │ ├── Merge.kt │ ├── MinPathSum.kt │ ├── MyAtoi.kt │ ├── MyPow.kt │ ├── NextPermutation.kt │ ├── Permute.kt │ ├── PermuteUnique.kt │ ├── RemoveNthFromEnd.kt │ ├── Rotate.kt │ ├── Search.kt │ ├── SearchRange.kt │ ├── SortColors.kt │ ├── SubdomainVisits.kt │ ├── Subsets.kt │ ├── SwapPairs.kt │ ├── ThreeSum.kt │ ├── ThreeSumClosest.kt │ └── UniquePaths.kt └── top150 │ ├── AddTwoNumbers.kt │ ├── AverageOfLevels.kt │ ├── BSTIterator.kt │ ├── BuildTree.kt │ ├── BuildTree2.kt │ ├── Calculate.kt │ ├── CanCompleteCircuit.kt │ ├── CanConstruct.kt │ ├── CanFinish.kt │ ├── CanJump.kt │ ├── Candy.kt │ ├── CheckInclusion.kt │ ├── ClimbStairs.kt │ ├── CloneGraph.kt │ ├── Connect.kt │ ├── ContainsNearbyDuplicate.kt │ ├── Convert.kt │ ├── CopyRandomList.kt │ ├── CountNodes.kt │ ├── DeleteDuplicates.kt │ ├── EvalRPN.kt │ ├── FindKthLargest.kt │ ├── FindMinArrowShots.kt │ ├── FindOrder.kt │ ├── FindSubstring.kt │ ├── Flatten.kt │ ├── FullJustify.kt │ ├── GameOfLife.kt │ ├── GetMinimumDifference.kt │ ├── GroupAnagrams.kt │ ├── HIndex.kt │ ├── HasCycle.kt │ ├── HasPathSum.kt │ ├── InsertSection.kt │ ├── IntToRoman.kt │ ├── InvertTree.kt │ ├── IsAnagram.kt │ ├── IsHappy.kt │ ├── IsIsomorphic.kt │ ├── IsPalindrome.kt │ ├── IsPalindromeInt.kt │ ├── IsSameTree.kt │ ├── IsSubsequence.kt │ ├── IsSymmetric.kt │ ├── IsValid.kt │ ├── IsValidBST.kt │ ├── IsValidSudoku.kt │ ├── Jump.kt │ ├── KthSmallest.kt │ ├── LRUCache.kt │ ├── LargestNumber.kt │ ├── LengthOfLastWord.kt │ ├── LengthOfLongestSubstring.kt │ ├── LongestCommonPrefix.kt │ ├── LongestCommonSubsequence.kt │ ├── LongestConsecutive.kt │ ├── LongestPalindrome.kt │ ├── LowestCommonAncestor.kt │ ├── MaxArea.kt │ ├── MaxDepth.kt │ ├── MaxPathSum.kt │ ├── MaxProfit.kt │ ├── MaxProfit2.kt │ ├── Merge.kt │ ├── MergeSection.kt │ ├── MergeTwoLists.kt │ ├── MinStack.kt │ ├── MinSubArrayLen.kt │ ├── MinWindow.kt │ ├── NumIslands.kt │ ├── Partition.kt │ ├── PermuteUnique.kt │ ├── PlusOne.kt │ ├── ProductExceptSelf.kt │ ├── RandomizedSet.kt │ ├── RemoveNthFromEnd.kt │ ├── ReverseBetween.kt │ ├── ReverseKGroup.kt │ ├── ReverseWords.kt │ ├── RightSideView.kt │ ├── RomanToInt.kt │ ├── Rotate.kt │ ├── RotateImage.kt │ ├── RotateRight.kt │ ├── SearchMatrix.kt │ ├── SetZeroes.kt │ ├── SimplifyPath.kt │ ├── Solve.kt │ ├── SpiralOrder.kt │ ├── StrStr.kt │ ├── SumNumbers.kt │ ├── SummaryRanges.kt │ ├── ThreeSum.kt │ ├── Trap.kt │ ├── TwoSum.kt │ ├── TwoSum0.kt │ ├── WordPattern.kt │ └── ZigzagLevelOrder.kt ├── linked ├── LinkedNode.kt └── algo │ ├── Circle.kt │ ├── DeleteLastN.kt │ ├── LRU.kt │ ├── MiddleNode.kt │ ├── OrderMerge.kt │ ├── Palindrome.kt │ └── Reversal.kt ├── lookup ├── BinarySearch.kt ├── BinarySearchV1.kt ├── BinarySearchV2.kt ├── BinarySearchV3.kt ├── BinarySearchV4.kt └── SkipList.kt ├── queue └── CircleQueue.kt ├── recursion ├── KthGrammar.kt └── ValidTicTacToe.kt ├── sort ├── BubbleSort.kt ├── CountSort.kt ├── HeapSort.kt ├── InsertSort.kt ├── MergeSort.kt ├── QuickSort.kt └── SelectSort.kt ├── stack ├── BackSpaceCompare.kt ├── BaseballGame.kt ├── Calculate.kt ├── MinStack.kt ├── NetGreaterElement.kt └── ValidParenthesis.kt ├── sword └── Permutation.kt ├── tree ├── BinarySearchTree.kt ├── MaxDepth.kt └── TreeNode.kt └── trie ├── ACAutoMata.kt └── Trie.kt /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | out 3 | -------------------------------------------------------------------------------- /Java/Java.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/Main.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim; 2 | 3 | public class Main { 4 | } 5 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/linked/LinkedNode.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked; 2 | 3 | public class LinkedNode { 4 | public T value; 5 | public LinkedNode next; 6 | 7 | public LinkedNode(T value, LinkedNode next) { 8 | this.value = value; 9 | this.next = next; 10 | } 11 | 12 | public T getValue() { 13 | return value; 14 | } 15 | 16 | public void setValue(T value) { 17 | this.value = value; 18 | } 19 | 20 | public void setNext(LinkedNode next) { 21 | this.next = next; 22 | } 23 | 24 | public LinkedNode getNext() { 25 | return next; 26 | } 27 | 28 | public void printAll() { 29 | System.out.println(value); 30 | LinkedNode temp = next; 31 | while (temp != null) { 32 | System.out.println(temp.value); 33 | temp = temp.next; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/linked/algo/Circle.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked.algo; 2 | 3 | import com.daily.algothrim.linked.LinkedNode; 4 | 5 | /** 6 | * 链表中环的检测 7 | * 使用快慢指针,慢指针每次走一步,快指针每次走两步;当快指针等于慢指针时,说明快指针已经领先慢指针一圈,即该链表存在环。 8 | */ 9 | public class Circle { 10 | 11 | public static void main(String[] args) { 12 | LinkedNode head = new LinkedNode<>(1, null); 13 | head.setNext(new LinkedNode<>(2, 14 | new LinkedNode<>(3, 15 | new LinkedNode<>(2, 16 | new LinkedNode<>(1, head))))); 17 | System.out.println(new Circle().existCircle(head)); 18 | } 19 | 20 | /** 21 | * O(n) 22 | */ 23 | private boolean existCircle(LinkedNode linkedList) { 24 | LinkedNode fast = linkedList; 25 | LinkedNode slow = linkedList; 26 | 27 | while (fast != null && fast.getNext() != null) { 28 | fast = fast.getNext().getNext(); 29 | slow = slow.getNext(); 30 | if (fast == slow) return true; 31 | } 32 | 33 | return false; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/linked/algo/DeleteLastN.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked.algo; 2 | 3 | import com.daily.algothrim.linked.LinkedNode; 4 | 5 | /** 6 | * 删除链表倒数第 n 个结点 7 | * 使用快慢指针,快指针先走n步,然后快慢指针再一起走,直到快指针走到链表尾部,此时慢指针的位置即为链表倒数第n个结点 8 | */ 9 | public class DeleteLastN { 10 | 11 | public static void main(String[] args) { 12 | LinkedNode result = new DeleteLastN().delete(new LinkedNode<>("a", 13 | new LinkedNode<>("b", 14 | new LinkedNode<>("c", 15 | new LinkedNode<>("d", 16 | new LinkedNode<>("e", 17 | new LinkedNode<>("f", 18 | new LinkedNode<>("g", null))))))), 3); 19 | if (result != null) { 20 | result.printAll(); 21 | } 22 | } 23 | 24 | /** 25 | * O(n) 26 | */ 27 | private LinkedNode delete(LinkedNode singleLinked, int n) { 28 | if (n <= 0) return singleLinked; 29 | 30 | LinkedNode result = new LinkedNode<>("#", singleLinked); 31 | LinkedNode pre = result; 32 | LinkedNode fast = singleLinked; 33 | LinkedNode slow = singleLinked; 34 | 35 | while (fast != null && --n > 0) { 36 | fast = fast.next; 37 | } 38 | 39 | if (n != 0) throw new IllegalStateException("The size of singleLinked less than " + n); 40 | 41 | while (fast.next != null) { 42 | fast = fast.next; 43 | pre = slow; 44 | slow = slow.next; 45 | } 46 | 47 | pre.next = slow.next; 48 | 49 | return result.next; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/linked/algo/LRU.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked.algo; 2 | 3 | import com.daily.algothrim.linked.LinkedNode; 4 | 5 | /** 6 | * 使用单链表实现LRU 7 | * 1. 如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。 8 | * 2. 如果此数据没有在缓存链表中,又可以分为两种情况: 9 | * 2.1 如果此时缓存未满,则将此结点直接插入到链表的头部; 10 | * 2.2 如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部。 11 | */ 12 | public class LRU { 13 | 14 | private static final int MAX_SIZE = 5; 15 | 16 | public static void main(String[] args) { 17 | LRU lru = new LRU(); 18 | 19 | lru.cache(lru.cache(lru.cache(lru.cache(lru.cache(lru.cache(lru.cache(null, 1), 2), 3), 4), 5), 4), 6).printAll(); 20 | } 21 | 22 | /** 23 | * O(n) 24 | */ 25 | private LinkedNode cache(LinkedNode singleLinked, int item) { 26 | // 缓存为空 27 | if (singleLinked == null) return new LinkedNode<>(item, null); 28 | 29 | // 头节点 30 | if (singleLinked.value == item) return singleLinked; 31 | 32 | LinkedNode pre = singleLinked; 33 | LinkedNode temp = singleLinked; 34 | int size = 1; 35 | 36 | while (temp.next != null) { 37 | LinkedNode current = temp.next; 38 | // 存在缓存, 移到头节点 39 | if (current.value == item) { 40 | temp.next = current.next; 41 | current.next = singleLinked; 42 | return current; 43 | } 44 | size++; 45 | pre = temp; 46 | temp = temp.next; 47 | } 48 | 49 | // 缓存已满,删除尾节点 50 | if (size == MAX_SIZE) { 51 | pre.next = null; 52 | } 53 | 54 | // 将新数据移到到头节点 55 | return new LinkedNode<>(item, singleLinked); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/linked/algo/MiddleNode.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked.algo; 2 | 3 | import com.daily.algothrim.linked.LinkedNode; 4 | 5 | /** 6 | * 求链表的中间结点 7 | * 快慢指针 8 | */ 9 | public class MiddleNode { 10 | 11 | public static void main(String[] args) { 12 | new MiddleNode().middle(new LinkedNode<>("a", 13 | new LinkedNode<>("b", 14 | new LinkedNode<>("c", 15 | new LinkedNode<>("d", 16 | new LinkedNode<>("e", 17 | new LinkedNode<>("f", 18 | new LinkedNode<>("g", null)))))))).printAll(); 19 | } 20 | 21 | /** 22 | * O(n) 23 | */ 24 | private LinkedNode middle(LinkedNode singleLinked) { 25 | LinkedNode fast = singleLinked; 26 | LinkedNode slow = singleLinked; 27 | 28 | while (fast.next != null && fast.next.next != null) { 29 | fast = fast.next.next; 30 | slow = slow.next; 31 | } 32 | return slow; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/linked/algo/Reversal.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked.algo; 2 | 3 | import com.daily.algothrim.linked.LinkedNode; 4 | 5 | /** 6 | * 单链表反转 7 | */ 8 | public class Reversal { 9 | 10 | public static void main(String[] args) { 11 | new Reversal().reversal(new LinkedNode<>("a", 12 | new LinkedNode<>("b", 13 | new LinkedNode<>("c", 14 | new LinkedNode<>("d", 15 | new LinkedNode<>("a", null)))))).printAll(); 16 | } 17 | 18 | /** 19 | * O(n) 20 | */ 21 | private LinkedNode reversal(LinkedNode singleLinked) { 22 | LinkedNode result = null; 23 | LinkedNode temp; 24 | 25 | while (singleLinked != null) { 26 | temp = singleLinked.next; 27 | singleLinked.next = result; 28 | result = singleLinked; 29 | singleLinked = temp; 30 | } 31 | 32 | return result; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/lookup/BinarySearch.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup; 2 | 3 | /** 4 | * 二分查找 5 | */ 6 | public class BinarySearch { 7 | 8 | public static void main(String[] args) { 9 | int[] a = new int[]{1, 2, 4, 5, 6, 9, 29, 93, 95, 213, 741}; 10 | System.out.println(new BinarySearch().search(a, a.length, 93)); 11 | } 12 | 13 | /** 14 | * O(log n) 15 | */ 16 | private int search(int[] a, int n, int value) { 17 | int start = 0; 18 | int end = n - 1; 19 | 20 | while (end >= start) { 21 | // 注意运算优先级 22 | int mid = start + ((end - start) >> 1); 23 | if (value == a[mid]) { 24 | return mid; 25 | } else if (value < a[mid]) { 26 | end = mid - 1; 27 | } else { 28 | start = mid + 1; 29 | } 30 | } 31 | 32 | return -1; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/lookup/BinarySearchV1.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup; 2 | 3 | /** 4 | * 二分查找第一个等于给定的值 5 | */ 6 | public class BinarySearchV1 { 7 | 8 | public static void main(String[] args) { 9 | int[] a = new int[]{1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741}; 10 | System.out.println(new BinarySearchV1().search(a, a.length, 93)); 11 | } 12 | 13 | /** 14 | * O(log n) 15 | */ 16 | private int search(int[] a, int n, int value) { 17 | int start = 0; 18 | int end = n - 1; 19 | while (end >= start) { 20 | int mid = start + ((end - start) >> 1); 21 | if (a[mid] < value) { 22 | start = mid + 1; 23 | } else if (a[mid] > value) { 24 | end = mid - 1; 25 | } else { 26 | if (mid == 0 || a[mid - 1] != value) return mid; 27 | end = mid - 1; 28 | } 29 | } 30 | 31 | return -1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/lookup/BinarySearchV2.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup; 2 | 3 | /** 4 | * 二分法查找最后一个值等于给定的值 5 | */ 6 | public class BinarySearchV2 { 7 | 8 | public static void main(String[] args) { 9 | int[] a = new int[]{1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741}; 10 | System.out.println(new BinarySearchV2().search(a, a.length, 93)); 11 | } 12 | 13 | /** 14 | * O(log n) 15 | */ 16 | private int search(int[] a, int n, int value) { 17 | int start = 0; 18 | int end = n - 1; 19 | 20 | while (end >= start) { 21 | int mid = start + ((end - start) >> 1); 22 | if (a[mid] < value) { 23 | start = mid + 1; 24 | } else if (a[mid] > value) { 25 | end = mid - 1; 26 | } else { 27 | if (mid == n - 1 || a[mid + 1] != value) return mid; 28 | start = mid + 1; 29 | } 30 | } 31 | 32 | return -1; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/lookup/BinarySearchV3.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup; 2 | 3 | /** 4 | * 二分查找第一个大于等于给定的值 5 | */ 6 | public class BinarySearchV3 { 7 | 8 | public static void main(String[] args) { 9 | int[] a = new int[]{1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741}; 10 | System.out.println(new BinarySearchV3().search(a, a.length, 93)); 11 | } 12 | 13 | /** 14 | * O(log n) 15 | */ 16 | private int search(int[] a, int n, int value) { 17 | int start = 0; 18 | int end = n - 1; 19 | 20 | while (end >= start) { 21 | int mid = start + ((end - start) >> 1); 22 | if (a[mid] >= value) { 23 | if (mid == 0 || a[mid - 1] < value) return mid; 24 | end = mid + 1; 25 | } else { 26 | start = mid - 1; 27 | } 28 | } 29 | 30 | return -1; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/lookup/BinarySearchV4.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup; 2 | 3 | /** 4 | * 二分查找最后一个小于等于给定的值 5 | */ 6 | public class BinarySearchV4 { 7 | 8 | public static void main(String[] args) { 9 | int[] a = new int[]{1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741}; 10 | System.out.println(new BinarySearchV4().search(a, a.length, 93)); 11 | } 12 | 13 | /** 14 | * O(log n) 15 | */ 16 | private int search(int[] a, int n, int value) { 17 | int start = 0; 18 | int end = n - 1; 19 | 20 | while (end >= start) { 21 | int mid = start + ((end - start) >> 1); 22 | if (a[mid] <= value) { 23 | if (mid == n - 1 || a[mid + 1] > value) return mid; 24 | start = mid + 1; 25 | } else { 26 | end = mid - 1; 27 | } 28 | } 29 | return -1; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/queue/CircleQueue.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.queue; 2 | 3 | /** 4 | * 基于数组的循环队列 5 | */ 6 | public class CircleQueue { 7 | 8 | public static void main(String[] args) { 9 | CircleQueue queue = new CircleQueue(6); 10 | System.out.println(queue.enqueue("1")); 11 | System.out.println(queue.enqueue("2")); 12 | System.out.println(queue.dequeue()); 13 | System.out.println(queue.enqueue("3")); 14 | System.out.println(queue.enqueue("4")); 15 | System.out.println(queue.dequeue()); 16 | System.out.println(queue.dequeue()); 17 | System.out.println(queue.enqueue("5")); 18 | System.out.println(queue.dequeue()); 19 | System.out.println(queue.enqueue("6")); 20 | System.out.println(queue.enqueue("7")); 21 | System.out.println(queue.enqueue("8")); 22 | System.out.println(queue.enqueue("9")); 23 | System.out.println(queue.enqueue("10")); 24 | } 25 | 26 | private int n; 27 | private int head; 28 | private int tail; 29 | private String[] queue; 30 | 31 | private CircleQueue(int capacity) { 32 | n = capacity; 33 | queue = new String[n]; 34 | } 35 | 36 | private boolean enqueue(String item) { 37 | // 队满,会浪费一个存储空间 38 | if ((tail + 1) % n == head) return false; 39 | queue[tail] = item; 40 | tail = (tail + 1) % n; 41 | return true; 42 | } 43 | 44 | private String dequeue() { 45 | if (tail == head) return null; 46 | String item = queue[head]; 47 | head = (head + 1) % n; 48 | return item; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/sort/BubbleSort.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort; 2 | 3 | /** 4 | * 冒泡排序 5 | * 稳定排序 6 | * 原地排序 7 | */ 8 | public class BubbleSort { 9 | 10 | public static void main(String[] args) { 11 | int[] a = new int[]{10, 1, 4, 2, 5, 643, 654, 234, 2}; 12 | BubbleSort bubbleSort = new BubbleSort(); 13 | bubbleSort.sort(a, a.length); 14 | for (int value : a) { 15 | System.out.println(value); 16 | } 17 | 18 | System.out.println(); 19 | 20 | int[] b = new int[]{10, 1, 4, 2, 5, 643, 654, 234, 2}; 21 | bubbleSort.optSort(b, b.length); 22 | for (int value : b) { 23 | System.out.println(value); 24 | } 25 | } 26 | 27 | /** 28 | * O(n2) 29 | */ 30 | private void sort(int[] a, int n) { 31 | for (int i = 0; i < n; i++) { 32 | for (int j = 0; j < n - i - 1; j++) { 33 | if (a[j + 1] < a[j]) { 34 | int temp = a[j + 1]; 35 | a[j + 1] = a[j]; 36 | a[j] = temp; 37 | } 38 | } 39 | } 40 | } 41 | 42 | private void optSort(int[] a, int n) { 43 | for (int i = 0; i < n; i++) { 44 | boolean flag = false; 45 | for (int j = 0; j < n - i - 1; j++) { 46 | if (a[j + 1] < a[j]) { 47 | int temp = a[j + 1]; 48 | a[j + 1] = a[j]; 49 | a[j] = temp; 50 | flag = true; 51 | } 52 | } 53 | if (!flag) return; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/sort/CountSort.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort; 2 | 3 | /** 4 | * 计数排序 5 | * 稳定排序 6 | * 非原地排序 7 | */ 8 | public class CountSort { 9 | 10 | public static void main(String[] args) { 11 | int[] a = new int[]{3, 2, 4, 3, 5, 3, 2, 1, 5, 0, 0, 4, 6}; 12 | new CountSort().sort(a, a.length); 13 | for (int value : a) { 14 | System.out.println(value); 15 | } 16 | } 17 | 18 | /** 19 | * O(n) 20 | */ 21 | private void sort(int[] a, int n) { 22 | 23 | // 找到最大值 24 | int max = 0; 25 | for (int value : a) { 26 | if (max < value) max = value; 27 | } 28 | 29 | // 计数 30 | int[] count = new int[max + 1]; 31 | for (int value : a) { 32 | count[value]++; 33 | } 34 | 35 | // 求和 36 | for (int i = 1; i < count.length; i++) { 37 | count[i] = count[i] + count[i - 1]; 38 | } 39 | 40 | // 排序 41 | int[] temp = new int[n]; 42 | for (int i = n - 1; i >= 0; i--) { 43 | temp[count[a[i]] - 1] = a[i]; 44 | count[a[i]]--; 45 | } 46 | 47 | // 拷贝 48 | System.arraycopy(temp, 0, a, 0, n); 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/sort/InsertSort.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort; 2 | 3 | /** 4 | * 插入排序 5 | * 原地排序 6 | * 稳定排序 7 | */ 8 | public class InsertSort { 9 | 10 | public static void main(String[] args) { 11 | int[] a = new int[]{10, 1, 4, 2, 5, 643, 654, 234, 2}; 12 | new InsertSort().sort(a, a.length); 13 | for (int value : a) { 14 | System.out.println(value); 15 | } 16 | } 17 | 18 | 19 | /** 20 | * O(n2) 21 | */ 22 | private void sort(int[] a, int n) { 23 | for (int i = 1; i < n; i++) { 24 | int value = a[i]; 25 | int j = i - 1; 26 | for (; j >= 0; j--) { 27 | if (value < a[j]) { 28 | a[j + 1] = a[j]; 29 | } else { 30 | break; 31 | } 32 | } 33 | a[j + 1] = value; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/sort/MergeSort.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort; 2 | 3 | /** 4 | * 归并排序 5 | * 稳定排序 6 | * 不是原地排序 7 | */ 8 | public class MergeSort { 9 | 10 | public static void main(String[] args) { 11 | int[] a = new int[]{10, 1, 4, 2, 5, 643, 654, 234, 2}; 12 | new MergeSort().sort(a, 0, a.length - 1); 13 | for (int value : a) { 14 | System.out.println(value); 15 | } 16 | } 17 | 18 | /** 19 | * 时间复杂度: O(nlog n) 20 | * 空间复杂度: O(n) 21 | */ 22 | private void sort(int[] a, int start, int end) { 23 | if (start < end) { 24 | int mid = (end + start) / 2; 25 | sort(a, start, mid); 26 | sort(a, mid + 1, end); 27 | merge(a, start, end); 28 | } 29 | } 30 | 31 | private void merge(int[] a, int start, int end) { 32 | int mid = (start + end) / 2; 33 | int i = start; 34 | int j = mid + 1; 35 | int k = 0; 36 | int[] temp = new int[end - start + 1]; 37 | while (i <= mid && j <= end) { 38 | if (a[i] < a[j]) { 39 | temp[k++] = a[i++]; 40 | } else { 41 | temp[k++] = a[j++]; 42 | } 43 | } 44 | 45 | while (i <= mid) { 46 | temp[k++] = a[i++]; 47 | } 48 | 49 | while (j <= end) { 50 | temp[k++] = a[j++]; 51 | } 52 | 53 | if (temp.length >= 0) System.arraycopy(temp, 0, a, start, temp.length); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/sort/QuickSort.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort; 2 | 3 | /** 4 | * 快速排序 5 | * 不稳定排序 6 | * 原地排序 7 | */ 8 | public class QuickSort { 9 | 10 | public static void main(String[] args) { 11 | int[] a = new int[]{10, 1, 4, 2, 5, 643, 654, 234, 2}; 12 | new QuickSort().sort(a, 0, a.length - 1); 13 | for (int value : a) { 14 | System.out.println(value); 15 | } 16 | } 17 | 18 | /** 19 | * 时间复制度O(nlog n); 最好时间复杂度O(nlog n); 最坏时间复杂度O(n2) 20 | * 空间复杂度O(1) 21 | */ 22 | private void sort(int[] a, int start, int end) { 23 | if (start < end) { 24 | int mid = quick(a, start, end); 25 | sort(a, start, mid - 1); 26 | sort(a, mid + 1, end); 27 | } 28 | } 29 | 30 | private int quick(int[] a, int start, int end) { 31 | int i = start; 32 | int j = start; 33 | int pivot = a[end]; 34 | 35 | for (; j < end; j++) { 36 | if (a[j] < pivot) { 37 | int temp = a[i]; 38 | a[i] = a[j]; 39 | a[j] = temp; 40 | i++; 41 | } 42 | } 43 | 44 | int temp = a[i]; 45 | a[i] = pivot; 46 | a[end] = temp; 47 | 48 | return i; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/sort/SelectSort.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort; 2 | 3 | /** 4 | * 选择排序 5 | * 不稳定排序 6 | * 原地排序 7 | */ 8 | public class SelectSort { 9 | 10 | public static void main(String[] args) { 11 | int[] a = new int[]{10, 1, 4, 2, 5, 643, 654, 234, 2}; 12 | new SelectSort().sort(a, a.length); 13 | for (int value : a) { 14 | System.out.println(value); 15 | } 16 | } 17 | 18 | /** 19 | * O(n2) 20 | */ 21 | private void sort(int[] a, int n) { 22 | for (int i = 0; i < n; i++) { 23 | int min = a[i]; 24 | int k = i; 25 | for (int j = i + 1; j < n; j++) { 26 | if (min > a[j]) { 27 | min = a[j]; 28 | k = j; 29 | } 30 | } 31 | a[k] = a[i]; 32 | a[i] = min; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/stack/MinStack.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.stack; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。(LeetCode 155) 7 | * push(x) —— 将元素 x 推入栈中。 8 | * pop()—— 删除栈顶的元素。 9 | * top()—— 获取栈顶元素。 10 | * getMin() —— 检索栈中的最小元素。 11 | * 12 | * 使用辅助栈,每次操作都与实际栈一一对应,只不过每次push的都是实际值与辅助栈顶值中的最小值 13 | * */ 14 | public class MinStack { 15 | 16 | public static void main(String[] args) { 17 | MinStack minStack = new MinStack(); 18 | minStack.push(-2); 19 | minStack.push(0); 20 | minStack.push(-3); 21 | 22 | System.out.println(minStack.getMin()); 23 | minStack.pop(); 24 | System.out.println(minStack.top()); 25 | System.out.println(minStack.getMin()); 26 | } 27 | 28 | private Stack mStack = new Stack<>(); 29 | private Stack mMinStack = new Stack<>(); 30 | 31 | private void push(int item) { 32 | mStack.push(item); 33 | if (mMinStack.isEmpty() || item < mMinStack.peek()) { 34 | mMinStack.push(item); 35 | } else { 36 | mMinStack.push(mMinStack.peek()); 37 | } 38 | } 39 | 40 | private int pop() { 41 | mMinStack.pop(); 42 | return mStack.pop(); 43 | } 44 | 45 | private int top() { 46 | return mStack.peek(); 47 | } 48 | 49 | private int getMin() { 50 | return mMinStack.peek(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Java/src/com/daily/algothrim/stack/ValidParenthesis.java: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.stack; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * 有效的括号(LeetCode 20) 7 | * 给定一个只包括 '(',')','{','}','[',']'的字符串,判断字符串是否有效。 8 | * 有效字符串需满足: 9 | *

10 | * 左括号必须用相同类型的右括号闭合。 11 | * 左括号必须以正确的顺序闭合。 12 | * 注意空字符串可被认为是有效字符串。 13 | *

14 | * 使用栈实现,遍历字符串,遇到左括号统统入栈,遇到有括号 15 | * 1. 判断栈是否为空,为空则无效 16 | * 2. 从栈中取出一个元素,与当前右括号做匹配,不符合则无效,符合则继续向下操作 17 | * 3. 字符串遍历结束之后,判断栈是否为空,不为空则无效。 18 | */ 19 | public class ValidParenthesis { 20 | 21 | public static void main(String[] args) { 22 | System.out.println(new ValidParenthesis().solution("({[[{(([]))}]]})")); 23 | } 24 | 25 | private boolean solution(String s) { 26 | Stack stack = new Stack<>(); 27 | for (char c : s.toCharArray()) { 28 | if ('(' == c || '[' == c || '{' == c) { 29 | stack.push(c); 30 | } else { 31 | if (stack.isEmpty()) return false; 32 | char top = stack.pop(); 33 | if ((')' == c && '(' != top) || (']' == c && '[' != top) || ('}' == c && '{' != top)) return false; 34 | } 35 | } 36 | 37 | return stack.isEmpty(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idisfkj/daily_algorithm/f8f42b4e5620a43f9797be737d714a52dcaafedc/images/.DS_Store -------------------------------------------------------------------------------- /images/rouse.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/idisfkj/daily_algorithm/f8f42b4e5620a43f9797be737d714a52dcaafedc/images/rouse.jpeg -------------------------------------------------------------------------------- /kotlin/kotlin.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/Main.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim 2 | 3 | class Main { 4 | 5 | companion object { 6 | 7 | @JvmStatic 8 | fun main(args: Array) { 9 | println("main") 10 | } 11 | 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/backtracking/01Backpack.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.backtracking 2 | 3 | /** 4 | * 01-背包 5 | */ 6 | class `01Backpack` { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | `01Backpack`().apply { 12 | backtracking(0, intArrayOf(2, 2, 4, 6, 3), 5, 9, 0) 13 | println(maxW) 14 | } 15 | } 16 | } 17 | 18 | private var maxW = Int.MIN_VALUE 19 | 20 | /** 21 | * O(2^n) 22 | * w: 可装的背包最大重量 23 | * cw: 当前装的重量 24 | * item: 背包重量数组 25 | * n: 背包个数 26 | * i: 当前背包 27 | */ 28 | fun backtracking(i: Int, item: IntArray, n: Int, w: Int, cw: Int) { 29 | if (cw == w || i == n) { 30 | if (cw > maxW) maxW = cw 31 | return 32 | } 33 | backtracking(i + 1, item, n, w, cw) // 不装 34 | if (cw + item[i] <= w) { // 装 35 | backtracking(i + 1, item, n, w, cw + item[i]) 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/backtracking/01BackpackUpgrade.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.backtracking 2 | 3 | /** 4 | * 01-背包升级版,增加背包价值,求最大价值。 5 | */ 6 | class `01BackpackUpgrade` { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | `01BackpackUpgrade`().apply { 12 | backtracking(0, 5, intArrayOf(2, 2, 4, 6, 3), intArrayOf(3, 4, 8, 9, 6), 9, 0, 0) 13 | println(maxV) 14 | } 15 | } 16 | } 17 | 18 | private var maxV = Int.MIN_VALUE 19 | 20 | /** 21 | * O(2^n) 22 | * w: 可装的背包最大重量 23 | * cw: 当前装的重量 24 | * cv: 当前背包价值 25 | * item: 背包重量数组 26 | * value: 背包价值数组 27 | * n: 背包个数 28 | * i: 当前背包 29 | */ 30 | fun backtracking(i: Int, n: Int, item: IntArray, value: IntArray, w: Int, cw: Int, cv: Int) { 31 | if (i == n || cw == w) { 32 | if (maxV < cv) maxV = cv 33 | return 34 | } 35 | 36 | backtracking(i + 1, n, item, value, w, cw, cv) // 不装 37 | if (cw + item[i] <= w) { // 装 38 | backtracking(i + 1, n, item, value, w, cw + item[i], cv + value[i]) 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/backtracking/MinDist.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.backtracking 2 | 3 | /** 4 | * 棋盘最小路径 5 | * 6 | * 假设我们有一个 n 乘以 n 的矩阵 matrix[n][n]。矩阵存储的都是正整数。棋子起始位置在左上角,终止位置在右下角。 7 | * 我们将棋子从左上角移动到右下角。每次只能向右或者向下移动一位。从左上角到右下角,会有很多不同的路径可以走。 8 | * 我们把每条路径经过的数字加起来看作路径的长度。那从左上角移动到右下角的最短路径长度是多少呢? 9 | */ 10 | class MinDist { 11 | 12 | companion object { 13 | @JvmStatic 14 | fun main(args: Array) { 15 | MinDist().apply { 16 | minDist(0, 0, arrayOf( 17 | intArrayOf(1, 3, 5, 9), 18 | intArrayOf(2, 1, 3, 4), 19 | intArrayOf(5, 2, 6, 7), 20 | intArrayOf(6, 8, 4, 3) 21 | ), 4, 0) 22 | println(mMinDist) 23 | } 24 | } 25 | } 26 | 27 | private var mMinDist = Int.MAX_VALUE 28 | 29 | fun minDist(row: Int, column: Int, matrix: Array, n: Int, dist: Int) { 30 | // (row == n && column == n - 1) 最后一步是从上到下到达终点 31 | // (column == n && row == n - 1) 最后一步是从左到右达到终点 32 | if ((row == n && column == n - 1) || (column == n && row == n - 1)) { 33 | if (dist < mMinDist) mMinDist = dist 34 | return 35 | } 36 | 37 | if (row == n || column == n) return 38 | 39 | minDist(row + 1, column, matrix, n, dist + matrix[row][column]) 40 | 41 | minDist(row, column + 1, matrix, n, dist + matrix[row][column]) 42 | } 43 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/backtracking/MinEdit.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.backtracking 2 | 3 | /** 4 | * 最少编辑次数 5 | * 求把一个字符串变成另一个字符串,需要的最少编辑次数 6 | * 编辑内容包含:增加、删除、修改 7 | */ 8 | class MinEdit { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | MinEdit().apply { 14 | minEdit("mitcmu".toCharArray(), "mtacnu".toCharArray(), 0, 0, 0) 15 | println(mMinEdit) 16 | } 17 | } 18 | 19 | } 20 | 21 | private var mMinEdit = Int.MAX_VALUE 22 | 23 | fun minEdit(a: CharArray, b: CharArray, ap: Int, bp: Int, min: Int) { 24 | if (ap == a.size || bp == b.size) { 25 | var temp = min 26 | if (ap < a.size) temp += a.size - ap 27 | if (bp < b.size) temp += b.size - bp 28 | if (temp < mMinEdit) mMinEdit = temp 29 | return 30 | } 31 | 32 | // 1. 相同 a[ap+1]b[bp+1] 33 | // 2. 不相同 34 | // 2.1 a增/b 删 a[ap][bp+1] 35 | // 2.2 b增/a 删 a[ap+1][bp] 36 | // 2.3 ab修改成相同 a[ap+1][bp+1] 37 | if (a[ap] == b[ap]) { // 相同 38 | minEdit(a, b, ap + 1, bp + 1, min) 39 | } else { // 不相同 40 | minEdit(a, b, ap, bp + 1, min + 1) // a增/b 删 a[ap][bp+1] 41 | minEdit(a, b, ap + 1, bp, min + 1) // b增/a 删 a[ap+1][bp] 42 | minEdit(a, b, ap + 1, bp + 1, min + 1) // ab修改成相同a[ap+1][bp+1] 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/bitmap/BitMap.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.bitmap 2 | 3 | import kotlin.random.Random 4 | 5 | /** 6 | * 位图 7 | */ 8 | class BitMap(private val nBits: Int) { 9 | companion object { 10 | @JvmStatic 11 | fun main(args: Array) { 12 | BitMap(100000000).apply { 13 | var i = 0 14 | while (i++ < 100000000) { 15 | val random = Random.nextInt(1000000000) 16 | set(random) 17 | } 18 | testTemp.forEach { 19 | if (!get(it)) { 20 | return@apply 21 | } 22 | } 23 | print("success!") 24 | } 25 | } 26 | } 27 | 28 | private val array = IntArray(nBits / 32 + 1) // 32 int 数据占32位 29 | private val testTemp = ArrayList() // 测试集合 30 | 31 | fun set(k: Int) { 32 | if (k > nBits) return 33 | testTemp.add(k) 34 | val bBite = k / 32 35 | val bBiteIndex = k % 32 36 | array[bBite] = array[bBite].or(1.shl(bBiteIndex)) 37 | } 38 | 39 | fun get(k: Int): Boolean { 40 | if (k > nBits) return false 41 | val bBite = k / 32 42 | val bBiteIndex = k % 32 43 | return array[bBite].and(1.shl(bBiteIndex)) != 0 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/dp/YangHuiTriangleVer.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.dp 2 | 3 | import kotlin.math.min 4 | 5 | /** 6 | * 杨辉三角变体 7 | * 8 | * 每个位置的数字可以随意填写,经过某个数字只能到达下面一层相邻的两个数字。 9 | * 假设你站在第一层,往下移动,我们把移动到最底层所经过的所有数字之和,定义为路径的长度。请你编程求出从最高层移动到最底层的最短路径长度。 10 | */ 11 | class YangHuiTriangleVer { 12 | 13 | companion object { 14 | @JvmStatic 15 | fun main(args: Array) { 16 | println(YangHuiTriangleVer().yangHuiTriangle(arrayOf( 17 | intArrayOf(5), 18 | intArrayOf(7, 8), 19 | intArrayOf(2, 3, 4), 20 | intArrayOf(4, 9, 6, 1), 21 | intArrayOf(2, 7, 9, 4, 5) 22 | ), 5)) 23 | } 24 | } 25 | 26 | fun yangHuiTriangle(matrix: Array, n: Int): Int { 27 | val status = Array(n) { IntArray(n) } 28 | status[0][0] = matrix[0][0] 29 | 30 | var i = 1 31 | 32 | while (i < n) { 33 | var k = 0 34 | while (k <= i) { 35 | when (k) { 36 | 0 -> status[i][k] = status[i - 1][k] + matrix[i][k] 37 | i -> status[i][k] = status[i - 1][k - 1] + matrix[i][k] 38 | else -> status[i][k] = min(status[i - 1][k - 1], status[i - 1][k]) + matrix[i][k] 39 | } 40 | k++ 41 | } 42 | i++ 43 | } 44 | 45 | var min = Int.MAX_VALUE 46 | status[n - 1].forEach { 47 | if (it < min) min = it 48 | } 49 | 50 | return min 51 | } 52 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/AddTwoNumbers.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | import com.daily.algothrim.linked.LinkedNode 4 | 5 | /** 6 | * 两数相加(leetcode 2) 7 | * 8 | * 给出两个非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。 9 | * 10 | * 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 11 | * 12 | * 您可以假设除了数字 0 之外,这两个数都不会以 0开头。 13 | * 14 | * 示例: 15 | * 16 | * 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 17 | * 输出:7 -> 0 -> 8 18 | * 原因:342 + 465 = 807 19 | */ 20 | class AddTwoNumbers { 21 | companion object { 22 | @JvmStatic 23 | fun main(args: Array) { 24 | AddTwoNumbers().solution(LinkedNode(2, LinkedNode(4, LinkedNode(3))), 25 | LinkedNode(5, LinkedNode(6, LinkedNode(4))))?.printAll() 26 | } 27 | } 28 | 29 | /** 30 | * O(m+n) 31 | */ 32 | fun solution(l1: LinkedNode?, l2: LinkedNode?): LinkedNode? { 33 | var a = l1 34 | var b = l2 35 | 36 | val result = LinkedNode(-1) 37 | var temp: LinkedNode? = result 38 | var carry = 0 39 | 40 | while (a != null || b != null) { 41 | val add = (a?.value ?: 0) + (b?.value ?: 0) + carry 42 | carry = add / 10 43 | temp?.next = LinkedNode(add % 10) 44 | temp = temp?.next 45 | a = a?.next 46 | b = b?.next 47 | 48 | if (carry > 0) temp?.next = LinkedNode(carry) 49 | } 50 | 51 | return result.next 52 | } 53 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/CanPlaceFlowers.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 605. 种花问题 5 | * 6 | * 假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。 7 | * 给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数 n 。能否在不打破种植规则的情况下种入 n 朵花?能则返回True,不能则返回False。 8 | * 9 | * 示例 1: 10 | * 11 | * 输入: flowerbed = [1,0,0,0,1], n = 1 12 | * 输出: True 13 | * 示例 2: 14 | * 15 | * 输入: flowerbed = [1,0,0,0,1], n = 2 16 | * 输出: False 17 | * */ 18 | class CanPlaceFlowers { 19 | 20 | companion object { 21 | @JvmStatic 22 | fun main(args: Array) { 23 | println(CanPlaceFlowers().solution(intArrayOf(0, 1, 1, 0, 0, 1, 1), 1)) 24 | } 25 | } 26 | 27 | 28 | /** 29 | * O(n) 30 | */ 31 | fun solution(flowerbed: IntArray, n: Int): Boolean { 32 | var i = 0 33 | val size = flowerbed.size 34 | var num = 0 35 | while (i < size) { 36 | if (flowerbed[i] == 0 && (i == size - 1 || flowerbed[i + 1] == 0) && (i == 0 || flowerbed[i - 1] == 0)) { 37 | flowerbed[i] = 1 38 | num++ 39 | } 40 | i++ 41 | } 42 | 43 | return num >= n 44 | } 45 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/CheckPossibility.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 665. 非递减数列 5 | * 6 | * 给你一个长度为 n 的整数数组,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。 7 | * 我们是这样定义一个非递减数列的: 对于数组中所有的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。 8 | */ 9 | class CheckPossibility { 10 | 11 | companion object { 12 | @JvmStatic 13 | fun main(args: Array) { 14 | println(CheckPossibility().solution(intArrayOf(4, 2, 3))) 15 | println(CheckPossibility().solution(intArrayOf(4, 2, 1))) 16 | println(CheckPossibility().solution(intArrayOf(4, 2))) 17 | println(CheckPossibility().solution(intArrayOf(2))) 18 | println(CheckPossibility().solution(intArrayOf(3, 4, 2, 3))) 19 | } 20 | } 21 | 22 | // 输入: nums = [4,2,3] 23 | // 输出: true 24 | // 解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。 25 | fun solution(nums: IntArray): Boolean { 26 | val size = nums.size 27 | var adjustTime = 0 28 | for (i in 0 until size - 1) { 29 | val x = nums[i] 30 | val y = nums[i + 1] 31 | if (x > y) { 32 | adjustTime++ 33 | if (adjustTime > 1) return false 34 | if (i > 0 && y < nums[i - 1]) { 35 | nums[i + 1] = x 36 | } 37 | } 38 | 39 | } 40 | 41 | return true 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/ContainsDuplicate.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 217. 存在重复元素 5 | * 6 | * 给定一个整数数组,判断是否存在重复元素。 7 | * 8 | * 如果任意一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。 9 | * 10 | * 示例 1: 11 | * 12 | * 输入: [1,2,3,1] 13 | * 输出: true 14 | * 示例 2: 15 | * 16 | * 输入: [1,2,3,4] 17 | * 输出: false 18 | * 示例 3: 19 | * 20 | * 输入: [1,1,1,3,3,4,3,2,4,2] 21 | * 输出: true 22 | * */ 23 | class ContainsDuplicate { 24 | 25 | companion object { 26 | @JvmStatic 27 | fun main(args: Array) { 28 | println(ContainsDuplicate().solution(intArrayOf(1, 2, 3, 1))) 29 | println(ContainsDuplicate().solution(intArrayOf(1, 2, 3, 4))) 30 | println(ContainsDuplicate().solution(intArrayOf(1, 1, 1, 3, 3, 4, 3, 2, 4, 2))) 31 | } 32 | } 33 | 34 | // 时间:O(n) 35 | // 空间:O(n) 36 | fun solution(nums: IntArray): Boolean { 37 | val map = hashMapOf() 38 | nums.forEach { 39 | if (map[it] != null) return true 40 | map[it] = true 41 | } 42 | return false 43 | } 44 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/Decode.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 1720. 解码异或后的数组 5 | * 6 | * 未知 整数数组 arr 由 n 个非负整数组成。 7 | * 8 | * 经编码后变为长度为 n - 1 的另一个整数数组 encoded ,其中 encoded[i] = arr[i] XOR arr[i + 1] 。例如,arr = [1,0,2,1] 经编码后得到 encoded = [1,2,3] 。 9 | * 10 | * 给你编码后的数组 encoded 和原数组 arr 的第一个元素 first(arr[0])。 11 | * 12 | * 请解码返回原数组 arr 。可以证明答案存在并且是唯一的。 13 | */ 14 | class Decode { 15 | 16 | companion object { 17 | @JvmStatic 18 | fun main(args: Array) { 19 | Decode().decode(intArrayOf(1, 2, 3), 1).forEach { 20 | println(it) 21 | } 22 | } 23 | } 24 | 25 | // a ^ a = 0 26 | // a ^ 0 = a 27 | // encoded[i] = result[i] ^ result[i + 1] 28 | // encoded[i] ^ result[i] = result[i] ^ result[i] ^ result[i + 1] 29 | // encoded[i] ^ result[i] = result[i + 1] 30 | 31 | // 时间:O(n) 32 | // 空间:O(1) 33 | fun decode(encoded: IntArray, first: Int): IntArray { 34 | val result = IntArray(encoded.size + 1) 35 | result[0] = first 36 | encoded.forEachIndexed { index, i -> 37 | result[index + 1] = i.xor(result[index]) 38 | } 39 | return result 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/FairCandySwap.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 888. 公平的糖果棒交换 5 | * 爱丽丝和鲍勃有不同大小的糖果棒:A[i] 是爱丽丝拥有的第 i 根糖果棒的大小,B[j] 是鲍勃拥有的第 j 根糖果棒的大小。 6 | * 7 | * 因为他们是朋友,所以他们想交换一根糖果棒,这样交换后,他们都有相同的糖果总量。(一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。) 8 | * 9 | * 返回一个整数数组 ans,其中 ans[0] 是爱丽丝必须交换的糖果棒的大小,ans[1] 是 Bob 必须交换的糖果棒的大小。 10 | * 11 | * 如果有多个答案,你可以返回其中任何一个。保证答案存在。 12 | * 13 | */ 14 | class FairCandySwap { 15 | 16 | companion object { 17 | @JvmStatic 18 | fun main(args: Array) { 19 | FairCandySwap().solution(intArrayOf(1, 1), intArrayOf(2, 2)).forEach { 20 | println(it) 21 | } 22 | } 23 | 24 | } 25 | 26 | // 输入:A = [1,1], B = [2,2] 27 | // 输出:[1,2] 28 | // O(m+n) 29 | // O(m) 30 | fun solution(A: IntArray, B: IntArray): IntArray { 31 | val map = HashSet() 32 | var sumA = 0 33 | var sumB = 0 34 | val result = IntArray(2) 35 | 36 | for (a in A) { 37 | sumA += a 38 | map.add(a) 39 | } 40 | 41 | for (b in B) { 42 | sumB += b 43 | } 44 | 45 | val sub = (sumA - sumB) / 2 46 | 47 | for (b in B) { 48 | val a = b + sub 49 | if (map.contains(a)) { 50 | result[0] = a 51 | result[1] = b 52 | break 53 | } 54 | } 55 | 56 | return result 57 | } 58 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/FindMaxAverage.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | import kotlin.math.max 4 | 5 | /** 6 | * 643. 子数组最大平均数 I 7 | * 给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。  8 | * 9 | * 示例: 10 | * 11 | * 输入:[1,12,-5,-6,50,3], k = 4 12 | * 输出:12.75 13 | * 解释:最大平均数 (12-5-6+50)/4 = 51/4 = 12.75 14 | */ 15 | class FindMaxAverage { 16 | 17 | companion object { 18 | @JvmStatic 19 | fun main(args: Array) { 20 | println(FindMaxAverage().solution(intArrayOf(1, 12, -5, -6, 50, 3), 4)) 21 | } 22 | } 23 | 24 | fun solution(nums: IntArray, k: Int): Double { 25 | var maxTotal = 0 26 | var tempTotal = 0 27 | var i = 0 28 | var j = 0 29 | val size = nums.size 30 | 31 | while (i < size) { 32 | if (i < k) { 33 | maxTotal += nums[i] 34 | tempTotal = maxTotal 35 | } else { 36 | tempTotal = tempTotal - nums[j] + nums[i] 37 | maxTotal = max(tempTotal, maxTotal) 38 | j++ 39 | } 40 | i++ 41 | } 42 | return maxTotal.toDouble() / k 43 | } 44 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/FindMaximumXOR.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 421. 数组中两个数的最大异或值 5 | * 6 | * 给你一个整数数组 nums ,返回 nums[i] XOR nums[j] 的最大运算结果,其中 0 ≤ i ≤ j < n 。 7 | * 8 | * 进阶:你可以在 O(n) 的时间解决这个问题吗? 9 | */ 10 | class FindMaximumXOR { 11 | 12 | companion object { 13 | @JvmStatic 14 | fun main(args: Array) { 15 | println(FindMaximumXOR().findMaximumXOR(intArrayOf(3, 10, 5, 25, 2, 8))) 16 | println(FindMaximumXOR().findMaximumXOR(intArrayOf(8, 10, 2))) 17 | } 18 | } 19 | 20 | // 输入:nums = [3,10,5,25,2,8] 21 | // 输出:28 22 | // 解释:最大运算结果是 5 XOR 25 = 28. 23 | fun findMaximumXOR(nums: IntArray): Int { 24 | var x = 0 25 | for (k in 30 downTo 0) { 26 | val seen = hashSetOf() 27 | for (num in nums) { 28 | seen.add(num.shr(k)) 29 | } 30 | 31 | val xNext = x * 2 + 1 32 | var found = false 33 | 34 | for (num in nums) { 35 | if (seen.contains(xNext.xor(num.shr(k)))) { 36 | found = true 37 | break 38 | } 39 | } 40 | 41 | x = if (found) { 42 | xNext 43 | } else { 44 | xNext - 1 45 | } 46 | } 47 | return x 48 | } 49 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/HasCycle.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | import com.daily.algothrim.linked.LinkedNode 4 | 5 | /** 6 | * 环形链表(leetcode 141) 7 | */ 8 | class HasCycle { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | val head = LinkedNode(1) 14 | val cycleNode = LinkedNode(2) 15 | println(HasCycle().hasCycle(head.apply { 16 | next = cycleNode.apply { 17 | next = LinkedNode(3).apply { 18 | next = LinkedNode(2).apply { 19 | next = LinkedNode(1).apply { 20 | next = cycleNode 21 | } 22 | } 23 | } 24 | } 25 | })) 26 | } 27 | } 28 | 29 | fun hasCycle(head: LinkedNode?): Boolean { 30 | var fast = head 31 | var slow = head 32 | 33 | while (fast?.next != null) { 34 | fast = fast.next?.next 35 | slow = slow?.next 36 | if (slow == fast) return true 37 | } 38 | 39 | return false 40 | } 41 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/KthLargestValue.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 1738. 找出第 K 大的异或坐标值 5 | *给你一个二维矩阵 matrix 和一个整数 k ,矩阵大小为 m x n 由非负整数组成。 6 | * 7 | * 矩阵中坐标 (a, b) 的 值 可由对所有满足 0 <= i <= a < m 且 0 <= j <= b < n 的元素 matrix[i][j](下标从 0 开始计数)执行异或运算得到。 8 | * 9 | * 请你找出 matrix 的所有坐标中第 k 大的值(k 的值从 1 开始计数)。 10 | */ 11 | class KthLargestValue { 12 | 13 | companion object { 14 | @JvmStatic 15 | fun main(args: Array) { 16 | println(KthLargestValue().kthLargestValue(arrayOf(intArrayOf(5, 2), intArrayOf(1, 6)), 1)) 17 | println(KthLargestValue().kthLargestValue(arrayOf(intArrayOf(5, 2), intArrayOf(1, 6)), 2)) 18 | println(KthLargestValue().kthLargestValue(arrayOf(intArrayOf(5, 2), intArrayOf(1, 6)), 3)) 19 | println(KthLargestValue().kthLargestValue(arrayOf(intArrayOf(5, 2), intArrayOf(1, 6)), 4)) 20 | } 21 | } 22 | 23 | /** 24 | * 时间:O(mnlog(mn)) 25 | * 空间:O(mn) 26 | */ 27 | fun kthLargestValue(matrix: Array, k: Int): Int { 28 | val n = matrix.size 29 | val m = matrix[0].size 30 | val result = mutableListOf() 31 | 32 | val pre = Array(n + 1) { 33 | IntArray(m + 1) 34 | } 35 | 36 | for (i in 1..n) { 37 | for (j in 1..m) { 38 | pre[i][j] = pre[i - 1][j].xor(pre[i][j - 1]).xor(pre[i - 1][j - 1]).xor(matrix[i - 1][j - 1]) 39 | result.add(pre[i][j]) 40 | } 41 | } 42 | 43 | result.sortWith(Comparator { o1, o2 -> o2 - o1 }) 44 | 45 | return result[k - 1] 46 | } 47 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/MaxTurbulenceSize.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 978. 最长湍流子数组 5 | * 当 A 的子数组 A[i], A[i+1], ..., A[j] 满足下列条件时,我们称其为湍流子数组: 6 | * 7 | * 若 i <= k < j,当 k 为奇数时, A[k] > A[k+1],且当 k 为偶数时,A[k] < A[k+1]; 8 | * 或 若 i <= k < j,当 k 为偶数时,A[k] > A[k+1] ,且当 k 为奇数时, A[k] < A[k+1]。 9 | * 也就是说,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是湍流子数组。 10 | * 返回 A 的最大湍流子数组的长度。 11 | */ 12 | class MaxTurbulenceSize { 13 | 14 | companion object { 15 | @JvmStatic 16 | fun main(args: Array) { 17 | println(MaxTurbulenceSize().solution(intArrayOf(9, 4, 2, 10, 7, 8, 8, 1, 9))) 18 | println(MaxTurbulenceSize().solution(intArrayOf(4, 8, 12, 16))) 19 | println(MaxTurbulenceSize().solution(intArrayOf(100))) 20 | println(MaxTurbulenceSize().solution(intArrayOf(9, 9))) 21 | } 22 | } 23 | 24 | // 输入:[9,4,2,10,7,8,8,1,9] 25 | // 输出:5 26 | // 解释:(A[1] > A[2] < A[3] > A[4] < A[5]) 27 | fun solution(arr: IntArray): Int { 28 | val size = arr.size 29 | if (size == 1) return 1 30 | 31 | var max = 0 32 | var temp = 1 33 | var i = 0 34 | var flag = false 35 | 36 | while (i < size - 1) { 37 | val sub = arr[i] - arr[i + 1] 38 | if (sub > 0 && !flag) { 39 | temp++ 40 | } else if (sub < 0 && flag) { 41 | temp++ 42 | } else { 43 | max = Math.max(max, temp) 44 | temp = if (sub != 0) 2 else 1 45 | } 46 | 47 | flag = sub > 0 48 | i++ 49 | } 50 | 51 | max = Math.max(max, temp) 52 | return max 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/MaximumProduct.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | import kotlin.math.max 4 | 5 | /** 6 | * 628. 三个数的最大乘积 7 | * 给定一个整型数组,在数组中找出由三个数组成的最大乘积,并输出这个乘积。 8 | */ 9 | class MaximumProduct { 10 | 11 | companion object { 12 | @JvmStatic 13 | fun main(args: Array) { 14 | println(MaximumProduct().solution(intArrayOf(1, 2, 3, 4))) 15 | } 16 | } 17 | 18 | 19 | // 三个最大数的乘积或者两个最小负数的与最大正数的乘积 20 | fun solution(nums: IntArray): Int { 21 | var max1 = Int.MIN_VALUE 22 | var max2 = Int.MIN_VALUE 23 | var max3 = Int.MIN_VALUE 24 | var min1 = Int.MAX_VALUE 25 | var min2 = Int.MAX_VALUE 26 | 27 | for (num in nums) { 28 | when { 29 | num > max1 -> { 30 | max3 = max2 31 | max2 = max1 32 | max1 = num 33 | } 34 | num > max2 -> { 35 | max3 = max2 36 | max2 = num 37 | } 38 | num > max3 -> max3 = num 39 | } 40 | 41 | if (num < min1) { 42 | min2 = min1 43 | min1 = num 44 | } else if (num < min2) { 45 | min2 = num 46 | } 47 | } 48 | 49 | return max(max1.times(max2).times(max3), max1.times(min1).times(min2)) 50 | } 51 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/MinimumDifference.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | import com.daily.algothrim.tree.TreeNode 4 | import kotlin.math.min 5 | 6 | /** 7 | * 二叉树的最小绝对差(leetcode 530) 8 | * 9 | * 给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。 10 | * 示例: 11 | * 12 | * 输入: 13 | * 14 | * 1 15 | * \ 16 | * 3 17 | * / 18 | * 2 19 | * 20 | * 输出: 21 | * 1 22 | * 23 | * 解释: 24 | * 最小绝对差为 1,其中 2 和 1 的差的绝对值为 1(或者 2 和 3)。 25 | * 26 | * 提示: 27 | * 树中至少有 2 个节点。 28 | */ 29 | class MinimumDifference { 30 | 31 | private var mPre = -1 32 | 33 | companion object { 34 | @JvmStatic 35 | fun main(args: Array) { 36 | println(MinimumDifference().getMinimumDifference(TreeNode(5, left = TreeNode(4), right = TreeNode(7)))) 37 | } 38 | } 39 | 40 | /** 41 | * O(n) 42 | */ 43 | fun getMinimumDifference(root: TreeNode?): Int { 44 | return dfs(root, Int.MAX_VALUE) 45 | } 46 | 47 | /** 48 | * 中序遍历之后是一个递增的有序队列,直接比较 49 | */ 50 | private fun dfs(root: TreeNode?, currentMin: Int): Int { 51 | if (root == null) return currentMin 52 | var sCurrentMin: Int 53 | sCurrentMin = dfs(root.left, currentMin) 54 | if (mPre < 0) { 55 | mPre = root.data 56 | } else { 57 | sCurrentMin = min(sCurrentMin, root.data - mPre) 58 | mPre = root.data 59 | } 60 | sCurrentMin = dfs(root.right, sCurrentMin) 61 | return sCurrentMin 62 | } 63 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/NumEquivDominoPairs.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 1128. 等价多米诺骨牌对的数量 5 | * 6 | * 给你一个由一些多米诺骨牌组成的列表 dominoes。 7 | * 8 | * 如果其中某一张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌,我们就认为这两张牌是等价的。 9 | * 10 | * 形式上,dominoes[i] = [a, b] 和 dominoes[j] = [c, d] 等价的前提是 a==c 且 b==d,或是 a==d 且 b==c。 11 | * 12 | * 在 0 <= i < j < dominoes.length 的前提下,找出满足 dominoes[i] 和 dominoes[j] 等价的骨牌对 (i, j) 的数量。 13 | * */ 14 | class NumEquivDominoPairs { 15 | 16 | companion object { 17 | @JvmStatic 18 | fun main(args: Array) { 19 | println(NumEquivDominoPairs().solution(arrayOf( 20 | intArrayOf(1, 2), 21 | intArrayOf(2, 1), 22 | intArrayOf(3, 4), 23 | intArrayOf(5, 6) 24 | ))) 25 | } 26 | } 27 | 28 | // dominoes[i].size 最大为两位 29 | // O(n) 30 | fun solution(dominoes: Array): Int { 31 | // 组成两位数的正数 32 | val a = IntArray(100) 33 | var count = 0 34 | 35 | for (item in dominoes) { 36 | if (item[0] > item[1]) { 37 | val temp = item[0] 38 | item[0] = item[1] 39 | item[1] = temp 40 | } 41 | 42 | count += a[item[0] * 10 + item[1]]++ 43 | } 44 | 45 | return count 46 | } 47 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/NumIslands.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 200. 岛屿数量 5 | * 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。 6 | * 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 7 | * 此外,你可以假设该网格的四条边均被水包围。 8 | */ 9 | class NumIslands { 10 | 11 | companion object { 12 | @JvmStatic 13 | fun main(args: Array) { 14 | println(NumIslands().numIslands( 15 | arrayOf( 16 | charArrayOf('1', '1', '1', '1', '0'), 17 | charArrayOf('1', '1', '0', '1', '0'), 18 | charArrayOf('1', '1', '0', '0', '0'), 19 | charArrayOf('0', '0', '0', '0', '0') 20 | ) 21 | )) 22 | } 23 | } 24 | 25 | fun numIslands(grid: Array): Int { 26 | if (grid.isNullOrEmpty() || grid[0].isEmpty()) return 0 27 | var result = 0 28 | val r = grid.size 29 | val c = grid[0].size 30 | 31 | for (ir in 0 until r) { 32 | for (ic in 0 until c) { 33 | if (grid[ir][ic] == '1') { 34 | result++ 35 | dfs(r, c, ir, ic, grid) 36 | } 37 | } 38 | } 39 | 40 | return result 41 | } 42 | 43 | private fun dfs(r: Int, c: Int, ir: Int, ic: Int, grid: Array) { 44 | if (ir < 0 || ic < 0 || ir >= r || ic >= c || grid[ir][ic] == '0') return 45 | 46 | grid[ir][ic] = '0' 47 | dfs(r, c, ir - 1, ic, grid) 48 | dfs(r, c, ir + 1, ic, grid) 49 | dfs(r, c, ir, ic - 1, grid) 50 | dfs(r, c, ir, ic + 1, grid) 51 | } 52 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/PivotIndex.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 724. 寻找数组的中心索引 5 | * 6 | * 给定一个整数类型的数组 nums,请编写一个能够返回数组 “中心索引” 的方法。 7 | * 8 | * 我们是这样定义数组 中心索引 的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。 9 | * 10 | * 如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。 11 | * */ 12 | class PivotIndex { 13 | 14 | companion object { 15 | @JvmStatic 16 | fun main(args: Array) { 17 | println(PivotIndex().solution(intArrayOf( 18 | 1, 7, 3, 6, 5, 6 19 | ))) 20 | println(PivotIndex().solution(intArrayOf( 21 | 1, 2, 3 22 | ))) 23 | println(PivotIndex().solution(intArrayOf( 24 | -1, -1, -1, -1, -1, -1 25 | ))) 26 | } 27 | } 28 | 29 | // 输入: 30 | // nums = [1, 7, 3, 6, 5, 6] 31 | // 输出:3 32 | // 解释: 33 | // 索引 3 (nums[3] = 6) 的左侧数之和 (1 + 7 + 3 = 11),与右侧数之和 (5 + 6 = 11) 相等。 34 | // 同时, 3 也是第一个符合要求的中心索引。 35 | fun solution(nums: IntArray): Int { 36 | var totalSum = 0 37 | var subSum = 0 38 | for (item in nums) { 39 | totalSum += item 40 | } 41 | 42 | nums.forEachIndexed { index, item -> 43 | if (subSum * 2 + item == totalSum) { 44 | return index 45 | } 46 | subSum += item 47 | } 48 | 49 | return -1 50 | } 51 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/SortArrayByParityII.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 922. 按奇偶排序数组 II 5 | * 6 | * 给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。 7 | * 对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。 8 | * 9 | * 你可以返回任何满足上述条件的数组作为答案。 10 | * 11 | * 示例: 12 | * 13 | * 输入:[4,2,5,7] 14 | * 输出:[4,5,2,7] 15 | * 解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。 16 | * */ 17 | class SortArrayByParityII { 18 | 19 | companion object { 20 | 21 | @JvmStatic 22 | fun main(args: Array) { 23 | SortArrayByParityII().solution(intArrayOf(4, 2, 5, 7)).forEach { 24 | println(it) 25 | } 26 | } 27 | } 28 | 29 | fun solution(A: IntArray): IntArray { 30 | var evenIndex = 0 31 | var oddIndex = 1 32 | 33 | while (evenIndex < A.size) { 34 | // 索引为偶数值为奇数 35 | if (A[evenIndex] % 2 != 0) { 36 | while (oddIndex < A.size) { 37 | // 索引为奇数值为偶数 38 | if (A[oddIndex] % 2 == 0) { 39 | val temp = A[evenIndex] 40 | A[evenIndex] = A[oddIndex] 41 | A[oddIndex] = temp 42 | break 43 | } 44 | oddIndex += 2 45 | } 46 | } 47 | evenIndex += 2 48 | } 49 | 50 | return A 51 | } 52 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/StrangePrinter.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 664: 奇怪的打印机 5 | * 6 | * 有台奇怪的打印机有以下两个特殊要求: 7 | * 8 | * 打印机每次只能打印由 同一个字符 组成的序列。 9 | * 每次可以在任意起始和结束位置打印新字符,并且会覆盖掉原来已有的字符。 10 | * 给你一个字符串 s ,你的任务是计算这个打印机打印它需要的最少打印次数。 11 | */ 12 | class StrangePrinter { 13 | 14 | companion object { 15 | @JvmStatic 16 | fun main(args: Array) { 17 | println(StrangePrinter().strangePrinter("aaaabbb")) 18 | println(StrangePrinter().strangePrinter("aba")) 19 | } 20 | } 21 | 22 | /** 23 | * 时间:O(n3) 24 | * 空间:(n2) 25 | */ 26 | fun strangePrinter(s: String): Int { 27 | val n = s.length 28 | val f = Array(n) { 29 | IntArray(n) 30 | } 31 | 32 | var i = n - 1 33 | while (i >= 0) { 34 | f[i][i] = 1 35 | for (j in i + 1 until n) { 36 | if (s[i] == s[j]) { 37 | f[i][j] = f[i][j - 1] 38 | } else { 39 | var min = Int.MAX_VALUE 40 | for (k in i until j) { 41 | min = Math.min(min, f[i][k] + f[k + 1][j]) 42 | } 43 | f[i][j] = min 44 | } 45 | } 46 | i-- 47 | } 48 | return f[0][n - 1] 49 | } 50 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/SubarraysWithKDistinct.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 992. K 个不同整数的子数组 5 | * 给定一个正整数数组 A,如果 A 的某个子数组中不同整数的个数恰好为 K,则称 A 的这个连续、不一定独立的子数组为好子数组。 6 | * 7 | * (例如,[1,2,3,1,2] 中有 3 个不同的整数:1,2,以及 3。) 8 | * 9 | * 返回 A 中好子数组的数目。 10 | */ 11 | class SubarraysWithKDistinct { 12 | 13 | companion object { 14 | @JvmStatic 15 | fun main(args: Array) { 16 | println(SubarraysWithKDistinct().solution(intArrayOf(1, 2, 1, 2, 3), 2)) 17 | } 18 | } 19 | 20 | // 输入:A = [1,2,1,2,3], K = 2 21 | // 输出:7 22 | // 解释:恰好由 2 个不同整数组成的子数组:[1,2], [2,1], [1,2], [2,3], [1,2,1], [2,1,2], [1,2,1,2]. 23 | fun solution(A: IntArray, K: Int): Int { 24 | return atMostKDistinct(A, K) - atMostKDistinct(A, K - 1) 25 | } 26 | 27 | private fun atMostKDistinct(A: IntArray, K: Int): Int { 28 | val size = A.size 29 | 30 | var left = 0 31 | var right = 0 32 | 33 | var count = 0 34 | var result = 0 35 | 36 | val freg = IntArray(size + 1) 37 | 38 | while (right < size) { 39 | if (freg[A[right]] == 0) { 40 | count++ 41 | } 42 | freg[A[right]]++ 43 | right++ 44 | 45 | while (count > K) { 46 | freg[A[left]]-- 47 | if (freg[A[left]] == 0) { 48 | count-- 49 | } 50 | left++ 51 | } 52 | result += right - left 53 | } 54 | return result 55 | } 56 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/TowSum.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 两数之和(leetcode 1) 5 | * 给定一个整数数组 nums和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。 6 | * 7 | * 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。 8 | * 9 | * 示例: 10 | * 11 | * 给定 nums = [2, 7, 11, 15], target = 9 12 | * 13 | * 因为 nums[0] + nums[1] = 2 + 7 = 9 14 | * 所以返回 [0, 1] 15 | */ 16 | class TowSum { 17 | 18 | companion object { 19 | @JvmStatic 20 | fun main(args: Array) { 21 | TowSum().solution(intArrayOf(2, 7, 11, 15), 9).forEach { 22 | println(it) 23 | } 24 | } 25 | } 26 | 27 | /** 28 | * O(n) 29 | */ 30 | fun solution(num: IntArray, target: Int): IntArray { 31 | val result = IntArray(2) 32 | val map = hashMapOf() 33 | 34 | num.forEachIndexed { index, i -> 35 | if (map.containsKey(i)) { 36 | map[i]?.let { 37 | return intArrayOf(it, index) 38 | } 39 | } 40 | map[target - i] = index 41 | } 42 | return result 43 | } 44 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/Trap.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 42. 接雨水 5 | * 6 | * 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 7 | * */ 8 | class Trap { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | println(Trap().trap(intArrayOf(0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1))) 14 | } 15 | } 16 | 17 | fun trap(height: IntArray): Int { 18 | if (height.size <= 2) return 0 19 | 20 | val n = height.size 21 | val leftMax = IntArray(n) 22 | val rightMax = IntArray(n) 23 | 24 | leftMax[0] = height[0] 25 | for (i in 1 until n) { 26 | leftMax[i] = Math.max(leftMax[i - 1], height[i]) 27 | } 28 | 29 | rightMax[n - 1] = height[n - 1] 30 | var m = n - 2 31 | while (m >= 0) { 32 | rightMax[m] = Math.max(rightMax[m + 1], height[m]) 33 | m-- 34 | } 35 | 36 | var sum = 0 37 | for (j in 0 until n) { 38 | sum += Math.min(leftMax[j], rightMax[j]) - height[j] 39 | } 40 | 41 | return sum 42 | } 43 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/XorOperation.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 1486. 数组异或操作 5 | * 6 | * 给你两个整数,n 和 start 。 7 | * 8 | * 数组 nums 定义为:nums[i] = start + 2*i(下标从 0 开始)且 n == nums.length 。 9 | * 10 | * 请返回 nums 中所有元素按位异或(XOR)后得到的结果。 11 | */ 12 | class XorOperation { 13 | 14 | companion object { 15 | @JvmStatic 16 | fun main(args: Array) { 17 | println(XorOperation().xorOperation(5, 0)) 18 | println(XorOperation().xorOperation(4, 3)) 19 | println(XorOperation().xorOperation2(5, 0)) 20 | println(XorOperation().xorOperation2(4, 3)) 21 | } 22 | } 23 | 24 | fun xorOperation(n: Int, start: Int): Int { 25 | var result = start 26 | for (i in 1 until n) { 27 | result = result.xor(start + 2 * i) 28 | } 29 | return result 30 | } 31 | 32 | fun xorOperation2(n: Int, start: Int): Int { 33 | val s = start.shr(1) 34 | val e = n.and(start).and(1) 35 | val result = sumXor(s - 1).xor(sumXor(s + n - 1)) 36 | return result.shl(1).or(e) 37 | } 38 | 39 | private fun sumXor(x: Int): Int { 40 | return when (x % 4) { 41 | 0 -> x 42 | 1 -> 1 43 | 2 -> x + 1 44 | else -> 0 45 | } 46 | } 47 | 48 | 49 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/XorQueries.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode 2 | 3 | /** 4 | * 1310. 子数组异或查询 5 | * 6 | * 有一个正整数数组 arr,现给你一个对应的查询数组 queries,其中 queries[i] = [Li, Ri]。 7 | * 8 | * 对于每个查询 i,请你计算从 Li 到 Ri 的 XOR 值(即 arr[Li] xor arr[Li+1] xor ... xor arr[Ri])作为本次查询的结果。 9 | * 10 | * 并返回一个包含给定查询 queries 所有结果的数组。 11 | */ 12 | class XorQueries { 13 | 14 | companion object { 15 | @JvmStatic 16 | fun main(args: Array) { 17 | XorQueries().xorQueries(intArrayOf(1,3,4,8), arrayOf(intArrayOf(0, 1), intArrayOf(1, 2), intArrayOf(0, 3), intArrayOf(3, 3))).apply { 18 | forEach { 19 | println(it) 20 | } 21 | } 22 | } 23 | } 24 | 25 | //输入:arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]] 26 | //输出:[2,7,14,8] 27 | //解释: 28 | //数组中元素的二进制表示形式是: 29 | //1 = 0001 30 | //3 = 0011 31 | //4 = 0100 32 | //8 = 1000 33 | //查询的 XOR 值为: 34 | //[0,1] = 1 xor 3 = 2 35 | //[1,2] = 3 xor 4 = 7 36 | //[0,3] = 1 xor 3 xor 4 xor 8 = 14 37 | //[3,3] = 8 38 | fun xorQueries(arr: IntArray, queries: Array): IntArray { 39 | val querySize = queries.size 40 | val arrSize = arr.size 41 | val result = IntArray(querySize) 42 | 43 | val xorIteration = IntArray(arrSize + 1) 44 | for (i in 0 until arrSize) { 45 | xorIteration[i + 1] = xorIteration[i].xor(arr[i]) 46 | } 47 | 48 | for (i in 0 until querySize) { 49 | result[i] = xorIteration[queries[i][0]].xor(xorIteration[queries[i][1] + 1]) 50 | } 51 | 52 | return result 53 | } 54 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/AddBinary.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 67. 二进制求和 5 | * 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。 6 | * 7 | * 示例 1: 8 | * 输入:a = "11", b = "1" 9 | * 输出:"100" 10 | * 11 | * 示例 2: 12 | * 输入:a = "1010", b = "1011" 13 | * 输出:"10101" 14 | */ 15 | class AddBinary { 16 | 17 | companion object { 18 | 19 | @JvmStatic 20 | fun main(args: Array) { 21 | println(AddBinary().addBinary("11", "1")) 22 | println(AddBinary().addBinary("1010", "1011")) 23 | } 24 | 25 | } 26 | 27 | fun addBinary(a: String, b: String): String { 28 | var carry = 0 29 | val result = StringBuilder() 30 | 31 | val n = Math.max(a.length, b.length) 32 | for (i in 0 until n) { 33 | if (i < a.length) { 34 | carry += a[a.length - i - 1] - '0' 35 | } 36 | if (i < b.length) { 37 | carry += b[b.length - i - 1] - '0' 38 | } 39 | result.append(carry % 2) 40 | carry /= 2 41 | } 42 | 43 | if (carry > 0) { 44 | result.append(carry) 45 | } 46 | 47 | result.reverse() 48 | 49 | return result.toString() 50 | } 51 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/AreAlmostEqual.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 1790. 仅执行一次字符串交换能否使两个字符串相等 5 | * 给你长度相等的两个字符串 s1 和 s2 。一次 字符串交换 操作的步骤如下:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符。 6 | * 如果对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true ;否则,返回 false 。 7 | * 8 | * 示例 1: 9 | * 输入:s1 = "bank", s2 = "kanb" 10 | * 输出:true 11 | * 解释:例如,交换 s2 中的第一个和最后一个字符可以得到 "bank" 12 | * 13 | * 示例 2: 14 | * 输入:s1 = "attack", s2 = "defend" 15 | * 输出:false 16 | * 解释:一次字符串交换无法使两个字符串相等 17 | * 18 | * 示例 3: 19 | * 输入:s1 = "kelb", s2 = "kelb" 20 | * 输出:true 21 | * 解释:两个字符串已经相等,所以不需要进行字符串交换 22 | * 23 | * 示例 4: 24 | * 输入:s1 = "abcd", s2 = "dcba" 25 | * 输出:false 26 | */ 27 | class AreAlmostEqual { 28 | 29 | companion object { 30 | @JvmStatic 31 | fun main(args: Array) { 32 | println(AreAlmostEqual().areAlmostEqual("bank", "kanb")) 33 | println(AreAlmostEqual().areAlmostEqual("attack", "defend")) 34 | println(AreAlmostEqual().areAlmostEqual("kelb", "kelb")) 35 | println(AreAlmostEqual().areAlmostEqual("abcd", "dcba")) 36 | } 37 | } 38 | 39 | fun areAlmostEqual(s1: String, s2: String): Boolean { 40 | val diff = arrayListOf() 41 | 42 | for (i in s1.indices) { 43 | if (s1[i] != s2[i]) { 44 | if (diff.size >= 2) { 45 | return false 46 | } 47 | diff.add(i) 48 | } 49 | } 50 | if (diff.isEmpty()) return true 51 | if (diff.size != 2) return false 52 | 53 | return s1[diff[0]] == s2[diff[1]] && s1[diff[1]] == s2[diff[0]] 54 | } 55 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/ClimbStairs.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 70. 爬楼梯 5 | * 6 | * 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 7 | * 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 8 | * 注意:给定 n 是一个正整数。 9 | */ 10 | class ClimbStairs { 11 | 12 | companion object { 13 | @JvmStatic 14 | fun main(args: Array) { 15 | println(ClimbStairs().climbStairs(2)) 16 | println(ClimbStairs().climbStairs(3)) 17 | println(ClimbStairs().climbStairs2(2)) 18 | println(ClimbStairs().climbStairs2(3)) 19 | } 20 | } 21 | 22 | fun climbStairs(n: Int): Int { 23 | if (n == 1) return 1 24 | if (n == 2) return 2 25 | 26 | val dp = IntArray(n) 27 | dp[0] = 1 28 | dp[1] = 2 29 | 30 | for (i in 2 until n) { 31 | dp[i] = dp[i - 1] + dp[i - 2] 32 | } 33 | 34 | return dp[n - 1] 35 | } 36 | 37 | fun climbStairs2(n: Int): Int { 38 | var p = 0 39 | var q: Int 40 | var r = 1 41 | 42 | for (i in 0 until n) { 43 | q = p 44 | p = r 45 | r = p + q 46 | } 47 | return r 48 | } 49 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/ContainsNearbyDuplicate.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 219. 存在重复元素 II 5 | */ 6 | class ContainsNearbyDuplicate { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(array: Array) { 11 | println(ContainsNearbyDuplicate().containsNearbyDuplicate(intArrayOf(1, 2, 3, 1), 3)) 12 | println(ContainsNearbyDuplicate().containsNearbyDuplicate(intArrayOf(1, 2, 3, 1, 2, 3), 2)) 13 | } 14 | } 15 | 16 | fun containsNearbyDuplicate(nums: IntArray, k: Int): Boolean { 17 | val set = hashSetOf() 18 | for (i in nums.indices) { 19 | if (i > k) { 20 | set.remove(nums[i - k - 1]) 21 | } 22 | if (!set.add(nums[i])) { 23 | return true 24 | } 25 | } 26 | return false 27 | } 28 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/Generate.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 118. 杨辉三角 5 | */ 6 | class Generate { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | Generate().generate(5).forEach {list -> 12 | list.forEach { 13 | print(it) 14 | } 15 | print(",") 16 | } 17 | println() 18 | Generate().generate(1).forEach {list -> 19 | list.forEach { 20 | print(it) 21 | } 22 | print(",") 23 | } 24 | } 25 | } 26 | 27 | fun generate(numRows: Int): List> { 28 | val result = arrayListOf>() 29 | for (i in 0 until numRows) { 30 | val row = arrayListOf() 31 | for (j in 0..i) { 32 | if (j == 0 || j == i) { 33 | row.add(1) 34 | } else { 35 | row.add(result[i - 1][j - 1] + result[i - 1][j]) 36 | } 37 | } 38 | result.add(row) 39 | } 40 | return result 41 | } 42 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/GetRow.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 119. 杨辉三角 II 5 | */ 6 | class GetRow { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | GetRow().getRow(3).forEach { 12 | print(it) 13 | } 14 | println() 15 | GetRow().getRow(0).forEach { 16 | print(it) 17 | } 18 | println() 19 | } 20 | } 21 | 22 | fun getRow(rowIndex: Int): List { 23 | var pre = ArrayList() 24 | for (i in 0 .. rowIndex) { 25 | val cur = ArrayList() 26 | for (j in 0..i) { 27 | if (j == 0 || j == i) { 28 | cur.add(1) 29 | } else { 30 | cur.add(pre[j - 1] + pre[j]) 31 | } 32 | } 33 | pre = cur 34 | } 35 | return pre 36 | } 37 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/HammingWeight.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 191. 位1的个数 5 | */ 6 | class HammingWeight { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | println(HammingWeight().hammingWeight(11)) 12 | println(HammingWeight().hammingWeight(256)) 13 | } 14 | } 15 | 16 | fun hammingWeight(n:Int):Int { 17 | var count = 0 18 | var temp = n 19 | while (temp != 0) { 20 | temp = temp.and(temp - 1) 21 | count++ 22 | } 23 | return count 24 | } 25 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/InorderTraversal.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 94. 二叉树的中序遍历 5 | */ 6 | class InorderTraversal { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | InorderTraversal().inorderTraversal(TreeNode(1).apply { 12 | right = TreeNode(2).apply { 13 | left = TreeNode(3) 14 | } 15 | }).forEach { 16 | print(it) 17 | } 18 | println() 19 | InorderTraversal().inorderTraversal(TreeNode(1)).forEach { 20 | print(it) 21 | } 22 | } 23 | } 24 | 25 | fun inorderTraversal(root: TreeNode?): List { 26 | val list = mutableListOf() 27 | inorder(root, list) 28 | return list 29 | } 30 | 31 | private fun inorder(root: TreeNode?, list: MutableList) { 32 | if (root == null) return 33 | inorder(root.left, list) 34 | list.add(root.`val`) 35 | inorder(root.right, list) 36 | } 37 | } 38 | 39 | class TreeNode(var `val`: Int) { 40 | var left: TreeNode? = null 41 | var right: TreeNode? = null 42 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/InvertTree.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | import java.util.LinkedList 4 | 5 | /** 6 | * 226. 翻转二叉树 7 | */ 8 | class InvertTree { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | printlnTree(InvertTree().invertTree( 14 | TreeNode(4).apply { 15 | left = TreeNode(2).apply { 16 | left = TreeNode(1) 17 | right = TreeNode(3) 18 | } 19 | right = TreeNode(7).apply { 20 | left = TreeNode(6) 21 | right = TreeNode(9) 22 | } 23 | } 24 | )) 25 | } 26 | 27 | private fun printlnTree(root: TreeNode?) { 28 | if (root == null) return 29 | val queue = LinkedList() 30 | queue.offer(root) 31 | while (queue.isNotEmpty()) { 32 | val node = queue.poll() 33 | println(node.`val`) 34 | if (node.left != null) { 35 | queue.offer(node.left) 36 | } 37 | if (node.right != null) { 38 | queue.offer(node.right) 39 | } 40 | } 41 | } 42 | 43 | } 44 | 45 | fun invertTree(root: TreeNode?): TreeNode? { 46 | if (root == null) return null 47 | 48 | val left = invertTree(root.left) 49 | val right = invertTree(root.right) 50 | root.left = right 51 | root.right = left 52 | return root 53 | } 54 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/IsHappy.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 202. 快乐数 5 | */ 6 | class IsHappy { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | println(IsHappy().isHappy(19)) 12 | println(IsHappy().isHappy(2)) 13 | } 14 | } 15 | 16 | fun isHappy(n: Int): Boolean { 17 | val map = hashSetOf() 18 | var temp = n 19 | while (temp != 1 && !map.contains(temp)) { 20 | map.add(temp) 21 | temp = getNext(temp) 22 | } 23 | return temp == 1 24 | } 25 | 26 | private fun getNext(n: Int): Int { 27 | var sum = 0 28 | var temp = n 29 | while (temp > 0) { 30 | val d = temp % 10 31 | temp /= 10 32 | sum += d * d 33 | } 34 | return sum 35 | } 36 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/IsIsomorphic.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 205. 同构字符串 5 | */ 6 | class IsIsomorphic { 7 | 8 | companion object { 9 | 10 | @JvmStatic 11 | fun main(args: Array) { 12 | println(IsIsomorphic().isIsomorphic("egg", "add")) 13 | println(IsIsomorphic().isIsomorphic("foo", "bar")) 14 | } 15 | } 16 | 17 | fun isIsomorphic(s: String, t: String): Boolean { 18 | val s2t = hashMapOf() 19 | val t2s = hashMapOf() 20 | 21 | for (i in s.indices) { 22 | val x = s[i] 23 | val y = t[i] 24 | if (s2t.containsKey(x) && s2t[x] != y || t2s.containsKey(y) && t2s[y] != x) { 25 | return false 26 | } 27 | s2t[x] = y 28 | t2s[y] = x 29 | } 30 | return true 31 | } 32 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/IsPalindrome.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 9. 回文数 5 | * 6 | * 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 7 | * 8 | * 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 9 | * 例如,121 是回文,而 123 不是。 10 | * 11 | * 示例 1: 12 | * 输入:x = 121 13 | * 输出:true 14 | * 15 | * 示例2: 16 | * 输入:x = -121 17 | * 输出:false 18 | * 解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 19 | * 20 | * 示例 3: 21 | * 输入:x = 10 22 | * 输出:false 23 | * 解释:从右向左读, 为 01 。因此它不是一个回文数。 24 | */ 25 | class IsPalindrome { 26 | companion object { 27 | 28 | @JvmStatic 29 | fun main(args: Array) { 30 | println(IsPalindrome().isPalindrome(121)) 31 | println(IsPalindrome().isPalindrome(-121)) 32 | println(IsPalindrome().isPalindrome(10)) 33 | } 34 | 35 | } 36 | 37 | fun isPalindrome(x: Int): Boolean { 38 | if (x < 0) return false 39 | if (x % 10 == 0 && x != 0) return false 40 | var temp = x 41 | var reverse = 0 42 | 43 | while (temp > reverse) { 44 | reverse = temp % 10 + reverse * 10 45 | temp /= 10 46 | } 47 | 48 | return reverse == temp || reverse / 10 == temp 49 | } 50 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/IsPowerOfTwo.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 231. 2 的幂 5 | */ 6 | class IsPowerOfTwo { 7 | 8 | companion object { 9 | 10 | @JvmStatic 11 | fun main(args: Array) { 12 | println(IsPowerOfTwo().isPowerOfTwo(1)) 13 | println(IsPowerOfTwo().isPowerOfTwo(16)) 14 | println(IsPowerOfTwo().isPowerOfTwo(3)) 15 | println(IsPowerOfTwo().isPowerOfTwo(4)) 16 | } 17 | 18 | } 19 | 20 | fun isPowerOfTwo(n: Int): Boolean { 21 | return n > 0 && n.and(n - 1) == 0 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/IsSameTree.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 100. 相同的树 5 | */ 6 | class IsSameTree { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | println(IsSameTree().isSameTree(TreeNode(1).apply { 12 | left = TreeNode(2) 13 | right = TreeNode(3) 14 | },TreeNode(1).apply { 15 | left = TreeNode(2) 16 | right = TreeNode(3) 17 | })) 18 | println(IsSameTree().isSameTree(TreeNode(1).apply { 19 | left = TreeNode(2) 20 | },TreeNode(1).apply { 21 | right = TreeNode(3) 22 | })) 23 | } 24 | } 25 | 26 | fun isSameTree(p: TreeNode?, q: TreeNode?): Boolean { 27 | if (p == null && q == null) return true 28 | if (p == null || q == null) return false 29 | if (p.`val` != q.`val`) return false 30 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/IsSymmetric.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 101. 对称二叉树 5 | */ 6 | class IsSymmetric { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | println(IsSymmetric().isSymmetric(TreeNode(1).apply { 12 | left = TreeNode(2).apply { 13 | left = TreeNode(3) 14 | right = TreeNode(4) 15 | } 16 | right = TreeNode(2).apply { 17 | left = TreeNode(4) 18 | right = TreeNode(3) 19 | } 20 | })) 21 | 22 | println(IsSymmetric().isSymmetric(TreeNode(1).apply { 23 | left = TreeNode(2).apply { 24 | right = TreeNode(3) 25 | } 26 | right = TreeNode(2).apply { 27 | right = TreeNode(3) 28 | } 29 | })) 30 | } 31 | } 32 | 33 | fun isSymmetric(root: TreeNode?): Boolean { 34 | return check(root, root) 35 | } 36 | 37 | private fun check(p: TreeNode?, q: TreeNode?): Boolean { 38 | if (p == null && q == null) return true 39 | if (p == null || q == null) return false 40 | 41 | return p.`val` == q.`val` && check(p.left, q.right) && check(p.right, q.left) 42 | } 43 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/IsValid.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | import java.util.* 4 | 5 | /** 6 | * 20. 有效的括号 7 | * 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。 8 | * 9 | * 有效字符串需满足: 10 | * 1. 左括号必须用相同类型的右括号闭合。 11 | * 2. 左括号必须以正确的顺序闭合。 12 | */ 13 | class IsValid { 14 | 15 | companion object { 16 | @JvmStatic 17 | fun main(args: Array) { 18 | println(IsValid().isValid("()")) 19 | println(IsValid().isValid("()[]{}")) 20 | println(IsValid().isValid("(]")) 21 | println(IsValid().isValid("{[]}")) 22 | } 23 | } 24 | 25 | // {[]} 26 | // ()[]{} 27 | fun isValid(s: String): Boolean { 28 | val length = s.length 29 | var i = 0 30 | val stack = Stack() 31 | while (i < length) { 32 | val char = s[i++] 33 | if (char == '(' || char == '[' || char == '{') { 34 | stack.push(char) 35 | } else if (stack.isEmpty() || (char == ')' && stack.peek() != '(') || (char == ']' && stack.peek() != '[') || (char == '}' && stack.peek() != '{')) { 36 | return false 37 | } else { 38 | stack.pop() 39 | } 40 | } 41 | return stack.isEmpty() // notice 42 | } 43 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/LongestCommonPrefix.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 14. 最长公共前缀 5 | * 6 | * 编写一个函数来查找字符串数组中的最长公共前缀。 7 | * 如果不存在公共前缀,返回空字符串 ""。 8 | * 9 | * 示例 1: 10 | * 11 | * 输入:strs = ["flower","flow","flight"] 12 | * 输出:"fl" 13 | * 示例 2: 14 | * 15 | * 输入:strs = ["dog","racecar","car"] 16 | * 输出:"" 17 | * 解释:输入不存在公共前缀。 18 | */ 19 | class LongestCommonPrefix { 20 | 21 | companion object { 22 | @JvmStatic 23 | fun main(args: Array) { 24 | println( 25 | LongestCommonPrefix().longestCommonPrefix( 26 | arrayOf( 27 | "flower", "flow", "flight" 28 | ) 29 | ) 30 | ) 31 | println( 32 | LongestCommonPrefix().longestCommonPrefix( 33 | arrayOf( 34 | "dog", "racecar", "car" 35 | ) 36 | ) 37 | ) 38 | } 39 | } 40 | 41 | fun longestCommonPrefix(strs: Array): String { 42 | if (strs.isEmpty()) return "" 43 | 44 | var result = strs[0] 45 | 46 | for (i in 1 until strs.size) { 47 | val length = Math.min(result.length, strs[i].length) 48 | var j = 0 49 | while (j < length && result[j] == strs[i][j]) { 50 | j++ 51 | } 52 | result = result.substring(0, j) 53 | if (result.isEmpty()) break 54 | } 55 | 56 | return result 57 | } 58 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/MajorityElement.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 169. 多数元素 5 | */ 6 | class MajorityElement { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | println(MajorityElement().majorityElement(intArrayOf(3, 2, 3))) 12 | println(MajorityElement().majorityElement(intArrayOf(2, 2, 1, 1, 1, 2, 2))) 13 | } 14 | } 15 | 16 | fun majorityElement(nums: IntArray): Int { 17 | nums.sort() 18 | return nums[nums.size / 2] 19 | } 20 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/MergeTwoLists.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | import com.daily.algothrim.leetcode.ListNode 4 | 5 | /** 6 | * 21. 合并两个有序链表 7 | * 8 | * 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 9 | */ 10 | class MergeTwoLists { 11 | 12 | companion object { 13 | @JvmStatic 14 | fun main(args: Array) { 15 | MergeTwoLists().mergeTwoLists(ListNode(1).apply { 16 | next = ListNode(2).apply { 17 | next = ListNode(4) 18 | } 19 | }, ListNode(1).apply { 20 | next = ListNode(3).apply { 21 | next = ListNode(4) 22 | } 23 | })?.printAll() 24 | MergeTwoLists().mergeTwoLists(null, null)?.printAll() 25 | MergeTwoLists().mergeTwoLists(null, ListNode(0))?.printAll() 26 | } 27 | } 28 | 29 | // l1 = [1,2,4], l2 = [1,3,4] 30 | // [1,1,2,3,4,4] 31 | fun mergeTwoLists(l1: ListNode?, l2: ListNode?): ListNode? { 32 | val result = ListNode(-1) 33 | var temp: ListNode? = result 34 | var left = l1 35 | var right = l2 36 | 37 | while (left != null && right != null) { 38 | if (left.`val` <= right.`val`) { 39 | temp?.next = left 40 | left = left.next 41 | } else { 42 | temp?.next = right 43 | right = right.next 44 | } 45 | temp = temp?.next 46 | } 47 | 48 | if (left != null) { 49 | temp?.next = left 50 | } 51 | 52 | if (right != null) { 53 | temp?.next = right 54 | } 55 | 56 | return result.next 57 | } 58 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/MyQueue.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | import java.util.Stack 4 | 5 | /** 6 | * 232. 用栈实现队列 7 | */ 8 | class MyQueue { 9 | 10 | companion object { 11 | 12 | @JvmStatic 13 | fun main(args: Array) { 14 | MyQueue().apply { 15 | push(1) 16 | push(2) 17 | println(peek()) 18 | println(pop()) 19 | println(empty()) 20 | } 21 | } 22 | 23 | } 24 | 25 | private val inStack = Stack() 26 | private val outStack = Stack() 27 | 28 | fun push(x: Int) { 29 | inStack.push(x) 30 | } 31 | 32 | fun pop(): Int { 33 | in2out() 34 | return outStack.pop() 35 | } 36 | 37 | fun peek(): Int { 38 | in2out() 39 | return outStack.peek() 40 | } 41 | 42 | fun empty(): Boolean { 43 | return inStack.isEmpty() && outStack.isEmpty() 44 | } 45 | 46 | private fun in2out() { 47 | if (outStack.isEmpty()) { 48 | while (inStack.isNotEmpty()) { 49 | outStack.push(inStack.pop()) 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/MySqrt.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 69. x 的平方根 5 | * 6 | * 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 7 | * 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 8 | * 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。 9 | * 10 | * 示例 1: 11 | * 输入:x = 4 12 | * 输出:2 13 | * 14 | * 示例 2: 15 | * 输入:x = 8 16 | * 输出:2 17 | * 解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。 18 | */ 19 | class MySqrt { 20 | companion object { 21 | @JvmStatic 22 | fun main(args: Array) { 23 | println(MySqrt().mySqrt(4)) 24 | println(MySqrt().mySqrt(8)) 25 | println(MySqrt().mySqrt(2147395599)) 26 | } 27 | } 28 | 29 | fun mySqrt(x: Int): Int { 30 | var l = 0 31 | var r = x 32 | var ans = -1 33 | 34 | while (l <= r) { 35 | val mid = l + (r - l).shr(1) 36 | if (mid * mid.toLong() <= x) { 37 | ans = mid 38 | l = mid + 1 39 | } else { 40 | r = mid - 1 41 | } 42 | } 43 | return ans 44 | } 45 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/MyStack.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | import java.util.LinkedList 4 | 5 | /** 6 | * 225. 用队列实现栈 7 | */ 8 | class MyStack { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | MyStack().apply { 14 | push(1) 15 | push(2) 16 | println(top()) 17 | println(pop()) 18 | println(empty()) 19 | } 20 | } 21 | } 22 | 23 | private var queue1: LinkedList = LinkedList() 24 | private var queue2: LinkedList = LinkedList() 25 | 26 | fun push(x: Int) { 27 | queue1.offer(x) 28 | while (queue2.isNotEmpty()) { 29 | queue1.offer(queue2.poll()) 30 | } 31 | val temp = queue1 32 | queue1 = queue2 33 | queue2 = temp 34 | } 35 | 36 | fun pop(): Int { 37 | return queue2.poll() 38 | } 39 | 40 | fun top(): Int { 41 | return queue2.peek() 42 | } 43 | 44 | fun empty(): Boolean { 45 | return queue2.isEmpty() 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/PlusOne.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 66. 加一 5 | * 6 | * 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。 7 | * 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 8 | * 你可以假设除了整数 0 之外,这个整数不会以零开头。 9 | * 10 | * 示例 1: 11 | * 输入:digits = [1,2,3] 12 | * 输出:[1,2,4] 13 | * 解释:输入数组表示数字 123。 14 | * 15 | * 示例 2: 16 | * 输入:digits = [4,3,2,1] 17 | * 输出:[4,3,2,2] 18 | * 解释:输入数组表示数字 4321。 19 | * 20 | * 示例 3: 21 | * 输入:digits = [0] 22 | * 输出:[1] 23 | */ 24 | class PlusOne { 25 | 26 | companion object { 27 | @JvmStatic 28 | fun main(args: Array) { 29 | PlusOne().plusOne(intArrayOf(1, 2, 3)).forEach { 30 | print(it) 31 | } 32 | println() 33 | PlusOne().plusOne(intArrayOf(4, 3, 2, 1)).forEach { 34 | print(it) 35 | } 36 | println() 37 | PlusOne().plusOne(intArrayOf(0)).forEach { 38 | print(it) 39 | } 40 | } 41 | } 42 | 43 | fun plusOne(digits: IntArray): IntArray { 44 | val size = digits.size 45 | for (i in size - 1 downTo 0) { 46 | if (digits[i] != 9) { 47 | digits[i]++ 48 | for (j in i + 1 until size) { 49 | digits[j] = 0 50 | } 51 | return digits 52 | } 53 | } 54 | val result = IntArray(size + 1) 55 | result[0] = 1 56 | return result 57 | } 58 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/PostorderTraversal.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 145. 二叉树的后序遍历 5 | */ 6 | class PostorderTraversal { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | PostorderTraversal().postorderTraversal(TreeNode(1).apply { 12 | right = TreeNode(2).apply { 13 | left = TreeNode(3) 14 | } 15 | }).forEach { 16 | print(it) 17 | } 18 | println() 19 | PostorderTraversal().postorderTraversal(TreeNode(1).apply { 20 | right = TreeNode(2) 21 | }).forEach { 22 | print(it) 23 | } 24 | println() 25 | } 26 | } 27 | 28 | fun postorderTraversal(root: TreeNode?): List { 29 | val result = mutableListOf() 30 | postorder(root, result) 31 | return result 32 | } 33 | 34 | private fun postorder(root: TreeNode?, list: MutableList) { 35 | if (root == null) return 36 | postorder(root.left, list) 37 | postorder(root.right, list) 38 | list.add(root.`val`) 39 | } 40 | 41 | class TreeNode(var `val`: Int) { 42 | var left: TreeNode? = null 43 | var right: TreeNode? = null 44 | } 45 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/PreorderTraversal.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 144. 二叉树的前序遍历 5 | */ 6 | class PreorderTraversal { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | PreorderTraversal().preorderTraversal(TreeNode(1).apply { 12 | right = TreeNode(2).apply { 13 | left = TreeNode(3) 14 | } 15 | }).forEach { 16 | print(it) 17 | } 18 | println() 19 | PreorderTraversal().preorderTraversal(TreeNode(1).apply { 20 | right = TreeNode(2) 21 | }).forEach { 22 | print(it) 23 | } 24 | println() 25 | } 26 | } 27 | 28 | fun preorderTraversal(root: TreeNode?): List { 29 | val result = mutableListOf() 30 | preorder(root, result) 31 | return result 32 | } 33 | 34 | private fun preorder(root: TreeNode?, list: MutableList) { 35 | if (root == null) return 36 | list.add(root.`val`) 37 | preorder(root.left, list) 38 | preorder(root.right, list) 39 | } 40 | 41 | class TreeNode(var `val`: Int) { 42 | var left: TreeNode? = null 43 | var right: TreeNode? = null 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/RemoveDuplicates.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 26. 删除有序数组中的重复项 5 | * 6 | * 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。 7 | * 由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么nums的前 k 个元素应该保存最终结果。 8 | * 将最终结果插入nums 的前 k 个位置后返回 k 。 9 | * 不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 10 | * 11 | * 示例 1: 12 | * 输入:nums = [1,1,2] 13 | * 输出:2, nums = [1,2,_] 14 | * 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。 15 | * 16 | * 示例 2: 17 | * 输入:nums = [0,0,1,1,1,2,2,3,3,4] 18 | * 输出:5, nums = [0,1,2,3,4] 19 | * 解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。 20 | */ 21 | class RemoveDuplicates { 22 | 23 | companion object { 24 | @JvmStatic 25 | fun main(args: Array) { 26 | println( 27 | RemoveDuplicates().removeDuplicates( 28 | intArrayOf(1, 1, 2) 29 | ) 30 | ) 31 | println( 32 | RemoveDuplicates().removeDuplicates( 33 | intArrayOf(0, 0, 1, 1, 1, 2, 2, 3, 3, 4) 34 | ) 35 | ) 36 | } 37 | } 38 | 39 | fun removeDuplicates(nums: IntArray): Int { 40 | if (nums.isEmpty()) return 0 41 | 42 | var slow = 1 43 | var fast = 1 44 | 45 | while (fast < nums.size) { 46 | if (nums[fast] != nums[fast - 1]) { 47 | nums[slow] = nums[fast] 48 | slow++ 49 | } 50 | fast++ 51 | } 52 | return slow 53 | } 54 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/RemoveElement.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 27. 移除元素 5 | * 给你一个数组 nums和一个值 val,你需要 原地 移除所有数值等于val的元素,并返回移除后数组的新长度。 6 | * 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 7 | * 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 8 | * 9 | * 示例 1: 10 | * 输入:nums = [3,2,2,3], val = 3 11 | * 输出:2, nums = [2,2] 12 | * 解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。 13 | * 14 | * 示例 2: 15 | * 输入:nums = [0,1,2,2,3,0,4,2], val = 2 16 | * 输出:5, nums = [0,1,4,0,3] 17 | * 解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。 18 | */ 19 | class RemoveElement { 20 | 21 | companion object { 22 | @JvmStatic 23 | fun main(args: Array) { 24 | println(RemoveElement().removeElement( 25 | intArrayOf(3,2,2,3), 3 26 | )) 27 | println(RemoveElement().removeElement( 28 | intArrayOf(0,1,2,2,3,0,4,2), 2 29 | )) 30 | } 31 | } 32 | 33 | fun removeElement(nums: IntArray, `val`: Int): Int { 34 | var left = 0 35 | var right = nums.size 36 | 37 | while (left < right) { 38 | if (nums[left] == `val`) { 39 | nums[left] = nums[right - 1] 40 | right-- 41 | } else { 42 | left++ 43 | } 44 | } 45 | return left 46 | } 47 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/Reverse.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 7. 整数反转 5 | * 6 | * 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。 7 | * 8 | * 如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。 9 | * 10 | * 假设环境不允许存储 64 位整数(有符号或无符号)。 11 | */ 12 | class Reverse { 13 | 14 | companion object { 15 | @JvmStatic 16 | fun main(args: Array) { 17 | println(Reverse().reverse(123)) 18 | println(Reverse().reverse(-123)) 19 | println(Reverse().reverse(120)) 20 | println(Reverse().reverse(0)) 21 | } 22 | } 23 | 24 | // 输入:x = 123 25 | // 输出:321 26 | // 时间复杂度:O(\log |x|)O(log∣x∣)。翻转的次数即 xx 十进制的位数。 27 | // 空间复杂度:O(1)O(1)。 28 | fun reverse(x: Int): Int { 29 | var k = x 30 | var temp: Int 31 | var result = 0 32 | while (k != 0) { 33 | if (result > Int.MAX_VALUE / 10 || result < Int.MIN_VALUE / 10) return 0 34 | temp = k % 10 35 | k /= 10 36 | result = result * 10 + temp 37 | } 38 | return result 39 | } 40 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/SearchInsert.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 35. 搜索插入位置 5 | * 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 6 | * 请必须使用时间复杂度为 O(log n) 的算法。 7 | * 8 | * 示例 1: 9 | * 输入: nums = [1,3,5,6], target = 5 10 | * 输出: 2 11 | * 12 | * 示例 2: 13 | * 输入: nums = [1,3,5,6], target = 2 14 | * 输出: 1 15 | * 16 | * 示例 3: 17 | * 输入: nums = [1,3,5,6], target = 7 18 | * 输出: 4 19 | */ 20 | class SearchInsert { 21 | 22 | companion object { 23 | @JvmStatic 24 | fun main(args: Array) { 25 | println(SearchInsert().searchInsert(intArrayOf(1,3,5,6), 5)) 26 | println(SearchInsert().searchInsert(intArrayOf(1,3,5,6), 2)) 27 | println(SearchInsert().searchInsert(intArrayOf(1,3,5,6), 7)) 28 | } 29 | } 30 | 31 | fun searchInsert(nums: IntArray, target: Int): Int { 32 | var left = 0 33 | var right = nums.size - 1 34 | 35 | while (left <= right) { 36 | val mid = left + (right - left).shr(1) 37 | if (target <= nums[mid]) { 38 | right = mid - 1 39 | } else { 40 | left = mid + 1 41 | } 42 | } 43 | return left 44 | } 45 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/easy/SingleNumber.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.easy 2 | 3 | /** 4 | * 136. 只出现一次的数字 5 | */ 6 | class SingleNumber { 7 | companion object { 8 | @JvmStatic 9 | fun main(args: Array) { 10 | println(SingleNumber().singleNumber(intArrayOf(2, 2, 1))) 11 | println(SingleNumber().singleNumber(intArrayOf(4, 1, 2, 1, 2))) 12 | } 13 | } 14 | 15 | fun singleNumber(nums: IntArray): Int { 16 | var result = 0 17 | nums.forEach { 18 | result = result.xor(it) 19 | } 20 | return result 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/hard/LargestRectangleArea.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.hard 2 | 3 | import java.util.* 4 | 5 | /** 6 | * 84. 柱状图中最大的矩形 7 | * 8 | * 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 9 | * 求在该柱状图中,能够勾勒出来的矩形的最大面积。 10 | */ 11 | class LargestRectangleArea { 12 | 13 | companion object { 14 | 15 | @JvmStatic 16 | fun main(args: Array) { 17 | println(LargestRectangleArea().largestRectangleArea(intArrayOf(2, 1, 5, 6, 2, 3))) 18 | println(LargestRectangleArea().largestRectangleArea(intArrayOf(2, 4))) 19 | } 20 | } 21 | 22 | // 输入:heights = [2,1,5,6,2,3] 23 | // 输出:10 24 | fun largestRectangleArea(heights: IntArray): Int { 25 | var largest = Int.MIN_VALUE 26 | val size = heights.size 27 | val left = IntArray(size) 28 | val right = IntArray(size) 29 | Arrays.fill(right, size) 30 | 31 | val stack = Stack() 32 | for (i in 0 until size) { 33 | while (stack.isNotEmpty() && heights[stack.peek()] >= heights[i]) { 34 | right[stack.peek()] = i 35 | stack.pop() 36 | } 37 | left[i] = if (stack.isEmpty()) -1 else stack.peek() 38 | stack.push(i) 39 | } 40 | 41 | for (j in 0 until size) { 42 | largest = Math.max(largest, (right[j] - left[j] - 1) * heights[j]) 43 | } 44 | 45 | return largest 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/hard/LongestValidParentheses.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.hard 2 | 3 | import java.util.* 4 | 5 | /** 6 | * 32. 最长有效括号 7 | * 8 | * 给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。 9 | */ 10 | class LongestValidParentheses { 11 | 12 | companion object { 13 | @JvmStatic 14 | fun main(args: Array) { 15 | println(LongestValidParentheses().longestValidParentheses("(()")) 16 | println(LongestValidParentheses().longestValidParentheses(")()())")) 17 | println(LongestValidParentheses().longestValidParentheses("")) 18 | println(LongestValidParentheses().longestValidParentheses("()(()")) 19 | } 20 | } 21 | 22 | // s = ")()())" 23 | // 4 24 | fun longestValidParentheses(s: String): Int { 25 | val stack = Stack() 26 | stack.push(-1) 27 | val length = s.length 28 | var i = 0 29 | var max = 0 30 | 31 | while (i < length) { 32 | if (s[i] == ')') { 33 | stack.pop() 34 | if (stack.isNotEmpty()) { 35 | max = Math.max(max, i - stack.peek()) 36 | } else { 37 | stack.push(i) 38 | } 39 | } else { 40 | stack.push(i) 41 | } 42 | i++ 43 | } 44 | 45 | return max 46 | } 47 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/hard/MissingTwo.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.hard 2 | 3 | /** 4 | * 给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗? 5 | * 以任意顺序返回这两个数字均可。 6 | * 7 | * 示例 1: 8 | * 输入: [1] 9 | * 输出: [2,3] 10 | * 示例 2: 11 | * 12 | * 输入: [2,3] 13 | * 输出: [1,4] 14 | * 15 | * 提示: 16 | * nums.length <= 30000 17 | */ 18 | class MissingTwo { 19 | 20 | companion object { 21 | @JvmStatic 22 | fun main(args: Array) { 23 | MissingTwo().missingTwo(intArrayOf(1)).apply { 24 | println("${this[0]} ${this[1]}") 25 | } 26 | MissingTwo().missingTwo(intArrayOf(2, 3)).apply { 27 | println("${this[0]} ${this[1]}") 28 | } 29 | println("${2.xor(-2)}") 30 | } 31 | } 32 | 33 | fun missingTwo(nums: IntArray): IntArray { 34 | var xor = 0 35 | 36 | // n - 2 37 | for (i in nums) { 38 | xor = xor.xor(i) 39 | } 40 | val n = nums.size + 2 41 | // n 42 | for (i in 1 .. n) { 43 | xor = xor.xor(i) 44 | } 45 | 46 | val lsb = xor.and(-xor) 47 | 48 | var value1 = 0 49 | var value2 = 0 50 | // n - 2 51 | for (i in nums) { 52 | if (lsb.and(i) != 0) { 53 | value1 = value1.xor(i) 54 | } else { 55 | value2 = value2.xor(i) 56 | } 57 | } 58 | 59 | // n 60 | for (i in 1..n) { 61 | if (lsb.and(i) != 0) { 62 | value1 = value1.xor(i) 63 | } else { 64 | value2 = value2.xor(i) 65 | } 66 | } 67 | 68 | return intArrayOf(value1, value2) 69 | } 70 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/CanJump.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 55. 跳跃游戏 5 | * 给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。 6 | * 7 | * 数组中的每个元素代表你在该位置可以跳跃的最大长度。 8 | * 判断你是否能够到达最后一个下标。 9 | * 10 | */ 11 | class CanJump { 12 | 13 | companion object { 14 | @JvmStatic 15 | fun main(args: Array) { 16 | println(CanJump().canJump(intArrayOf(2, 3, 1, 1, 5))) 17 | println(CanJump().canJump(intArrayOf(3, 2, 1, 0, 4))) 18 | println(CanJump().canJump2(intArrayOf(2, 3, 1, 1, 5))) 19 | println(CanJump().canJump2(intArrayOf(3, 2, 1, 0, 4))) 20 | } 21 | } 22 | 23 | fun canJump(nums: IntArray): Boolean { 24 | val size = nums.size 25 | 26 | var i = size - 2 27 | nums[size - 1] = -1 28 | while (i >= 0) { 29 | var step = nums[i] 30 | while (step >= 0) { 31 | if (i + step < size && nums[i + step] == -1) { 32 | nums[i] = -1 33 | break 34 | } 35 | step-- 36 | } 37 | i-- 38 | } 39 | return nums[0] == -1 40 | } 41 | 42 | /** 43 | * greed 44 | */ 45 | fun canJump2(nums: IntArray): Boolean { 46 | val size = nums.size 47 | var maxJump = 0 48 | var i = 0 49 | while (i < size) { 50 | if (i <= maxJump) { 51 | maxJump = Math.max(i + nums[i], maxJump) 52 | if (maxJump >= size - 1) { 53 | return true 54 | } 55 | } 56 | i++ 57 | } 58 | return false 59 | } 60 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/Convert.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 6. Z 字形变换 5 | */ 6 | class Convert { 7 | 8 | companion object { 9 | 10 | @JvmStatic 11 | fun main(args: Array) { 12 | println(Convert().convert("PAYPALISHIRING", 3)) 13 | println(Convert().convert("PAYPALISHIRING", 4)) 14 | } 15 | } 16 | 17 | fun convert(s: String, numRows: Int): String { 18 | val n = s.length 19 | if (numRows == 1 || n <= numRows) return s 20 | 21 | val p = numRows + numRows - 2 22 | val pc = numRows - 1 23 | val column = (n + p - 1) / p * pc 24 | 25 | val matrix = Array(numRows) { 26 | CharArray(column) { 27 | '0' 28 | } 29 | } 30 | 31 | var x = 0 32 | var y = 0 33 | 34 | for (i in 0 until n) { 35 | matrix[x][y] = s[i] 36 | if (i % p < numRows - 1) { 37 | x++ 38 | } else { 39 | x-- 40 | y++ 41 | } 42 | } 43 | 44 | val result = StringBuilder() 45 | for (j in 0 until numRows) { 46 | for (k in 0 until column) { 47 | if (matrix[j][k] != '0') { 48 | result.append(matrix[j][k]) 49 | } 50 | } 51 | } 52 | return result.toString() 53 | } 54 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/CountAndSay.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | import java.lang.StringBuilder 4 | 5 | /** 6 | * 38. 外观数列 7 | */ 8 | class CountAndSay { 9 | 10 | companion object { 11 | 12 | @JvmStatic 13 | fun main(args: Array) { 14 | println(CountAndSay().countAndSay(1)) 15 | println(CountAndSay().countAndSay(4)) 16 | } 17 | } 18 | 19 | fun countAndSay(n: Int): String { 20 | var str = "1" 21 | for (i in 2..n) { 22 | val sb = StringBuilder() 23 | var start = 0 24 | var curr = 0 25 | while (curr < str.length) { 26 | while (curr < str.length && str[curr] == str[start]) { 27 | curr++ 28 | } 29 | sb.append(curr - start).append(str[start]) 30 | start = curr 31 | } 32 | str = sb.toString() 33 | } 34 | return str 35 | } 36 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/GenerateParenthesis.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 22. 括号生成 5 | * 6 | * 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 7 | */ 8 | class GenerateParenthesis { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | GenerateParenthesis().generateParenthesis(3).forEach { 14 | println(it) 15 | } 16 | } 17 | } 18 | 19 | // n = 3 20 | // ["((()))","(()())","(())()","()(())","()()()"] 21 | fun generateParenthesis(n: Int): List { 22 | val result = arrayListOf() 23 | backtracking(StringBuilder(), 0, 0, n, result) 24 | return result 25 | } 26 | 27 | private fun backtracking(currentStr: StringBuilder, left: Int, right: Int, n: Int, result: ArrayList) { 28 | if (currentStr.length == 2 * n) { 29 | result.add(currentStr.toString()) 30 | return 31 | } 32 | 33 | if (left < n) { 34 | currentStr.append("(") 35 | backtracking(currentStr, left + 1, right, n, result) 36 | currentStr.deleteCharAt(currentStr.length - 1) 37 | } 38 | if (right < left) { 39 | currentStr.append(")") 40 | backtracking(currentStr, left, right + 1, n, result) 41 | currentStr.deleteCharAt(currentStr.length - 1) 42 | } 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/IntToRoman.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 12. 整数转罗马数字 5 | */ 6 | class IntToRoman { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | println(IntToRoman().intToRoman(1994)) 12 | } 13 | } 14 | 15 | private val values = arrayOf( 16 | 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 17 | ) 18 | 19 | private val symbols = arrayOf( 20 | "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" 21 | ) 22 | 23 | fun intToRoman(num: Int): String { 24 | var temp = num 25 | return StringBuffer().apply { 26 | values.forEachIndexed { index, value -> 27 | val symbol = symbols[index] 28 | while (temp >= value) { 29 | temp -= value 30 | append(symbol) 31 | } 32 | if (temp == 0) return@apply 33 | } 34 | }.toString() 35 | } 36 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/Jump.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 45. 跳跃游戏 II 5 | */ 6 | class Jump { 7 | 8 | companion object { 9 | 10 | @JvmStatic 11 | fun main(array: Array) { 12 | println(Jump().jump(intArrayOf(2,3,1,1,4))) 13 | println(Jump().jump(intArrayOf(2,3,0,1,4))) 14 | } 15 | } 16 | 17 | fun jump(nums: IntArray): Int { 18 | val size = nums.size 19 | 20 | var maxPosition = 0 21 | var end = 0 22 | var step = 0 23 | 24 | for (i in 0 until size - 1) { 25 | maxPosition = Math.max(maxPosition, i + nums[i]) 26 | if (i == end) { 27 | end = maxPosition 28 | step++ 29 | } 30 | } 31 | return step 32 | } 33 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/LongestPalindrome.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 5. 最长回文子串 5 | * 给你一个字符串 s,找到 s 中最长的回文子串。 6 | */ 7 | class LongestPalindrome { 8 | 9 | companion object { 10 | @JvmStatic 11 | fun main(args: Array) { 12 | println(LongestPalindrome().longestPalindrome("babad")) 13 | println(LongestPalindrome().longestPalindrome("cbbd")) 14 | println(LongestPalindrome().longestPalindrome("a")) 15 | println(LongestPalindrome().longestPalindrome("ac")) 16 | println(LongestPalindrome().longestPalindrome("ccc")) 17 | } 18 | } 19 | 20 | var finalStart = 0 21 | var finalEnd = 0 22 | var maxLength = 0 23 | 24 | fun longestPalindrome(s: String): String { 25 | val length = s.length 26 | s.forEachIndexed { index, _ -> 27 | checkPalindrome(s, index, index) 28 | if (index + 1 < length) { 29 | checkPalindrome(s, index, index + 1) 30 | } 31 | } 32 | return s.substring(finalStart, finalEnd + 1) 33 | } 34 | 35 | private fun checkPalindrome(s: String, left: Int, right: Int) { 36 | val length = s.length 37 | var start = left 38 | var end = right 39 | while (start >= 0 && end < length) { 40 | if (s[start] == s[end]) { 41 | start-- 42 | end++ 43 | continue 44 | } 45 | break 46 | } 47 | end-- 48 | start++ 49 | if (end - start + 1 > maxLength) { 50 | maxLength = end - start + 1 51 | finalStart = start 52 | finalEnd = end 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/MaxArea.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 11. 盛最多水的容器 5 | * 给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 6 | */ 7 | class MaxArea { 8 | 9 | companion object { 10 | @JvmStatic 11 | fun main(args: Array) { 12 | println(MaxArea().maxArea(intArrayOf(1, 8, 6, 2, 5, 4, 8, 3, 7))) 13 | println(MaxArea().maxArea(intArrayOf(1, 1))) 14 | println(MaxArea().maxArea(intArrayOf(4, 3, 2, 1, 4))) 15 | println(MaxArea().maxArea(intArrayOf(1, 2, 1))) 16 | } 17 | } 18 | 19 | // [1,8,6,2,5,4,8,3,7] 20 | fun maxArea(height: IntArray): Int { 21 | var start = 0 22 | var end = height.size - 1 23 | var max = 0 24 | var min = Int.MIN_VALUE 25 | while (start < end) { 26 | val startValue = height[start] 27 | val endValue = height[end] 28 | val minValue = Math.min(startValue, endValue) 29 | if (minValue > min) { 30 | min = minValue 31 | max = Math.max(max, (end - start) * min) 32 | } 33 | if (startValue <= min) { 34 | start++ 35 | } else { 36 | end-- 37 | } 38 | } 39 | return max 40 | } 41 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/Merge.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 56. 合并区间 5 | * 6 | * 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。 7 | */ 8 | class Merge { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | Merge().merge(arrayOf(intArrayOf(1, 3), intArrayOf(2, 6), intArrayOf(8, 10), intArrayOf(15, 18))).forEach { 14 | println("${it[0]}, ${it[1]}") 15 | } 16 | Merge().merge(arrayOf(intArrayOf(1, 4), intArrayOf(0, 4))).forEach { 17 | println("${it[0]}, ${it[1]}") 18 | } 19 | } 20 | } 21 | 22 | // 输入:intervals = [[1,3],[2,6],[8,10],[15,18]] 23 | // 输出:[[1,6],[8,10],[15,18]] 24 | // 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. 25 | fun merge(intervals: Array): Array { 26 | intervals.sortWith(Comparator { o1, o2 -> (o1?.get(0) ?: 0) - (o2?.get(0) ?: 0) }) 27 | 28 | val result = arrayListOf() 29 | intervals.forEach { 30 | val start = it[0] 31 | val end = it[1] 32 | if (result.isEmpty() || result[result.size - 1][1] < start) { 33 | result.add(intArrayOf(start, end)) 34 | } else { 35 | result[result.size - 1][1] = Math.max(result[result.size - 1][1], end) 36 | } 37 | } 38 | return result.toTypedArray() 39 | } 40 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/MinPathSum.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 64. 最小路径和 5 | * 6 | * 给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 7 | * 说明:每次只能向下或者向右移动一步。 8 | */ 9 | class MinPathSum { 10 | 11 | companion object { 12 | @JvmStatic 13 | fun main(args: Array) { 14 | println( 15 | MinPathSum().minPathSum( 16 | arrayOf( 17 | intArrayOf(1, 3, 1), 18 | intArrayOf(1, 5, 1), 19 | intArrayOf(4, 2, 1) 20 | ) 21 | ) 22 | ) 23 | println( 24 | MinPathSum().minPathSum( 25 | arrayOf( 26 | intArrayOf(1, 2, 3), 27 | intArrayOf(4, 5, 6) 28 | ) 29 | ) 30 | ) 31 | } 32 | } 33 | 34 | // 输入:grid = [[1,3,1],[1,5,1],[4,2,1]] 35 | // 输出:7 36 | // 解释:因为路径 1→3→1→1→1 的总和最小。 37 | fun minPathSum(grid: Array): Int { 38 | val r = grid.size 39 | val c = grid[0].size 40 | val minPath = Array(r) { IntArray(c) } 41 | minPath[0][0] = grid[0][0] 42 | 43 | for (i in 1 until r) { 44 | minPath[i][0] = minPath[i - 1][0] + grid[i][0] 45 | } 46 | 47 | for (j in 1 until c) { 48 | minPath[0][j] = minPath[0][j - 1] + grid[0][j] 49 | } 50 | 51 | for (i in 1 until r) { 52 | for (j in 1 until c) { 53 | minPath[i][j] = Math.min(minPath[i - 1][j], minPath[i][j - 1]) + grid[i][j] 54 | } 55 | } 56 | 57 | return minPath[r - 1][c - 1] 58 | } 59 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/MyPow.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 50. Pow(x, n) 5 | */ 6 | class MyPow { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | println(MyPow().myPow(2.0, 10)) 12 | println(MyPow().myPow(2.1, 3)) 13 | println(MyPow().myPow(2.0, -2)) 14 | } 15 | } 16 | 17 | fun myPow(x: Double, n: Int): Double { 18 | return if (n >= 0) quickMul(x, n) else 1.0 / quickMul(x, -n) 19 | } 20 | 21 | private fun quickMul(x: Double, n: Int): Double { 22 | if (n == 0) return 1.0 23 | 24 | val y = quickMul(x, n / 2) 25 | return if (n % 2 == 0) y * y else y * y * x 26 | } 27 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/RemoveNthFromEnd.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | import com.daily.algothrim.leetcode.ListNode 4 | 5 | /** 6 | * 19. 删除链表的倒数第 N 个结点 7 | * 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 8 | * 进阶:你能尝试使用一趟扫描实现吗? 9 | */ 10 | class RemoveNthFromEnd { 11 | 12 | companion object { 13 | @JvmStatic 14 | fun main(args: Array) { 15 | RemoveNthFromEnd().removeNthFromEnd(ListNode(1).apply { 16 | next = ListNode(2).apply { 17 | next = ListNode(3).apply { 18 | next = ListNode(4).apply { 19 | next = ListNode(5) 20 | } 21 | } 22 | } 23 | }, 2)?.printAll() 24 | } 25 | } 26 | 27 | // head = [1,2,3,4,5], n = 2 28 | fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? { 29 | val result = ListNode(-1).apply { next = head } 30 | var slow: ListNode? = result 31 | var fast: ListNode? = result 32 | 33 | for (i in 0 until n) { 34 | fast = fast?.next 35 | } 36 | 37 | while (fast?.next != null) { 38 | slow = slow?.next 39 | fast = fast.next 40 | 41 | } 42 | slow?.next = slow?.next?.next 43 | 44 | return result.next 45 | } 46 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/Rotate.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 48. 旋转图像 5 | * 6 | * 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 7 | * 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 8 | */ 9 | class Rotate { 10 | 11 | companion object { 12 | @JvmStatic 13 | fun main(args: Array) { 14 | val matrix = arrayOf( 15 | intArrayOf(1, 2, 3), 16 | intArrayOf(4, 5, 6), 17 | intArrayOf(7, 8, 9)) 18 | Rotate().rotate(matrix) 19 | matrix.forEach { 20 | it.forEach { item -> 21 | print(item) 22 | } 23 | println() 24 | } 25 | } 26 | } 27 | 28 | // matrix = [[1,2,3],[4,5,6],[7,8,9]] 1. i + 2 2. size - 1 , i + j 29 | // [[7,4,1],[8,5,2],[9,6,3]] 30 | // matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]] 31 | // [[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]] 32 | fun rotate(matrix: Array) { 33 | val n = matrix.size 34 | 35 | // 水平翻转 36 | for (i in 0 until n / 2) { 37 | for (j in 0 until n) { 38 | val temp = matrix[i][j] 39 | matrix[i][j] = matrix[n - i - 1][j] 40 | matrix[n - i - 1][j] = temp 41 | } 42 | } 43 | 44 | // 主对角线翻转 45 | for (i in 0 until n) { 46 | for (j in 0 until i) { 47 | val temp = matrix[i][j] 48 | matrix[i][j] = matrix[j][i] 49 | matrix[j][i] = temp 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/Search.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 33. 搜索旋转排序数组 5 | * 6 | * 整数数组 nums 按升序排列,数组中的值 互不相同 。 7 | * 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。 8 | * 给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。 9 | */ 10 | class Search { 11 | 12 | companion object { 13 | @JvmStatic 14 | fun main(args: Array) { 15 | println(Search().search(intArrayOf(4, 5, 6, 7, 0, 1, 2), 0)) 16 | println(Search().search(intArrayOf(4, 5, 6, 7, 0, 1, 2), 3)) 17 | println(Search().search(intArrayOf(1), 0)) 18 | println(Search().search(intArrayOf(3, 1), 1)) 19 | } 20 | } 21 | 22 | fun search(nums: IntArray, target: Int): Int { 23 | var start = 0 24 | var end = nums.size - 1 25 | 26 | while (start <= end) { 27 | val mid = start + (end - start).shr(1) 28 | if (target == nums[mid]) return mid 29 | if (nums[start] <= nums[mid]) { 30 | if (target < nums[mid] && target >= nums[start]) { 31 | end = mid - 1 32 | } else { 33 | start = mid + 1 34 | } 35 | } else { 36 | if (target > nums[mid] && target <= nums[end]) { 37 | start = mid + 1 38 | } else { 39 | end = mid - 1 40 | } 41 | } 42 | } 43 | return -1 44 | } 45 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/Subsets.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 78. 子集 5 | * 6 | * 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 7 | * 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 8 | */ 9 | class Subsets { 10 | 11 | companion object { 12 | @JvmStatic 13 | fun main(args: Array) { 14 | Subsets().subsets(intArrayOf(1, 2, 3)).forEach { 15 | it.forEach { item -> 16 | print(item) 17 | } 18 | println() 19 | } 20 | Subsets().subsets(intArrayOf(0)).forEach { 21 | it.forEach { item -> 22 | print(item) 23 | } 24 | println() 25 | } 26 | } 27 | } 28 | 29 | // 输入:nums = [1,2,3] 30 | // 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]] 31 | fun subsets(nums: IntArray): List> { 32 | val result = ArrayList>() 33 | backtracking(nums, 0, arrayListOf(), result) 34 | return result 35 | } 36 | 37 | private fun backtracking(nums: IntArray, index: Int, subList: ArrayList, result: ArrayList>) { 38 | if (index == nums.size) { 39 | result.add(ArrayList(subList)) 40 | return 41 | } 42 | 43 | backtracking(nums, index + 1, subList, result) 44 | 45 | subList.add(nums[index]) 46 | backtracking(nums, index + 1, subList, result) 47 | subList.removeAt(subList.size - 1) 48 | } 49 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/SwapPairs.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | import com.daily.algothrim.leetcode.ListNode 4 | 5 | /** 6 | * 24. 两两交换链表中的节点 7 | */ 8 | class SwapPairs { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | SwapPairs().swapPairs( 14 | ListNode(1).apply { 15 | next = ListNode(2).apply { 16 | next = ListNode(3).apply { 17 | next = ListNode(4) 18 | } 19 | } 20 | } 21 | )?.printAll() 22 | } 23 | } 24 | 25 | fun swapPairs(head: ListNode?): ListNode? { 26 | val guardNode = ListNode(-1) 27 | guardNode.next = head 28 | var temp: ListNode? = guardNode 29 | 30 | while (temp?.next?.next != null) { 31 | val firstNode = temp.next 32 | val secondNode = temp.next?.next 33 | 34 | temp.next = secondNode 35 | firstNode?.next = secondNode?.next 36 | secondNode?.next = firstNode 37 | 38 | temp = firstNode 39 | } 40 | 41 | return guardNode.next 42 | } 43 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/ThreeSumClosest.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 16. 最接近的三数之和 5 | */ 6 | class ThreeSumClosest { 7 | 8 | companion object { 9 | 10 | @JvmStatic 11 | fun main(args: Array) { 12 | println(ThreeSumClosest().threeSumClosest(intArrayOf(-1, 2, 1, -4), 1)) 13 | println(ThreeSumClosest().threeSumClosest(intArrayOf(0, 0, 0), 1)) 14 | } 15 | } 16 | 17 | fun threeSumClosest(nums: IntArray, target: Int): Int { 18 | nums.sort() 19 | val size = nums.size 20 | var bestResult = Int.MAX_VALUE 21 | 22 | for (i in 0 until size) { 23 | if (i > 0 && nums[i] == nums[i - 1]) continue 24 | 25 | var j = i + 1 26 | var k = size - 1 27 | while (j < k) { 28 | val sum = nums[i] + nums[j] + nums[k] 29 | if (sum == target) return target 30 | 31 | if (Math.abs(sum - target) < Math.abs(bestResult - target)) { 32 | bestResult = sum 33 | } 34 | 35 | if (sum > target) { 36 | k-- 37 | while (j < k && nums[k] == nums[k + 1]) { 38 | k-- 39 | } 40 | } else { 41 | j++ 42 | while (j < k && nums[j] == nums[j - 1]) { 43 | j++ 44 | } 45 | } 46 | } 47 | } 48 | return bestResult 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/medium/UniquePaths.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.medium 2 | 3 | /** 4 | * 62. 不同路径 5 | * 6 | * 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 7 | * 8 | * 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 9 | * 问总共有多少条不同的路径? 10 | */ 11 | class UniquePaths { 12 | 13 | companion object { 14 | @JvmStatic 15 | fun main(args: Array) { 16 | println(UniquePaths().uniquePaths(3, 7)) 17 | println(UniquePaths().uniquePaths(3, 2)) 18 | println(UniquePaths().uniquePaths(7, 3)) 19 | println(UniquePaths().uniquePaths(3, 3)) 20 | } 21 | } 22 | 23 | // 输入:m = 3, n = 7 24 | // 输出:28 25 | fun uniquePaths(m: Int, n: Int): Int { 26 | val path = Array(m) { IntArray(n) } 27 | path[0][0] = 1 28 | for (i in 0 until m) { 29 | for (j in 0 until n) { 30 | if (i == 0 && j == 0) continue 31 | if (i == 0 && j > 0) { 32 | path[i][j] = path[i][j - 1] 33 | } else if (i > 0 && j == 0) { 34 | path[i][j] = path[i - 1][j] 35 | } else { 36 | path[i][j] = path[i - 1][j] + path[i][j - 1] 37 | } 38 | } 39 | } 40 | return path[m - 1][n - 1] 41 | } 42 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/CanConstruct.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 383. 赎金信 5 | */ 6 | 7 | /* 8 | 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 9 | 10 | 如果可以,返回 true ;否则返回 false 。 11 | 12 | magazine 中的每个字符只能在 ransomNote 中使用一次。 13 | 14 | 15 | 16 | 示例 1: 17 | 18 | 输入:ransomNote = "a", magazine = "b" 19 | 输出:false 20 | 示例 2: 21 | 22 | 输入:ransomNote = "aa", magazine = "ab" 23 | 输出:false 24 | 示例 3: 25 | 26 | 输入:ransomNote = "aa", magazine = "aab" 27 | 输出:true 28 | 29 | 30 | 提示: 31 | 32 | 1 <= ransomNote.length, magazine.length <= 105 33 | ransomNote 和 magazine 由小写英文字母组成 34 | */ 35 | class CanConstruct { 36 | 37 | companion object { 38 | @JvmStatic 39 | fun main(args: Array) { 40 | println(CanConstruct().canConstruct("a", "b")) 41 | println(CanConstruct().canConstruct("aa", "ab")) 42 | println(CanConstruct().canConstruct("aa", "aab")) 43 | } 44 | } 45 | 46 | fun canConstruct(ransomNote: String, magazine: String): Boolean { 47 | val map = hashMapOf() 48 | for (item in ransomNote) { 49 | map[item] = map.getOrDefault(item, 0) + 1 50 | } 51 | 52 | for (item in magazine) { 53 | if (map[item] != null) { 54 | map[item] = map.getOrDefault(item, 0) - 1 55 | if (map[item] == 0) { 56 | map.remove(item) 57 | if (map.size == 0) return true 58 | } 59 | } 60 | } 61 | 62 | return false 63 | } 64 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/CanJump.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import kotlin.math.max 4 | 5 | /** 6 | * 55. 跳跃游戏 7 | */ 8 | 9 | /* 10 | 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 11 | 12 | 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 13 | 14 | 15 | 16 | 示例 1: 17 | 18 | 输入:nums = [2,3,1,1,4] 19 | 输出:true 20 | 解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。 21 | 示例 2: 22 | 23 | 输入:nums = [3,2,1,0,4] 24 | 输出:false 25 | 解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。 26 | 27 | 28 | 提示: 29 | 30 | 1 <= nums.length <= 104 31 | 0 <= nums[i] <= 105 32 | */ 33 | class CanJump { 34 | companion object { 35 | @JvmStatic 36 | fun main(args: Array) { 37 | println(CanJump().canJump(intArrayOf(2, 3, 1, 1, 4))) 38 | println(CanJump().canJump(intArrayOf(3, 2, 1, 0, 4))) 39 | println(CanJump().canJump(intArrayOf(1, 13, 1, 1, 4))) 40 | } 41 | } 42 | 43 | fun canJump(nums: IntArray): Boolean { 44 | var k = 0 45 | for (i in nums.indices) { 46 | if (i > k) return false 47 | k = max(k, i + nums[i]) 48 | } 49 | return true 50 | } 51 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/Candy.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import kotlin.math.max 4 | 5 | /** 6 | * 135. 分发糖果 7 | */ 8 | 9 | /* 10 | n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 11 | 12 | 你需要按照以下要求,给这些孩子分发糖果: 13 | 14 | 每个孩子至少分配到 1 个糖果。 15 | 相邻两个孩子评分更高的孩子会获得更多的糖果。 16 | 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。 17 | 18 | 19 | 20 | 示例 1: 21 | 22 | 输入:ratings = [1,0,2] 23 | 输出:5 24 | 解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。 25 | 示例 2: 26 | 27 | 输入:ratings = [1,2,2] 28 | 输出:4 29 | 解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。 30 | 第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。 31 | 32 | 33 | 提示: 34 | 35 | n == ratings.length 36 | 1 <= n <= 2 * 104 37 | 0 <= ratings[i] <= 2 * 104 38 | */ 39 | class Candy { 40 | 41 | companion object { 42 | @JvmStatic 43 | fun main(args: Array) { 44 | println(Candy().candy(intArrayOf(1,0,2))) 45 | println(Candy().candy(intArrayOf(1,2,2))) 46 | } 47 | } 48 | 49 | fun candy(ratings: IntArray): Int { 50 | val n = ratings.size 51 | val left = IntArray(n) 52 | var count = 0 53 | for (i in 0 until n) { 54 | if (i > 0 && ratings[i] > ratings[i - 1]) { 55 | left[i] = left[i - 1] + 1 56 | } else { 57 | left[i] = 1 58 | } 59 | } 60 | 61 | var r = 1 62 | for (j in n - 1 downTo 0) { 63 | if (j < n - 1 && ratings[j] > ratings[j + 1]) { 64 | r++ 65 | } else { 66 | r = 1 67 | } 68 | count += max(left[j], r) 69 | } 70 | return count 71 | } 72 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/CheckInclusion.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 567. 字符串的排列 5 | */ 6 | 7 | /* 8 | 给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。 9 | 10 | 换句话说,s1 的排列之一是 s2 的 子串 。 11 | 12 | 13 | 14 | 示例 1: 15 | 16 | 输入:s1 = "ab" s2 = "eidbaooo" 17 | 输出:true 18 | 解释:s2 包含 s1 的排列之一 ("ba"). 19 | 示例 2: 20 | 21 | 输入:s1= "ab" s2 = "eidboaoo" 22 | 输出:false 23 | 24 | 25 | 提示: 26 | 27 | 1 <= s1.length, s2.length <= 104 28 | s1 和 s2 仅包含小写字母 29 | */ 30 | class CheckInclusion { 31 | 32 | companion object { 33 | @JvmStatic 34 | fun main(args: Array) { 35 | println(CheckInclusion().checkInclusion("ab", "eidbaooo")) 36 | } 37 | } 38 | 39 | /** 40 | * O(n + m + 字母集) 41 | * O(字母集) 42 | */ 43 | fun checkInclusion(s1: String, s2: String): Boolean { 44 | val n = s1.length 45 | val m = s2.length 46 | if (n > m) return false 47 | val ct1 = IntArray(26) 48 | val ct2 = IntArray(26) 49 | for (i in 0 until n) { 50 | ct1[s1[i] - 'a']++ 51 | ct2[s2[i] - 'a']++ 52 | } 53 | if (ct1.contentEquals(ct2)) { 54 | return true 55 | } 56 | 57 | for (j in n until m) { 58 | ct2[s2[j] - 'a']++ 59 | ct2[s2[j - n] - 'a']-- 60 | if (ct1.contentEquals(ct2)) return true 61 | } 62 | return false 63 | } 64 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/ClimbStairs.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 70. 爬楼梯 5 | */ 6 | 7 | /* 8 | 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 9 | 10 | 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 11 | 12 | 示例 1: 13 | 14 | 输入:n = 2 15 | 输出:2 16 | 解释:有两种方法可以爬到楼顶。 17 | 1. 1 阶 + 1 阶 18 | 2. 2 阶 19 | 示例 2: 20 | 21 | 输入:n = 3 22 | 输出:3 23 | 解释:有三种方法可以爬到楼顶。 24 | 1. 1 阶 + 1 阶 + 1 阶 25 | 2. 1 阶 + 2 阶 26 | 3. 2 阶 + 1 阶 27 | 28 | 提示: 29 | 30 | 1 <= n <= 45 31 | */ 32 | class ClimbStairs { 33 | 34 | companion object { 35 | @JvmStatic 36 | fun main(args: Array) { 37 | println(ClimbStairs().climbStairs(2)) 38 | println(ClimbStairs().climbStairs(3)) 39 | } 40 | } 41 | 42 | /** 43 | * O(n) 44 | * O(n) 45 | */ 46 | fun climbStairs(n: Int): Int { 47 | if (n == 1) return 1 48 | if (n == 2) return 2 49 | val dp = IntArray(n + 1) 50 | dp[1] = 1 51 | dp[2] = 2 52 | for (i in 3..n) { 53 | dp[i] = dp[i - 1] + dp[i - 2] 54 | } 55 | return dp[n] 56 | } 57 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/Convert.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import java.lang.StringBuilder 4 | 5 | /** 6 | * 6. Z 字形变换 7 | */ 8 | 9 | /* 10 | 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。 11 | 12 | 比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下: 13 | 14 | P A H N 15 | A P L S I I G 16 | Y I R 17 | 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"PAHNAPLSIIGYIR"。 18 | 19 | 请你实现这个将字符串进行指定行数变换的函数: 20 | 21 | string convert(string s, int numRows); 22 | 23 | 24 | 示例 1: 25 | 26 | 输入:s = "PAYPALISHIRING", numRows = 3 27 | 输出:"PAHNAPLSIIGYIR" 28 | 示例 2: 29 | 输入:s = "PAYPALISHIRING", numRows = 4 30 | 输出:"PINALSIGYAHRPI" 31 | 解释: 32 | P I N 33 | A L S I G 34 | Y A H R 35 | P I 36 | 示例 3: 37 | 38 | 输入:s = "A", numRows = 1 39 | 输出:"A" 40 | 41 | 42 | 提示: 43 | 44 | 1 <= s.length <= 1000 45 | s 由英文字母(小写和大写)、',' 和 '.' 组成 46 | 1 <= numRows <= 1000 47 | */ 48 | class Convert { 49 | 50 | companion object { 51 | 52 | @JvmStatic 53 | fun main(args: Array) { 54 | println(Convert().convert("PAYPALISHIRING", 3)) 55 | println(Convert().convert("PAYPALISHIRING", 4)) 56 | println(Convert().convert("A", 1)) 57 | } 58 | } 59 | 60 | fun convert(s: String, numRows: Int): String { 61 | if (numRows < 2) return s 62 | val result = StringBuilder() 63 | val rowsArray = Array(numRows) { StringBuilder() } 64 | var flag = -1 65 | var i = 0 66 | for (item in s) { 67 | if (i == 0 || i == numRows - 1) flag = -flag 68 | rowsArray[i].append(item) 69 | i += flag 70 | } 71 | for (item in rowsArray) { 72 | result.append(item) 73 | } 74 | return result.toString() 75 | } 76 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/CountNodes.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import com.daily.algothrim.leetcode.TreeNode 4 | 5 | /** 6 | * 222. 完全二叉树的节点个数 7 | */ 8 | 9 | /* 10 | 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。 11 | 12 | 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。 13 | 14 | 示例 1: 15 | 16 | 输入:root = [1,2,3,4,5,6] 17 | 输出:6 18 | 示例 2: 19 | 20 | 输入:root = [] 21 | 输出:0 22 | 示例 3: 23 | 24 | 输入:root = [1] 25 | 输出:1 26 | 27 | 提示: 28 | 29 | 树中节点的数目范围是[0, 5 * 104] 30 | 0 <= Node.val <= 5 * 104 31 | 题目数据保证输入的树是 完全二叉树 32 | 33 | 进阶:遍历树来统计节点是一种时间复杂度为 O(n) 的简单解决方案。你可以设计一个更快的算法吗? 34 | */ 35 | class CountNodes { 36 | 37 | companion object { 38 | @JvmStatic 39 | fun main(args: Array) { 40 | println(CountNodes().countNodes(TreeNode(1).apply { 41 | left = TreeNode(2).apply { 42 | left = TreeNode(4) 43 | right = TreeNode(5) 44 | } 45 | right = TreeNode(3).apply { 46 | left = TreeNode(6) 47 | } 48 | })) 49 | } 50 | } 51 | 52 | private var count = 0 53 | 54 | /** 55 | * O(n) 56 | * O(n) 57 | */ 58 | fun countNodes(root: TreeNode?): Int { 59 | dfs(root) 60 | return count 61 | } 62 | 63 | private fun dfs(root: TreeNode?) { 64 | if (root == null) return 65 | count++ 66 | countNodes(root.left) 67 | countNodes(root.right) 68 | } 69 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/FindKthLargest.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 215. 数组中的第K个最大元素 5 | */ 6 | /* 7 | 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 8 | 9 | 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 10 | 11 | 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 12 | 13 | 14 | 15 | 示例 1: 16 | 17 | 输入: [3,2,1,5,6,4], k = 2 18 | 输出: 5 19 | 示例 2: 20 | 21 | 输入: [3,2,3,1,2,4,5,5,6], k = 4 22 | 输出: 4 23 | 24 | 25 | 提示: 26 | 27 | 1 <= k <= nums.length <= 105 28 | -104 <= nums[i] <= 104 29 | */ 30 | class FindKthLargest { 31 | 32 | companion object { 33 | @JvmStatic 34 | fun main(args: Array) { 35 | println(FindKthLargest().findKthLargest(intArrayOf(3, 2, 1, 5, 6, 4), 2)) 36 | println(FindKthLargest().findKthLargest(intArrayOf(3, 2, 3, 1, 2, 4, 5, 5, 6), 4)) 37 | } 38 | } 39 | 40 | /** 41 | * O(n) 42 | * O(logn) 43 | */ 44 | fun findKthLargest(nums: IntArray, k: Int): Int { 45 | return quickSort(nums, 0, nums.size - 1, nums.size - k) 46 | } 47 | 48 | private fun quickSort(nums: IntArray, l: Int, r: Int, k: Int): Int { 49 | if (l == r) return nums[k] 50 | var i = l - 1 51 | var j = r + 1 52 | val x = nums[l] 53 | 54 | while (i < j) { 55 | do { 56 | i++ 57 | } while (nums[i] < x) 58 | do { 59 | j-- 60 | } while (nums[j] > x) 61 | if (i < j) { 62 | val temp = nums[i] 63 | nums[i] = nums[j] 64 | nums[j] = temp 65 | } 66 | } 67 | return if (k <= j) quickSort(nums, l, j, k) else quickSort(nums, j + 1, r, k) 68 | } 69 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/GetMinimumDifference.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import com.daily.algothrim.leetcode.TreeNode 4 | import kotlin.math.min 5 | 6 | /** 7 | * 530. 二叉搜索树的最小绝对差 8 | */ 9 | 10 | /* 11 | 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。 12 | 13 | 差值是一个正数,其数值等于两值之差的绝对值。 14 | 15 | 16 | 17 | 示例 1: 18 | 19 | 20 | 输入:root = [4,2,6,1,3] 21 | 输出:1 22 | 示例 2: 23 | 24 | 25 | 输入:root = [1,0,48,null,null,12,49] 26 | 输出:1 27 | 28 | 29 | 提示: 30 | 31 | 树中节点的数目范围是 [2, 104] 32 | 0 <= Node.val <= 105 33 | */ 34 | class GetMinimumDifference { 35 | 36 | companion object { 37 | @JvmStatic 38 | fun main(args: Array) { 39 | println(GetMinimumDifference().getMinimumDifference(TreeNode(4).apply { 40 | left = TreeNode(2).apply { 41 | left = TreeNode(1) 42 | right = TreeNode(3) 43 | } 44 | right = TreeNode(6) 45 | })) 46 | } 47 | } 48 | 49 | private var minResult = Int.MAX_VALUE 50 | private var pre = -1 51 | 52 | fun getMinimumDifference(root: TreeNode?): Int { 53 | inOrderTraversal(root) 54 | return minResult 55 | } 56 | 57 | /** 58 | * O(n) 59 | * O(n) 60 | */ 61 | private fun inOrderTraversal(root: TreeNode?) { 62 | if (root == null) return 63 | inOrderTraversal(root.left) 64 | if (pre == -1) { 65 | pre = root.`val` 66 | } else { 67 | minResult = min(minResult, root.`val` - pre) 68 | pre = root.`val` 69 | } 70 | inOrderTraversal(root.right) 71 | } 72 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/HIndex.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 274. H 指数 5 | */ 6 | /* 7 | 给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。 8 | 9 | 根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。 10 | 11 | 12 | 13 | 示例 1: 14 | 15 | 输入:citations = [3,0,6,1,5] 16 | 输出:3 17 | 解释:给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 3, 0, 6, 1, 5 次。 18 | 由于研究者有 3 篇论文每篇 至少 被引用了 3 次,其余两篇论文每篇被引用 不多于 3 次,所以她的 h 指数是 3。 19 | 示例 2: 20 | 21 | 输入:citations = [1,3,1] 22 | 输出:1 23 | 24 | 25 | 提示: 26 | 27 | n == citations.length 28 | 1 <= n <= 5000 29 | 0 <= citations[i] <= 1000 30 | */ 31 | class HIndex { 32 | 33 | companion object { 34 | @JvmStatic 35 | fun main(args: Array) { 36 | println(HIndex().hIndex(intArrayOf(3, 0, 6, 1, 5))) 37 | println(HIndex().hIndex(intArrayOf(1, 3, 1))) 38 | } 39 | } 40 | 41 | // citations = [3,0,6,1,5] 42 | fun hIndex(citations: IntArray): Int { 43 | citations.sort() 44 | var i = citations.size - 1 45 | var h = 0 46 | while (i >= 0 && citations[i] > h) { 47 | h++ 48 | i-- 49 | } 50 | return h 51 | } 52 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/InvertTree.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import com.daily.algothrim.leetcode.TreeNode 4 | 5 | /** 6 | * 226. 翻转二叉树 7 | */ 8 | 9 | /* 10 | 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 11 | 12 | 示例 1: 13 | 14 | 输入:root = [4,2,7,1,3,6,9] 15 | 输出:[4,7,2,9,6,3,1] 16 | 示例 2: 17 | 18 | 输入:root = [2,1,3] 19 | 输出:[2,3,1] 20 | 示例 3: 21 | 22 | 输入:root = [] 23 | 输出:[] 24 | 25 | 提示: 26 | 27 | 树中节点数目范围在 [0, 100] 内 28 | -100 <= Node.val <= 100 29 | */ 30 | class InvertTree { 31 | 32 | companion object { 33 | @JvmStatic 34 | fun main(args: Array) { 35 | 36 | } 37 | } 38 | 39 | /** 40 | * O(n) 41 | * O(n) 42 | */ 43 | fun invertTree(root: TreeNode?): TreeNode? { 44 | if (root == null) return null 45 | val left = invertTree(root.left) 46 | val right = invertTree(root.right) 47 | root.left = right 48 | root.right = left 49 | return root 50 | } 51 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/IsAnagram.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 242. 有效的字母异位词 5 | */ 6 | 7 | /* 8 | 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 9 | 10 | 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。 11 | 12 | 13 | 14 | 示例 1: 15 | 16 | 输入: s = "anagram", t = "nagaram" 17 | 输出: true 18 | 示例 2: 19 | 20 | 输入: s = "rat", t = "car" 21 | 输出: false 22 | 23 | 24 | 提示: 25 | 26 | 1 <= s.length, t.length <= 5 * 104 27 | s 和 t 仅包含小写字母 28 | 29 | 30 | 进阶: 如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况? 31 | */ 32 | class IsAnagram { 33 | 34 | companion object { 35 | @JvmStatic 36 | fun main(args: Array) { 37 | println(IsAnagram().isAnagram("anagram", "nagaram")) 38 | println(IsAnagram().isAnagram("rat", "car")) 39 | } 40 | } 41 | 42 | fun isAnagram(s: String, t: String): Boolean { 43 | if (s.length != t.length) return false 44 | val map = hashMapOf() 45 | for (item in s) { 46 | map[item] = map.getOrDefault(item, 0) + 1 47 | } 48 | for (item in t) { 49 | if (!map.containsKey(item)) return false 50 | if (map.getOrDefault(item, 0) == 1) { 51 | map.remove(item) 52 | } else { 53 | map[item] = map.getOrDefault(item, 0) - 1 54 | } 55 | } 56 | return map.size == 0 57 | } 58 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/IsIsomorphic.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 205. 同构字符串 5 | */ 6 | 7 | /* 8 | 给定两个字符串 s 和 t ,判断它们是否是同构的。 9 | 10 | 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。 11 | 12 | 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。 13 | 14 | 15 | 16 | 示例 1: 17 | 18 | 输入:s = "egg", t = "add" 19 | 输出:true 20 | 示例 2: 21 | 22 | 输入:s = "foo", t = "bar" 23 | 输出:false 24 | 示例 3: 25 | 26 | 输入:s = "paper", t = "title" 27 | 输出:true 28 | 29 | 30 | 提示: 31 | 32 | 1 <= s.length <= 5 * 104 33 | t.length == s.length 34 | s 和 t 由任意有效的 ASCII 字符组成 35 | */ 36 | class IsIsomorphic { 37 | 38 | companion object { 39 | @JvmStatic 40 | fun main(args: Array) { 41 | println(IsIsomorphic().isIsomorphic("egg", "add")) 42 | println(IsIsomorphic().isIsomorphic("foo", "bar")) 43 | println(IsIsomorphic().isIsomorphic("paper", "title")) 44 | println(IsIsomorphic().isIsomorphic("badc", "baba")) 45 | } 46 | } 47 | 48 | fun isIsomorphic(s: String, t: String): Boolean { 49 | val sMap = hashMapOf() 50 | val tMap = hashMapOf() 51 | 52 | for (i in s.indices) { 53 | if (sMap.containsKey(s[i]) && sMap[s[i]] != t[i] || tMap.containsKey(t[i]) && tMap[t[i]] != s[i]) return false 54 | sMap[s[i]] = t[i] 55 | tMap[t[i]] = s[i] 56 | } 57 | 58 | return true 59 | } 60 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/IsPalindrome.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 125. 验证回文串 5 | */ 6 | 7 | /* 8 | 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 9 | 10 | 字母和数字都属于字母数字字符。 11 | 12 | 给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。 13 | 14 | 15 | 16 | 示例 1: 17 | 18 | 输入: s = "A man, a plan, a canal: Panama" 19 | 输出:true 20 | 解释:"amanaplanacanalpanama" 是回文串。 21 | 示例 2: 22 | 23 | 输入:s = "race a car" 24 | 输出:false 25 | 解释:"raceacar" 不是回文串。 26 | 示例 3: 27 | 28 | 输入:s = " " 29 | 输出:true 30 | 解释:在移除非字母数字字符之后,s 是一个空字符串 "" 。 31 | 由于空字符串正着反着读都一样,所以是回文串。 32 | 33 | 34 | 提示: 35 | 36 | 1 <= s.length <= 2 * 105 37 | s 仅由可打印的 ASCII 字符组成 38 | */ 39 | class IsPalindrome { 40 | 41 | companion object { 42 | @JvmStatic 43 | fun main(args: Array) { 44 | println(IsPalindrome().isPalindrome("A man, a plan, a canal: Panama")) 45 | println(IsPalindrome().isPalindrome("race a car")) 46 | println(IsPalindrome().isPalindrome(" ")) 47 | println(IsPalindrome().isPalindrome("0P")) 48 | } 49 | } 50 | 51 | fun isPalindrome(s: String): Boolean { 52 | val temp = s.lowercase() 53 | var start = 0 54 | var end = temp.length - 1 55 | 56 | while (start < end) { 57 | if (!temp[start].isLetterOrDigit()) { 58 | start++ 59 | continue 60 | } 61 | if (!temp[end].isLetterOrDigit()) { 62 | end-- 63 | continue 64 | } 65 | 66 | if (temp[start++] != temp[end--]) return false 67 | } 68 | return true 69 | } 70 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/IsPalindromeInt.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 9. 回文数 5 | */ 6 | 7 | /* 8 | 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 9 | 10 | 回文数 11 | 是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 12 | 13 | 例如,121 是回文,而 123 不是。 14 | 15 | 16 | 示例 1: 17 | 18 | 输入:x = 121 19 | 输出:true 20 | 示例 2: 21 | 22 | 输入:x = -121 23 | 输出:false 24 | 解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 25 | 示例 3: 26 | 27 | 输入:x = 10 28 | 输出:false 29 | 解释:从右向左读, 为 01 。因此它不是一个回文数。 30 | 31 | 提示: 32 | 33 | -231 <= x <= 231 - 1 34 | 35 | 进阶:你能不将整数转为字符串来解决这个问题吗? 36 | */ 37 | class IsPalindromeInt { 38 | 39 | companion object { 40 | @JvmStatic 41 | fun main(args: Array) { 42 | println(IsPalindromeInt().isPalindrome(121)) 43 | println(IsPalindromeInt().isPalindrome(-121)) 44 | println(IsPalindromeInt().isPalindrome(10)) 45 | } 46 | } 47 | 48 | /** 49 | * O(logn) 50 | * O(1) 51 | */ 52 | fun isPalindrome(x: Int): Boolean { 53 | if (x < 0 || (x % 10 == 0 && x != 0)) return false 54 | 55 | var reverseInt = 0 56 | var temp = x 57 | 58 | while (temp > reverseInt) { 59 | reverseInt = reverseInt * 10 + temp % 10 60 | temp /= 10 61 | } 62 | 63 | return temp == reverseInt || temp == reverseInt / 10 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/IsSameTree.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import com.daily.algothrim.leetcode.TreeNode 4 | 5 | /** 6 | * 100. 相同的树 7 | */ 8 | 9 | /* 10 | 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 11 | 12 | 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 13 | 14 | 示例 1: 15 | 16 | 输入:p = [1,2,3], q = [1,2,3] 17 | 输出:true 18 | 示例 2: 19 | 20 | 21 | 输入:p = [1,2], q = [1,null,2] 22 | 输出:false 23 | 示例 3: 24 | 25 | 26 | 输入:p = [1,2,1], q = [1,1,2] 27 | 输出:false 28 | 29 | 30 | 提示: 31 | 32 | 两棵树上的节点数目都在范围 [0, 100] 内 33 | -104 <= Node.val <= 104 34 | */ 35 | 36 | class IsSameTree { 37 | 38 | companion object { 39 | @JvmStatic 40 | fun main(args: Array) { 41 | println(IsSameTree().isSameTree(TreeNode(1).apply { 42 | left = TreeNode(2) 43 | right = TreeNode(3) 44 | }, TreeNode(1).apply { 45 | left = TreeNode(2) 46 | right = TreeNode(3) 47 | })) 48 | println(IsSameTree().isSameTree(TreeNode(1).apply { 49 | left = TreeNode(2) 50 | }, TreeNode(1).apply { 51 | right = TreeNode(2) 52 | })) 53 | } 54 | } 55 | 56 | /** 57 | * O(min(n, m)) n,m二叉树节点数 58 | * O(min(n, m)) 不会超过最小二叉树的高度,最坏情况下高度等于节点数 59 | */ 60 | fun isSameTree(p: TreeNode?, q: TreeNode?): Boolean { 61 | if (p == null && q == null) return true 62 | if (p == null || q == null) return false 63 | if (p.`val` != q.`val`) return false 64 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right) 65 | } 66 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/IsSubsequence.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 392. 判断子序列 5 | */ 6 | 7 | /* 8 | 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 9 | 10 | 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。 11 | 12 | 进阶: 13 | 14 | 如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码? 15 | 16 | 致谢: 17 | 18 | 特别感谢 @pbrother 添加此问题并且创建所有测试用例。 19 | 20 | 21 | 22 | 示例 1: 23 | 24 | 输入:s = "abc", t = "ahbgdc" 25 | 输出:true 26 | 示例 2: 27 | 28 | 输入:s = "axc", t = "ahbgdc" 29 | 输出:false 30 | 31 | 32 | 提示: 33 | 34 | 0 <= s.length <= 100 35 | 0 <= t.length <= 10^4 36 | 两个字符串都只由小写字符组成。 37 | */ 38 | class IsSubsequence { 39 | 40 | companion object { 41 | @JvmStatic 42 | fun main(args: Array) { 43 | println(IsSubsequence().isSubsequence("abc", "ahbgdc")) 44 | println(IsSubsequence().isSubsequence("axc", "ahbgdc")) 45 | println(IsSubsequence().isSubsequence("", "ahbgdc")) 46 | } 47 | } 48 | 49 | fun isSubsequence(s: String, t: String): Boolean { 50 | val sSize = s.length 51 | val tSize = t.length 52 | if (sSize > tSize) return false 53 | if (sSize == 0) return true 54 | 55 | var i = 0 56 | var j = 0 57 | while (i < tSize && j < sSize) { 58 | if (t[i] == s[j]) { 59 | j++ 60 | } 61 | i++ 62 | } 63 | return j == sSize 64 | } 65 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/IsValid.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import java.util.Stack 4 | 5 | /** 6 | * 20. 有效的括号 7 | */ 8 | 9 | /* 10 | 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。 11 | 12 | 有效字符串需满足: 13 | 14 | 左括号必须用相同类型的右括号闭合。 15 | 左括号必须以正确的顺序闭合。 16 | 每个右括号都有一个对应的相同类型的左括号。 17 | 18 | 19 | 示例 1: 20 | 21 | 输入:s = "()" 22 | 输出:true 23 | 示例 2: 24 | 25 | 输入:s = "()[]{}" 26 | 输出:true 27 | 示例 3: 28 | 29 | 输入:s = "(]" 30 | 输出:false 31 | 32 | 33 | 提示: 34 | 35 | 1 <= s.length <= 104 36 | s 仅由括号 '()[]{}' 组成 37 | */ 38 | class IsValid { 39 | 40 | companion object { 41 | @JvmStatic 42 | fun main(args: Array) { 43 | println(IsValid().isValid("()")) 44 | println(IsValid().isValid("()[]{}")) 45 | println(IsValid().isValid("(]")) 46 | println(IsValid().isValid("(())")) 47 | } 48 | } 49 | 50 | fun isValid(s: String): Boolean { 51 | val stack = Stack() 52 | 53 | for (item in s) { 54 | if (item == '(' || item == '{' || item == '[') { 55 | stack.push(item) 56 | } else if (stack.empty() || (item == ')' && stack.peek() != '(' 57 | || item == '}' && stack.peek() != '{' 58 | || item == ']' && stack.peek() != '[') 59 | ) { 60 | return false 61 | } else { 62 | stack.pop() 63 | } 64 | } 65 | return stack.isEmpty() 66 | } 67 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/Jump.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 45. 跳跃游戏 II 5 | */ 6 | 7 | /* 8 | 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 9 | 10 | 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处: 11 | 12 | 0 <= j <= nums[i] 13 | i + j < n 14 | 返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。 15 | 16 | 17 | 18 | 示例 1: 19 | 20 | 输入: nums = [2,3,1,1,4] 21 | 输出: 2 22 | 解释: 跳到最后一个位置的最小跳跃数是 2。 23 | 从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。 24 | 示例 2: 25 | 26 | 输入: nums = [2,3,0,1,4] 27 | 输出: 2 28 | 29 | 30 | 提示: 31 | 32 | 1 <= nums.length <= 104 33 | 0 <= nums[i] <= 1000 34 | 题目保证可以到达 nums[n-1] 35 | */ 36 | import kotlin.math.max 37 | 38 | class Jump { 39 | 40 | companion object { 41 | @JvmStatic 42 | fun main(args: Array) { 43 | println(Jump().jump(intArrayOf(2, 3, 1, 1, 4))) 44 | println(Jump().jump(intArrayOf(2, 3, 0, 1, 4))) 45 | } 46 | } 47 | 48 | fun jump(nums: IntArray): Int { 49 | var step = 0 50 | var maxPosition = 0 51 | var end = 0 52 | for (i in 0 until nums.size - 1) { 53 | maxPosition = max(maxPosition, i + nums[i]) 54 | if (i == end) { 55 | end = maxPosition 56 | step++ 57 | } 58 | } 59 | return step 60 | } 61 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/LargestNumber.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 179. 最大数 5 | */ 6 | 7 | /* 8 | 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数。 9 | 10 | 注意:输出结果可能非常大,所以你需要返回一个字符串而不是整数。 11 | 12 | 13 | 14 | 示例 1: 15 | 16 | 输入:nums = [10,2] 17 | 输出:"210" 18 | 示例 2: 19 | 20 | 输入:nums = [3,30,34,5,9] 21 | 输出:"9534330" 22 | 23 | 24 | 提示: 25 | 26 | 1 <= nums.length <= 100 27 | 0 <= nums[i] <= 109 28 | */ 29 | 30 | class LargestNumber { 31 | 32 | companion object { 33 | @JvmStatic 34 | fun main(args: Array) { 35 | println(LargestNumber().largestNumber(intArrayOf(10, 2))) 36 | println(LargestNumber().largestNumber(intArrayOf(3, 30, 34, 5, 9))) 37 | println(LargestNumber().largestNumber(intArrayOf(1000000000, 1000000000))) 38 | } 39 | } 40 | 41 | /** 42 | * O(nlognlogm) n 序列长度,m32位整数最大值 43 | * O(logn) 44 | */ 45 | fun largestNumber(nums: IntArray): String { 46 | if (nums.isEmpty()) return "" 47 | val list = nums.sortedWith { x, y -> 48 | (y.toString() + x.toString()).compareTo((x.toString() + y.toString())) 49 | } 50 | if (list[0] == 0) return "0" 51 | return StringBuilder().apply { 52 | list.forEach { 53 | append(it) 54 | } 55 | }.toString() 56 | } 57 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/LengthOfLastWord.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 58. 最后一个单词的长度 5 | */ 6 | 7 | /* 8 | 给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 9 | 10 | 单词 是指仅由字母组成、不包含任何空格字符的最大 11 | 子字符串 12 | 。 13 | 14 | 15 | 16 | 示例 1: 17 | 18 | 输入:s = "Hello World" 19 | 输出:5 20 | 解释:最后一个单词是“World”,长度为5。 21 | 示例 2: 22 | 23 | 输入:s = " fly me to the moon " 24 | 输出:4 25 | 解释:最后一个单词是“moon”,长度为4。 26 | 示例 3: 27 | 28 | 输入:s = "luffy is still joyboy" 29 | 输出:6 30 | 解释:最后一个单词是长度为6的“joyboy”。 31 | 32 | 33 | 提示: 34 | 35 | 1 <= s.length <= 104 36 | s 仅有英文字母和空格 ' ' 组成 37 | s 中至少存在一个单词 38 | */ 39 | class LengthOfLastWord { 40 | 41 | companion object { 42 | @JvmStatic 43 | fun main(args: Array) { 44 | println(LengthOfLastWord().lengthOfLastWord("Hello World")) 45 | println(LengthOfLastWord().lengthOfLastWord(" fly me to the moon ")) 46 | println(LengthOfLastWord().lengthOfLastWord("luffy is still joyboy")) 47 | } 48 | } 49 | 50 | fun lengthOfLastWord(s: String): Int { 51 | var end = s.length - 1 52 | while (end >= 0 && s[end] == ' ') end-- 53 | if (end < 0) return 0 54 | var start = end 55 | while (start >= 0 && s[start] != ' ') start-- 56 | return end - start 57 | } 58 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/LongestCommonPrefix.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import kotlin.math.min 4 | 5 | /** 6 | * 14. 最长公共前缀 7 | */ 8 | 9 | /* 10 | 编写一个函数来查找字符串数组中的最长公共前缀。 11 | 12 | 如果不存在公共前缀,返回空字符串 ""。 13 | 14 | 15 | 16 | 示例 1: 17 | 18 | 输入:strs = ["flower","flow","flight"] 19 | 输出:"fl" 20 | 示例 2: 21 | 22 | 输入:strs = ["dog","racecar","car"] 23 | 输出:"" 24 | 解释:输入不存在公共前缀。 25 | 26 | 27 | 提示: 28 | 29 | 1 <= strs.length <= 200 30 | 0 <= strs[i].length <= 200 31 | strs[i] 仅由小写英文字母组成 32 | */ 33 | class LongestCommonPrefix { 34 | 35 | companion object { 36 | @JvmStatic 37 | fun main(args: Array) { 38 | println(LongestCommonPrefix().longestCommonPrefix(arrayOf("flower","flow","flight"))) 39 | println(LongestCommonPrefix().longestCommonPrefix(arrayOf("dog","racecar","car"))) 40 | } 41 | } 42 | 43 | fun longestCommonPrefix(strs: Array): String { 44 | var result = strs[0] 45 | for (i in 1 until strs.size) { 46 | val minLength = min(result.length, strs[i].length) 47 | var j = 0 48 | while (j < minLength) { 49 | if (result[j] != strs[i][j]) break 50 | j++ 51 | } 52 | result = result.substring(0, j) 53 | if (result.isEmpty()) break 54 | } 55 | return result 56 | } 57 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/LongestConsecutive.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import kotlin.math.max 4 | 5 | /** 6 | * 128. 最长连续序列 7 | */ 8 | 9 | /* 10 | 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 11 | 12 | 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 13 | 14 | 15 | 16 | 示例 1: 17 | 18 | 输入:nums = [100,4,200,1,3,2] 19 | 输出:4 20 | 解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。 21 | 示例 2: 22 | 23 | 输入:nums = [0,3,7,2,5,8,4,6,0,1] 24 | 输出:9 25 | 26 | 27 | 提示: 28 | 29 | 0 <= nums.length <= 105 30 | -109 <= nums[i] <= 109 31 | */ 32 | 33 | class LongestConsecutive { 34 | 35 | companion object { 36 | @JvmStatic 37 | fun main(args: Array) { 38 | println(LongestConsecutive().longestConsecutive(intArrayOf(100, 4, 200, 1, 3, 2))) 39 | println(LongestConsecutive().longestConsecutive(intArrayOf(0, 3, 7, 2, 5, 8, 4, 6, 0, 1))) 40 | } 41 | } 42 | 43 | fun longestConsecutive(nums: IntArray): Int { 44 | val set = hashSetOf() 45 | for (item in nums) { 46 | set.add(item) 47 | } 48 | 49 | var maxLength = 0 50 | for (item in set) { 51 | if (!set.contains(item - 1)) { 52 | var curr = item 53 | var count = 1 54 | while (set.contains(curr + 1)) { 55 | count++ 56 | curr++ 57 | } 58 | maxLength = max(maxLength, count) 59 | } 60 | } 61 | return maxLength 62 | } 63 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/MaxArea.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import kotlin.math.max 4 | import kotlin.math.min 5 | 6 | /** 7 | * 11. 盛最多水的容器 8 | */ 9 | 10 | /* 11 | 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 12 | 13 | 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 14 | 15 | 返回容器可以储存的最大水量。 16 | 17 | 说明:你不能倾斜容器。 18 | 19 | 输入:[1,8,6,2,5,4,8,3,7] 20 | 输出:49 21 | 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。 22 | 示例 2: 23 | 24 | 输入:height = [1,1] 25 | 输出:1 26 | 27 | 28 | 提示: 29 | 30 | n == height.length 31 | 2 <= n <= 105 32 | 0 <= height[i] <= 104 33 | */ 34 | class MaxArea { 35 | 36 | companion object { 37 | @JvmStatic 38 | fun main(args: Array) { 39 | println(MaxArea().maxArea(intArrayOf(1,8,6,2,5,4,8,3,7))) 40 | println(MaxArea().maxArea(intArrayOf(1, 1))) 41 | } 42 | } 43 | 44 | fun maxArea(height: IntArray): Int { 45 | val n = height.size 46 | var start = 0 47 | var end = n - 1 48 | var maxResult = 0 49 | while (start < end) { 50 | maxResult = max(min(height[start], height[end]) * (end - start), maxResult) 51 | if (height[start] > height[end]) { 52 | end-- 53 | } else { 54 | start++ 55 | } 56 | } 57 | return maxResult 58 | } 59 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/MaxDepth.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import com.daily.algothrim.leetcode.TreeNode 4 | import kotlin.math.max 5 | 6 | /** 7 | * 104. 二叉树的最大深度 8 | */ 9 | 10 | /* 11 | 给定一个二叉树 root ,返回其最大深度。 12 | 13 | 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 14 | 15 | 示例 1: 16 | 17 | 输入:root = [3,9,20,null,null,15,7] 18 | 输出:3 19 | 示例 2: 20 | 21 | 输入:root = [1,null,2] 22 | 输出:2 23 | 24 | 提示: 25 | 26 | 树中节点的数量在 [0, 104] 区间内。 27 | -100 <= Node.val <= 100 28 | */ 29 | 30 | class MaxDepth { 31 | 32 | companion object { 33 | @JvmStatic 34 | fun main(args: Array) { 35 | println(MaxDepth().maxDepth( 36 | TreeNode(3).apply { 37 | left = TreeNode(9) 38 | right = TreeNode(20).apply { 39 | left = TreeNode(15) 40 | right = TreeNode(7) 41 | } 42 | } 43 | )) 44 | println(MaxDepth().maxDepth( 45 | TreeNode(1).apply { 46 | right = TreeNode(2) 47 | } 48 | )) 49 | } 50 | } 51 | 52 | /** 53 | * O(n) 54 | * O(deep) 55 | */ 56 | fun maxDepth(root: TreeNode?): Int { 57 | return deep(root, 0) 58 | } 59 | 60 | private fun deep(node: TreeNode?, currDeep: Int): Int { 61 | if (node == null) return currDeep 62 | val left = deep(node.left, currDeep + 1) 63 | val right = deep(node.right, currDeep + 1) 64 | return max(left, right) 65 | } 66 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/MaxProfit.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | import kotlin.math.max 4 | 5 | /** 6 | * 121. 买卖股票的最佳时机 7 | */ 8 | /* 9 | 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 10 | 11 | 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 12 | 13 | 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。 14 | 15 | 16 | 17 | 示例 1: 18 | 19 | 输入:[7,1,5,3,6,4] 20 | 输出:5 21 | 解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。 22 | 注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。 23 | 示例 2: 24 | 25 | 输入:prices = [7,6,4,3,1] 26 | 输出:0 27 | 解释:在这种情况下, 没有交易完成, 所以最大利润为 0。 28 | 29 | 30 | 提示: 31 | 32 | 1 <= prices.length <= 105 33 | 0 <= prices[i] <= 104 34 | */ 35 | class MaxProfit { 36 | companion object { 37 | @JvmStatic 38 | fun main(args: Array) { 39 | println(MaxProfit().maxProfit(intArrayOf(7, 1, 5, 3, 6, 4))) 40 | println(MaxProfit().maxProfit(intArrayOf(7, 6, 4, 3, 1))) 41 | println(MaxProfit().maxProfit(intArrayOf(7, 2, 9, 3, 1, 10))) 42 | } 43 | } 44 | 45 | fun maxProfit(prices: IntArray): Int { 46 | var max = 0 47 | var i = 1 48 | var temp = prices[0] 49 | val n = prices.size 50 | while (i < n) { 51 | if (prices[i] > temp) { 52 | max = max(max, prices[i] - temp) 53 | } else { 54 | temp = prices[i] 55 | } 56 | i++ 57 | } 58 | return max 59 | } 60 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/MaxProfit2.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | 4 | /** 5 | * 122. 买卖股票的最佳时机 II 6 | */ 7 | /* 8 | 给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。 9 | 10 | 在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。 11 | 12 | 返回 你能获得的 最大 利润 。 13 | 14 | 15 | 16 | 示例 1: 17 | 18 | 输入:prices = [7,1,5,3,6,4] 19 | 输出:7 20 | 解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。 21 | 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。 22 | 总利润为 4 + 3 = 7 。 23 | 示例 2: 24 | 25 | 输入:prices = [1,2,3,4,5] 26 | 输出:4 27 | 解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。 28 | 总利润为 4 。 29 | 示例 3: 30 | 31 | 输入:prices = [7,6,4,3,1] 32 | 输出:0 33 | 解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。 34 | 35 | 36 | 提示: 37 | 38 | 1 <= prices.length <= 3 * 104 39 | 0 <= prices[i] <= 104 40 | */ 41 | class MaxProfit2 { 42 | 43 | companion object { 44 | @JvmStatic 45 | fun main(args: Array) { 46 | println(MaxProfit2().maxProfit(intArrayOf(7, 1, 5, 3, 6, 4))) 47 | println(MaxProfit2().maxProfit(intArrayOf(7, 6, 4, 3, 1))) 48 | println(MaxProfit2().maxProfit(intArrayOf(7, 2, 9, 3, 1, 10))) 49 | } 50 | } 51 | 52 | fun maxProfit(prices: IntArray): Int { 53 | var total = 0 54 | var temp = Int.MAX_VALUE 55 | for (item in prices) { 56 | if (item - temp > 0) { 57 | total += item - temp 58 | } 59 | temp = item 60 | } 61 | return total 62 | } 63 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/Merge.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 88. 合并两个有序数组 5 | */ 6 | /* 7 | 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。 8 | 9 | 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。 10 | 11 | 注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。 12 | 13 | 14 | 15 | 示例 1: 16 | 17 | 输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 18 | 输出:[1,2,2,3,5,6] 19 | 解释:需要合并 [1,2,3] 和 [2,5,6] 。 20 | 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。 21 | 示例 2: 22 | 23 | 输入:nums1 = [1], m = 1, nums2 = [], n = 0 24 | 输出:[1] 25 | 解释:需要合并 [1] 和 [] 。 26 | 合并结果是 [1] 。 27 | 示例 3: 28 | 29 | 输入:nums1 = [0], m = 0, nums2 = [1], n = 1 30 | 输出:[1] 31 | 解释:需要合并的数组是 [] 和 [1] 。 32 | 合并结果是 [1] 。 33 | 注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。 34 | */ 35 | class Merge { 36 | 37 | companion object { 38 | @JvmStatic 39 | fun main(args: Array) { 40 | val nums1 = intArrayOf(1, 2, 3, 0, 0, 0) 41 | val nums2 = intArrayOf(2, 5, 6) 42 | Merge().merge(nums1, 3, nums2, 3) 43 | nums1.forEach { 44 | println(it) 45 | } 46 | } 47 | } 48 | 49 | fun merge(nums1: IntArray, m: Int, nums2: IntArray, n: Int) { 50 | var i = m - 1 51 | var j = n - 1 52 | 53 | while (i >= 0 && j >= 0) { 54 | if (nums1[i] <= nums2[j]) { 55 | nums1[i + j + 1] = nums2[j--] 56 | } else { 57 | nums1[i + j + 1] = nums1[i--] 58 | } 59 | } 60 | while (j >= 0) { 61 | nums1[i + j + 1] = nums2[j--] 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/PermuteUnique.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 全排列 II 5 | * 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 6 | */ 7 | class PermuteUnique { 8 | 9 | companion object { 10 | @JvmStatic 11 | fun main(args: Array) { 12 | PermuteUnique().permuteUnique( 13 | intArrayOf(1, 1, 2) 14 | ).forEach { 15 | println("$it") 16 | } 17 | } 18 | } 19 | 20 | private val result = arrayListOf>() 21 | private val temp = arrayListOf() 22 | private var size = 0 23 | 24 | fun permuteUnique(nums: IntArray): List> { 25 | size = nums.size 26 | if (size == 0) return result 27 | nums.sort() 28 | val visits = BooleanArray(size) 29 | backtrace(nums, visits, 0) 30 | return result 31 | } 32 | 33 | /** 34 | * O(n * n!) 35 | * O(n) 36 | */ 37 | private fun backtrace(nums: IntArray, visits: BooleanArray, index: Int) { 38 | if (index == size) { 39 | result.add(ArrayList(temp)) 40 | return 41 | } 42 | for (i in 0 until size) { 43 | if (visits[i] || (i > 0 && nums[i] == nums[i - 1] && !visits[i - 1])) { 44 | continue 45 | } 46 | visits[i] = true 47 | temp.add(nums[i]) 48 | backtrace(nums, visits, index + 1) 49 | visits[i] = false 50 | temp.removeLast() 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/PlusOne.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 66. 加一 5 | */ 6 | 7 | /* 8 | 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。 9 | 10 | 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 11 | 12 | 你可以假设除了整数 0 之外,这个整数不会以零开头。 13 | 14 | 15 | 示例 1: 16 | 17 | 输入:digits = [1,2,3] 18 | 输出:[1,2,4] 19 | 解释:输入数组表示数字 123。 20 | 示例 2: 21 | 22 | 输入:digits = [4,3,2,1] 23 | 输出:[4,3,2,2] 24 | 解释:输入数组表示数字 4321。 25 | 示例 3: 26 | 27 | 输入:digits = [0] 28 | 输出:[1] 29 | 30 | 提示: 31 | 32 | 1 <= digits.length <= 100 33 | 0 <= digits[i] <= 9 34 | */ 35 | class PlusOne { 36 | 37 | companion object { 38 | @JvmStatic 39 | fun main(args: Array) { 40 | PlusOne().plusOne(intArrayOf(1, 2, 3)).forEach { 41 | println(it) 42 | } 43 | } 44 | } 45 | 46 | fun plusOne(digits: IntArray): IntArray { 47 | val size = digits.size 48 | for (i in size - 1 downTo 0) { 49 | if (digits[i] != 9) { 50 | digits[i]++ 51 | for (j in i + 1 until size) { 52 | digits[j] = 0 53 | } 54 | return digits 55 | } 56 | } 57 | val result = IntArray(size + 1) 58 | result[0] = 1 59 | return result 60 | } 61 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/StrStr.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 28. 找出字符串中第一个匹配项的下标 5 | */ 6 | 7 | /* 8 | 给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。 9 | 10 | 11 | 12 | 示例 1: 13 | 14 | 输入:haystack = "sadbutsad", needle = "sad" 15 | 输出:0 16 | 解释:"sad" 在下标 0 和 6 处匹配。 17 | 第一个匹配项的下标是 0 ,所以返回 0 。 18 | 示例 2: 19 | 20 | 输入:haystack = "leetcode", needle = "leeto" 21 | 输出:-1 22 | 解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1 。 23 | 24 | 25 | 提示: 26 | 27 | 1 <= haystack.length, needle.length <= 104 28 | haystack 和 needle 仅由小写英文字符组成 29 | */ 30 | class StrStr { 31 | 32 | companion object { 33 | 34 | @JvmStatic 35 | fun main(args: Array) { 36 | println(StrStr().strStr("sadbutsad", "sad")) 37 | println(StrStr().strStr("leetcode", "leeto")) 38 | println(StrStr().strStr("aaa", "aaaa")) 39 | println(StrStr().strStr("aafdaae", "aeu")) 40 | } 41 | } 42 | 43 | fun strStr(haystack: String, needle: String): Int { 44 | val hSize = haystack.length 45 | val nSize = needle.length 46 | if (hSize < nSize) return -1 47 | 48 | var i = 0 49 | var start: Int 50 | var end: Int 51 | while (i <= hSize - nSize) { 52 | start = i 53 | end = start + nSize - 1 54 | while (start <= end && haystack[start] == needle[start - i] && haystack[end] == needle[end - i]) { 55 | start++ 56 | end-- 57 | } 58 | if (start > end) return i 59 | i++ 60 | } 61 | return -1 62 | } 63 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/Trap.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 42. 接雨水 5 | */ 6 | 7 | /* 8 | 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 9 | 10 | 示例 1: 11 | 12 | 输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] 13 | 输出:6 14 | 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 15 | 示例 2: 16 | 17 | 输入:height = [4,2,0,3,2,5] 18 | 输出:9 19 | 20 | 21 | 提示: 22 | 23 | n == height.length 24 | 1 <= n <= 2 * 104 25 | 0 <= height[i] <= 105 26 | */ 27 | class Trap { 28 | 29 | companion object { 30 | @JvmStatic 31 | fun main(args: Array) { 32 | println(Trap().trap(intArrayOf(0,1,0,2,1,0,1,3,2,1,2,1))) 33 | println(Trap().trap(intArrayOf(4,2,0,3,2,5))) 34 | } 35 | } 36 | 37 | fun trap(height: IntArray): Int { 38 | var maxHeight = -1 39 | var maxIndex = 0 40 | var result = 0 41 | for (i in height.indices) { 42 | if (height[i] > maxHeight) { 43 | maxHeight = height[i] 44 | maxIndex = i 45 | } 46 | } 47 | 48 | var temp = Int.MIN_VALUE 49 | for (l in 0 until maxIndex) { 50 | if (height[l] >= temp) { 51 | temp = height[l] 52 | continue 53 | } 54 | result += temp - height[l] 55 | } 56 | 57 | temp = Int.MIN_VALUE 58 | for (r in height.size - 1 downTo maxIndex + 1) { 59 | if (height[r] >= temp) { 60 | temp = height[r] 61 | continue 62 | } 63 | result += temp - height[r] 64 | } 65 | return result 66 | } 67 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/leetcode/top150/WordPattern.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.leetcode.top150 2 | 3 | /** 4 | * 290. 单词规律 5 | */ 6 | 7 | /* 8 | 给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。 9 | 10 | 这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。 11 | 12 | 13 | 14 | 示例1: 15 | 16 | 输入: pattern = "abba", s = "dog cat cat dog" 17 | 输出: true 18 | 示例 2: 19 | 20 | 输入:pattern = "abba", s = "dog cat cat fish" 21 | 输出: false 22 | 示例 3: 23 | 24 | 输入: pattern = "aaaa", s = "dog cat cat dog" 25 | 输出: false 26 | 27 | 28 | 提示: 29 | 30 | 1 <= pattern.length <= 300 31 | pattern 只包含小写英文字母 32 | 1 <= s.length <= 3000 33 | s 只包含小写英文字母和 ' ' 34 | s 不包含 任何前导或尾随对空格 35 | s 中每个单词都被 单个空格 分隔 36 | */ 37 | class WordPattern { 38 | 39 | companion object { 40 | @JvmStatic 41 | fun main(args: Array) { 42 | println(WordPattern().wordPattern("abba", "dog cat cat dog")) 43 | println(WordPattern().wordPattern("abba", "dog cat cat fish")) 44 | println(WordPattern().wordPattern("aaaa", "dog cat cat dog")) 45 | } 46 | } 47 | 48 | fun wordPattern(pattern: String, s: String): Boolean { 49 | val pMap = hashMapOf() 50 | val sMap = hashMapOf() 51 | val ss = s.split(" ") 52 | if (ss.size != pattern.length) return false 53 | 54 | for (i in pattern.indices) { 55 | if (pMap.containsKey(pattern[i]) && pMap[pattern[i]] != ss[i] || sMap.containsKey(ss[i]) && sMap[ss[i]] != pattern[i]) return false 56 | pMap[pattern[i]] = ss[i] 57 | sMap[ss[i]] = pattern[i] 58 | } 59 | 60 | return true 61 | } 62 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/linked/LinkedNode.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked 2 | 3 | class LinkedNode(var value: T, var next: LinkedNode? = null) { 4 | 5 | fun printAll() { 6 | println("$value") 7 | var temp = next 8 | while (temp != null) { 9 | println(temp.value) 10 | temp = temp.next 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/linked/algo/Circle.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked.algo 2 | 3 | import com.daily.algothrim.linked.LinkedNode 4 | 5 | /** 6 | * 链表中环的检测 7 | * 使用快慢指针,慢指针每次走一步,快指针每次走两步;当快指针等于慢指针时,说明快指针已经领先慢指针一圈,即该链表存在环。 8 | */ 9 | class Circle { 10 | 11 | companion object { 12 | @JvmStatic 13 | fun main(args: Array) { 14 | val head = LinkedNode(1) 15 | println(Circle().existCircle(head.apply { 16 | next = LinkedNode(2).apply { 17 | next = LinkedNode(3).apply { 18 | next = LinkedNode(2).apply { 19 | next = LinkedNode(1).apply { 20 | next = head 21 | } 22 | } 23 | } 24 | } 25 | })) 26 | } 27 | } 28 | 29 | /** 30 | * O(n) 31 | */ 32 | fun existCircle(linkedList: LinkedNode?): Boolean { 33 | 34 | var slow = linkedList 35 | var fast = linkedList 36 | 37 | while (fast?.next != null) { 38 | slow = slow?.next 39 | fast = fast.next?.next 40 | if (fast == slow) return true 41 | } 42 | 43 | return false 44 | } 45 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/linked/algo/MiddleNode.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked.algo 2 | 3 | import com.daily.algothrim.linked.LinkedNode 4 | 5 | /** 6 | * 求链表的中间结点 7 | * 快慢指针 8 | */ 9 | class MiddleNode { 10 | 11 | companion object { 12 | @JvmStatic 13 | fun main(args: Array) { 14 | MiddleNode().middle(LinkedNode("a").apply { 15 | next = LinkedNode("b").apply { 16 | next = LinkedNode("c").apply { 17 | next = LinkedNode("d").apply { 18 | next = LinkedNode("e").apply { 19 | next = LinkedNode("f") 20 | } 21 | } 22 | } 23 | } 24 | })?.printAll() 25 | } 26 | } 27 | 28 | /** 29 | * O(n) 30 | */ 31 | private fun middle(singleLinked: LinkedNode?): LinkedNode? { 32 | var fast = singleLinked 33 | var slow = singleLinked 34 | 35 | while (fast?.next?.next != null) { 36 | fast = fast.next?.next 37 | slow = slow?.next 38 | } 39 | 40 | return slow 41 | } 42 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/linked/algo/Reversal.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.linked.algo 2 | 3 | import com.daily.algothrim.linked.LinkedNode 4 | 5 | /** 6 | * 单链表反转 7 | */ 8 | class Reversal { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | Reversal().reversal(LinkedNode("a").apply { 14 | next = LinkedNode("b").apply { 15 | next = LinkedNode("c").apply { 16 | next = LinkedNode("d").apply { 17 | next = LinkedNode("a") 18 | } 19 | } 20 | } 21 | })?.printAll() 22 | } 23 | } 24 | 25 | /** 26 | * O(n) 27 | */ 28 | fun reversal(singleLinked: LinkedNode?): LinkedNode? { 29 | var result: LinkedNode? = null 30 | var current = singleLinked 31 | var next: LinkedNode? 32 | 33 | while (current != null) { 34 | next = current.next 35 | current.next = result 36 | result = current 37 | current = next 38 | } 39 | return result 40 | } 41 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/lookup/BinarySearch.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup 2 | 3 | /** 4 | * 二分查找 5 | */ 6 | class BinarySearch { 7 | companion object { 8 | @JvmStatic 9 | fun main(args: Array) { 10 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 95, 213, 741) 11 | println(BinarySearch().search(a, a.size, 93)) 12 | } 13 | } 14 | 15 | /** 16 | * O(log n) 17 | */ 18 | fun search(a: IntArray, n: Int, value: Int): Int { 19 | var low = 0 20 | var high = n - 1 21 | 22 | while (low <= high) { 23 | val mid = low + (high - low).shr(1) 24 | when { 25 | a[mid] < value -> { 26 | low = mid + 1 27 | } 28 | a[mid] > value -> { 29 | high = mid - 1 30 | } 31 | else -> { 32 | return mid 33 | } 34 | } 35 | } 36 | return -1 37 | } 38 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/lookup/BinarySearchV1.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup 2 | 3 | /** 4 | * 二分查找第一个等于给定的值 5 | */ 6 | class BinarySearchV1 { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741) 12 | println(BinarySearchV1().search(a, a.size, 93)) 13 | } 14 | } 15 | 16 | /** 17 | * O(log n) 18 | */ 19 | fun search(a: IntArray, n: Int, value: Int): Int { 20 | var low = 0 21 | var high = n - 1 22 | while (low <= high) { 23 | val mid = low + (high - low).shr(1) 24 | when { 25 | a[mid] < value -> { 26 | low = mid + 1 27 | } 28 | a[mid] > value -> { 29 | high = mid - 1 30 | } 31 | else -> { 32 | if (mid == 0 || a[mid - 1] != value) return mid 33 | high = mid - 1 34 | } 35 | } 36 | } 37 | 38 | return -1 39 | } 40 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/lookup/BinarySearchV2.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup 2 | 3 | /** 4 | * 二分法查找最后一个值等于给定的值 5 | */ 6 | class BinarySearchV2 { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741) 12 | println(BinarySearchV2().search(a, a.size, 93)) 13 | } 14 | } 15 | 16 | /** 17 | * O(log n) 18 | */ 19 | fun search(a: IntArray, n: Int, value: Int): Int { 20 | var low = 0 21 | var high = n - 1 22 | 23 | while (low <= high) { 24 | val mid = low + (high - low).shr(1) 25 | when { 26 | a[mid] < value -> { 27 | low = mid + 1 28 | } 29 | a[mid] > value -> { 30 | high = mid - 1 31 | } 32 | else -> { 33 | if (mid == n - 1 || a[mid + 1] != value) return mid 34 | low = mid + 1 35 | } 36 | } 37 | } 38 | 39 | return -1 40 | } 41 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/lookup/BinarySearchV3.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup 2 | 3 | /** 4 | * 二分查找第一个大于等于给定的值 5 | */ 6 | class BinarySearchV3 { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741) 12 | println(BinarySearchV3().search(a, a.size, 93)) 13 | } 14 | } 15 | 16 | /** 17 | * O(log n) 18 | */ 19 | fun search(a: IntArray, n: Int, value: Int): Int { 20 | var low = 0 21 | var high = n - 1 22 | 23 | while (low <= high) { 24 | val mid = low + (high - low).shr(1) 25 | when { 26 | a[mid] >= value -> { 27 | if (mid == 0 || a[mid - 1] < value) return mid 28 | high = mid - 1 29 | } 30 | else -> { 31 | low = mid + 1 32 | } 33 | } 34 | } 35 | 36 | return -1 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/lookup/BinarySearchV4.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.lookup 2 | 3 | /** 4 | * 二分查找最后一个小于等于给定的值 5 | */ 6 | class BinarySearchV4 { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | val a = intArrayOf(1, 2, 4, 5, 6, 9, 29, 93, 93, 93, 95, 213, 741) 12 | println(BinarySearchV4().search(a, a.size, 93)) 13 | } 14 | } 15 | 16 | /** 17 | * O(log n) 18 | */ 19 | fun search(a: IntArray, n: Int, value: Int): Int { 20 | var low = 0 21 | var high = n - 1 22 | while (low <= high) { 23 | val mid = low + (high - low).shr(1) 24 | when { 25 | a[mid] <= value -> { 26 | if (mid == n - 1 || a[mid + 1] > value) return mid 27 | low = mid + 1 28 | } 29 | else -> { 30 | high = mid - 1 31 | } 32 | } 33 | } 34 | 35 | return -1 36 | } 37 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/queue/CircleQueue.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.queue 2 | 3 | /** 4 | * 基于数组的循环队列 5 | */ 6 | class CircleQueue(capacity: Int) { 7 | 8 | private var n = capacity 9 | private var head = 0 10 | private var tail = 0 11 | private var queue = arrayOfNulls(capacity) 12 | 13 | fun enqueue(item: String): Boolean { 14 | // 队满,会浪费一个存储空间 15 | if ((tail + 1) % n == head) return false 16 | queue[tail] = item 17 | tail = (tail + 1) % n 18 | return true 19 | } 20 | 21 | fun dequeue(): String? { 22 | if (tail == head) return null 23 | val item = queue[head] 24 | head = (head + 1) % n 25 | return item 26 | } 27 | 28 | companion object { 29 | 30 | @JvmStatic 31 | fun main(args: Array) { 32 | CircleQueue(6).apply { 33 | println(enqueue("1")) 34 | println(enqueue("2")) 35 | println(dequeue()) 36 | println(enqueue("3")) 37 | println(enqueue("4")) 38 | println(dequeue()) 39 | println(dequeue()) 40 | println(enqueue("5")) 41 | println(dequeue()) 42 | println(enqueue("6")) 43 | println(enqueue("7")) 44 | println(enqueue("8")) 45 | println(enqueue("9")) 46 | println(enqueue("10")) 47 | } 48 | } 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/recursion/KthGrammar.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.recursion 2 | 3 | /** 4 | * 第K个语法符号(LeetCode 779) 5 | * 6 | * 在第一行我们写上一个 0。接下来的每一行,将前一行中的0替换为01,1替换为10。 7 | * 8 | * 给定行数N和序数 K,返回第 N 行中第 K个字符。(K从1开始) 9 | * 10 | * 例子: 11 | * 12 | * 输入: N = 1, K = 1 13 | * 输出: 0 14 | * 15 | * 输入: N = 2, K = 1 16 | * 输出: 0 17 | * 18 | * 输入: N = 2, K = 2 19 | * 输出: 1 20 | * 21 | * 输入: N = 4, K = 5 22 | * 输出: 1 23 | * 24 | * 解释: 25 | * 第一行: 0 26 | * 第二行: 01 27 | * 第三行: 0110 28 | * 第四行: 01101001 29 | * 30 | * 注意: 31 | * 32 | * N的范围[1, 30]. 33 | * K的范围[1, 2^(N-1)]. 34 | * 35 | */ 36 | class KthGrammar { 37 | 38 | companion object { 39 | @JvmStatic 40 | fun main(args: Array) { 41 | println(KthGrammar().kthGrammar(4, 5)) 42 | println(KthGrammar().kthGrammarReverse(4, 5)) 43 | } 44 | } 45 | 46 | // 第一行: 0 47 | // 第二行: 01 48 | // 第三行: 0110 49 | // 第四行: 01101001 50 | 51 | // 第 K 个数字是上一行第 (K+1) / 2 个数字生成的。如果上一行的数字为 0,被生成的数字为 1 - (K%2),如果上一行的数字为 1,被生成的数字为 K%2 52 | // O(n) 53 | private fun kthGrammar(N: Int, K: Int): Int { 54 | if (N == 1) return 0 55 | return (K.inv() and 1) xor kthGrammar(N - 1, (K + 1) / 2) 56 | } 57 | 58 | // 每一行前一半部分等于上一行,后一半部分等于上一行的 0 1 反转 59 | // O(n) 60 | private fun kthGrammarReverse(N: Int, K: Int): Int { 61 | if (N == 1) return 0 62 | // K位于前一半部分 63 | if (K <= (1 shl (N - 2))) { 64 | return kthGrammarReverse(N - 1, K) 65 | } 66 | // K 位于后一半部分 67 | return kthGrammarReverse(N - 1, K - (1 shl (N - 1))) xor 1 68 | } 69 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/sort/BubbleSort.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort 2 | 3 | /** 4 | * 冒泡排序 5 | * 稳定排序 6 | * 原地排序 7 | */ 8 | class BubbleSort { 9 | companion object { 10 | @JvmStatic 11 | fun main(args: Array) { 12 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2) 13 | BubbleSort().sort(a, a.size) 14 | a.forEach { 15 | println(it) 16 | } 17 | println() 18 | val b = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2) 19 | BubbleSort().optSort(b, b.size) 20 | b.forEach { 21 | println(it) 22 | } 23 | } 24 | } 25 | 26 | /** 27 | * O(n2) 28 | */ 29 | fun sort(a: IntArray, n: Int) { 30 | var i = 0 31 | while (i < n) { 32 | var j = 0 33 | while (j < n - 1 - i) { 34 | if (a[j] > a[j + 1]) { 35 | val temp = a[j] 36 | a[j] = a[j + 1] 37 | a[j + 1] = temp 38 | } 39 | j++ 40 | } 41 | i++ 42 | } 43 | } 44 | 45 | fun optSort(a: IntArray, n: Int) { 46 | var i = 0 47 | while (i < n) { 48 | var j = 0 49 | var flag = false 50 | while (j < n - 1 - i) { 51 | if (a[j] > a[j + 1]) { 52 | val temp = a[j] 53 | a[j] = a[j + 1] 54 | a[j + 1] = temp 55 | flag = true 56 | } 57 | j++ 58 | } 59 | if (!flag) break 60 | i++ 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/sort/CountSort.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort 2 | 3 | /** 4 | * 计数排序 5 | * 稳定排序 6 | * 非原地排序 7 | */ 8 | class CountSort { 9 | companion object { 10 | @JvmStatic 11 | fun main(args: Array) { 12 | val a = intArrayOf(3, 2, 4, 3, 5, 3, 2, 1, 5, 0, 0, 4, 6) 13 | CountSort().sort(a, a.size) 14 | a.forEach { 15 | println(it) 16 | } 17 | } 18 | } 19 | 20 | /** 21 | * O(n) 22 | */ 23 | fun sort(a: IntArray, n: Int) { 24 | // 找到数据范围 25 | var max = 0 26 | a.forEach { 27 | if (it > max) max = it 28 | } 29 | 30 | // 统计每个值的个数 31 | val c = IntArray(max + 1) 32 | a.forEach { 33 | c[it]++ 34 | } 35 | 36 | // 每个值的个数求和 37 | for (i in 1 until max + 1) { 38 | c[i] = c[i] + c[i - 1] 39 | } 40 | 41 | // 排序到临时temp数组中 42 | var j = n - 1 43 | val temp = IntArray(n) 44 | while (j >= 0) { 45 | temp[c[a[j]] - 1] = a[j] 46 | c[a[j]]-- 47 | j-- 48 | } 49 | 50 | // 转移到a中 51 | temp.forEachIndexed { index, i -> 52 | a[index] = i 53 | } 54 | 55 | } 56 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/sort/HeapSort.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort 2 | 3 | /** 4 | * 堆排序 5 | * 不稳定排序(存在不相邻交换数据) 6 | * 原地排序 7 | * 8 | * 数据交换次数比快速排序多,但排序时间复杂度相对稳定。 9 | * 堆使用数组存储是间隔的,所以对于cpu缓存不友好 10 | */ 11 | class HeapSort { 12 | 13 | companion object { 14 | @JvmStatic 15 | fun main(args: Array) { 16 | // -1为占位符, 堆下标从1开始 17 | val a = intArrayOf(-1, 1, 5, 6, 2, 4, 93, 289, 534, 2, 3) 18 | HeapSort().sort(a, a.size) 19 | a.forEach { 20 | println(it) 21 | } 22 | } 23 | } 24 | 25 | 26 | /** 27 | * O(nlog n) 28 | */ 29 | fun sort(a: IntArray, n: Int) { 30 | // 建堆 31 | buildHeap(a, n) 32 | var k = n - 1 33 | 34 | // 排序 35 | while (k > 1) { 36 | swap(a, 1, k) 37 | // 堆化 38 | heapify(a, 1, --k) 39 | } 40 | 41 | } 42 | 43 | 44 | /** 45 | * O(n) 46 | */ 47 | private fun buildHeap(a: IntArray, n: Int) { 48 | var i = n / 2 49 | while (i >= 1) { 50 | heapify(a, i--, n) 51 | } 52 | } 53 | 54 | /** 55 | * O(log n) 56 | */ 57 | private fun heapify(a: IntArray, pos: Int, n: Int) { 58 | var i = pos 59 | while (true) { 60 | var j = i 61 | if (2 * i < n && a[j] < a[2 * i]) j = 2 * i 62 | if (2 * i + 1 < n && a[j] < a[2 * i + 1]) j = 2 * i + 1 63 | if (j == i) break 64 | swap(a, i, j) 65 | i = j 66 | } 67 | } 68 | 69 | private fun swap(a: IntArray, i: Int, j: Int) { 70 | val temp = a[i] 71 | a[i] = a[j] 72 | a[j] = temp 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/sort/InsertSort.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort 2 | 3 | /** 4 | * 插入排序 5 | * 原地排序 6 | * 稳定排序 7 | */ 8 | class InsertSort { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2) 14 | InsertSort().sort(a, a.size) 15 | a.forEach { 16 | println(it) 17 | } 18 | } 19 | } 20 | 21 | /** 22 | * O(n2) 23 | */ 24 | fun sort(a: IntArray, n: Int) { 25 | var i = 1 26 | while (i < n) { 27 | var j = i - 1 28 | val value = a[i] 29 | while (j >= 0) { 30 | if (value < a[j]) { 31 | a[j + 1] = a[j] 32 | } else { 33 | break 34 | } 35 | j-- 36 | } 37 | a[j + 1] = value 38 | i++ 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/sort/MergeSort.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort 2 | 3 | 4 | /** 5 | * 归并排序 6 | * 稳定排序 7 | * 不是原地排序 8 | */ 9 | class MergeSort { 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2) 14 | MergeSort().sort(a, 0, a.size - 1) 15 | a.forEach { 16 | println(it) 17 | } 18 | } 19 | } 20 | 21 | /** 22 | * 时间复杂度: O(nlog n) 23 | * 空间复杂度: O(n) 24 | */ 25 | private fun sort(a: IntArray, start: Int, end: Int) { 26 | if (start < end) { 27 | val mid = (start + end) / 2 28 | // 分治递归 29 | sort(a, start, mid) 30 | sort(a, mid + 1, end) 31 | // 合并 32 | merge(a, start, end) 33 | } 34 | } 35 | 36 | private fun merge(a: IntArray, start: Int, end: Int) { 37 | val mid = (start + end) / 2 38 | var i = start 39 | var j = mid + 1 40 | var k = 0 41 | val temp = IntArray(end - start + 1) 42 | while (i <= mid && j <= end) { 43 | if (a[i] < a[j]) { 44 | temp[k++] = a[i++] 45 | } else { 46 | temp[k++] = a[j++] 47 | } 48 | } 49 | 50 | // i有剩余 51 | while (i <= mid) { 52 | temp[k++] = a[i++] 53 | } 54 | 55 | // j有剩余 56 | while (j <= end) { 57 | temp[k++] = a[j++] 58 | } 59 | 60 | // 将temp转移到a中 61 | temp.forEachIndexed { index, item -> 62 | a[start + index] = item 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/sort/QuickSort.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort 2 | 3 | /** 4 | * 快速排序 5 | * 不稳定排序 6 | * 原地排序 7 | */ 8 | class QuickSort { 9 | companion object { 10 | @JvmStatic 11 | fun main(args: Array) { 12 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2) 13 | QuickSort().quick(a, 0, a.size - 1) 14 | a.forEach { 15 | println(it) 16 | } 17 | } 18 | } 19 | 20 | /** 21 | * 时间复制度O(nlog n); 最好时间复杂度O(nlog n); 最坏时间复杂度O(n2) 22 | * 空间复杂度O(1) 23 | */ 24 | private fun quick(a: IntArray, start: Int, end: Int) { 25 | if (start < end) { 26 | // 找到分区位置 27 | val mid = sort(a, start, end) 28 | // 分区 29 | quick(a, start, mid - 1) 30 | quick(a, mid + 1, end) 31 | } 32 | } 33 | 34 | private fun sort(a: IntArray, start: Int, end: Int): Int { 35 | val pivot = a[end] 36 | var i = start 37 | var j = start 38 | 39 | while (j < end) { 40 | if (a[j] < pivot) { 41 | val temp = a[i] 42 | a[i] = a[j] 43 | a[j] = temp 44 | i++ 45 | } 46 | j++ 47 | } 48 | 49 | val temp = a[i] 50 | a[i] = pivot 51 | a[end] = temp 52 | 53 | return i 54 | } 55 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/sort/SelectSort.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sort 2 | 3 | /** 4 | * 选择排序 5 | * 不稳定排序 6 | * 原地排序 7 | */ 8 | class SelectSort { 9 | 10 | companion object { 11 | @JvmStatic 12 | fun main(args: Array) { 13 | val a = intArrayOf(10, 1, 4, 2, 5, 643, 654, 234, 2) 14 | SelectSort().sort(a, a.size) 15 | a.forEach { 16 | println(it) 17 | } 18 | } 19 | } 20 | 21 | /** 22 | * O(n2) 23 | */ 24 | fun sort(a: IntArray, n: Int) { 25 | var i = 0 26 | while (i < n) { 27 | var j = i + 1 28 | var k = i 29 | var min = a[i] 30 | while (j < n) { 31 | if (a[j] < min) { 32 | min = a[j] 33 | k = j 34 | } 35 | j++ 36 | } 37 | a[k] = a[i] 38 | a[i] = min 39 | i++ 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/stack/MinStack.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.stack 2 | 3 | import java.util.* 4 | 5 | 6 | /** 7 | * 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。(LeetCode 155) 8 | * push(x) —— 将元素 x 推入栈中。 9 | * pop()—— 删除栈顶的元素。 10 | * top()—— 获取栈顶元素。 11 | * getMin() —— 检索栈中的最小元素。 12 | * 13 | * 使用辅助栈,每次操作都与实际栈一一对应,只不过每次push的都是实际值与辅助栈顶值中的最小值 14 | * */ 15 | class MinStack { 16 | companion object { 17 | @JvmStatic 18 | fun main(args: Array) { 19 | val minStack = MinStack() 20 | minStack.push(-2) 21 | minStack.push(0) 22 | minStack.push(-3) 23 | println(minStack.getMin()) 24 | minStack.pop() 25 | println(minStack.top()) 26 | println(minStack.getMin()) 27 | } 28 | } 29 | 30 | private val mStack = Stack() 31 | private val mMinStack = Stack() 32 | 33 | fun push(item: Int) { 34 | mStack.push(item) 35 | if (mMinStack.isEmpty() || item < mMinStack.peek()) { 36 | mMinStack.push(item) 37 | } else { 38 | mMinStack.push(mMinStack.peek()) 39 | } 40 | } 41 | 42 | fun pop() { 43 | mMinStack.pop() 44 | mStack.pop() 45 | } 46 | 47 | fun top(): Int { 48 | return mStack.peek() 49 | } 50 | 51 | fun getMin(): Int { 52 | return mMinStack.peek() 53 | } 54 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/stack/ValidParenthesis.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.stack 2 | 3 | import java.util.* 4 | 5 | /** 6 | * 有效的括号(LeetCode 20) 7 | * 给定一个只包括 '(',')','{','}','[',']'的字符串,判断字符串是否有效。 8 | * 有效字符串需满足: 9 | * 10 | * 左括号必须用相同类型的右括号闭合。 11 | * 左括号必须以正确的顺序闭合。 12 | * 注意空字符串可被认为是有效字符串。 13 | * 14 | * 使用栈实现,遍历字符串,遇到左括号统统入栈,遇到有括号 15 | * 1. 判断栈是否为空,为空则无效 16 | * 2. 从栈中取出一个元素,与当前右括号做匹配,不符合则无效,符合则继续向下操作 17 | * 3. 字符串遍历结束之后,判断栈是否为空,不为空则无效。 18 | */ 19 | class ValidParenthesis { 20 | 21 | companion object { 22 | @JvmStatic 23 | fun main(args: Array) { 24 | println(ValidParenthesis().isValid("({[[{(([]))}]]})")) 25 | } 26 | } 27 | 28 | /** 29 | * O(n) 30 | */ 31 | private fun isValid(s: String): Boolean { 32 | val stack = Stack() 33 | s.forEach { 34 | if (it == '(' || it == '{' || it == '[') { 35 | stack.push(it) 36 | } else { 37 | if (stack.isEmpty()) return false 38 | val popItem = stack.pop() 39 | if ((popItem == '(' && it != ')') 40 | || (popItem == '{' && it != '}') 41 | || (popItem == '[' && it != ']')) return false 42 | } 43 | } 44 | 45 | if (stack.isNotEmpty()) return false 46 | 47 | return true 48 | } 49 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/sword/Permutation.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.sword 2 | 3 | /** 4 | * 剑指 Offer 38. 字符串的排列 5 | * 6 | * 输入一个字符串,打印出该字符串中字符的所有排列。 7 | * 8 | * 你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。 9 | */ 10 | class Permutation { 11 | 12 | companion object { 13 | @JvmStatic 14 | fun main(args: Array) { 15 | val result = Permutation().permutation("abc") 16 | result.forEach { 17 | println(it) 18 | } 19 | } 20 | } 21 | 22 | fun permutation(s: String): Array { 23 | val result = arrayListOf() 24 | val c = s.toCharArray() 25 | dfs(0, c, result) 26 | return result.toArray(arrayOf()) 27 | } 28 | 29 | private fun dfs(x: Int, c: CharArray, res: MutableList) { 30 | if (x == c.size - 1) { 31 | res.add(c.contentToString()) 32 | return 33 | } 34 | val set = hashSetOf() 35 | for (i in x until c.size) { 36 | if (set.contains(c[i])) continue 37 | set.add(c[i]) 38 | swap(x, i, c) 39 | dfs(x + 1, c, res) 40 | swap(i, x, c) 41 | } 42 | } 43 | 44 | private fun swap(x: Int, i: Int, c: CharArray) { 45 | val temp = c[x] 46 | c[x] = c[i] 47 | c[i] = temp 48 | } 49 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/tree/MaxDepth.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.tree 2 | 3 | import kotlin.math.max 4 | 5 | /** 6 | * 二叉树的最大深度(leetcode 104) 7 | * 8 | * 给定一个二叉树,找出其最大深度。 9 | * 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 10 | * 说明:叶子节点是指没有子节点的节点。 11 | * 12 | * 示例: 13 | * 给定二叉树 [3,9,20,null,null,15,7], 14 | * 3 15 | * / \ 16 | * 9 20 17 | * / \ 18 | * 15 7 19 | * 返回它的最大深度3 。 20 | */ 21 | class MaxDepth { 22 | 23 | companion object { 24 | @JvmStatic 25 | fun main(args: Array) { 26 | println(MaxDepth().solution(TreeNode(3, TreeNode(9), TreeNode(20, TreeNode(15), TreeNode(7))))) 27 | } 28 | } 29 | 30 | /** 31 | * 时间:O(n) n => 节点数 32 | * 空间:O(height) height => 高度 33 | */ 34 | fun solution(root: TreeNode?): Int { 35 | if (root != null) { 36 | return max(solution(root.left), solution(root.right)) + 1 37 | } 38 | return 0 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/tree/TreeNode.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.tree 2 | 3 | data class TreeNode(var data: T, var left: TreeNode? = null, var right: TreeNode? = null) { 4 | fun printMid(node: TreeNode) { 5 | node.left?.let { printMid(it) } 6 | println(node.data) 7 | node.right?.let { printMid(it) } 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /kotlin/src/com/daily/algothrim/trie/Trie.kt: -------------------------------------------------------------------------------- 1 | package com.daily.algothrim.trie 2 | 3 | /** 4 | * Trie树,解决字符串查询 5 | */ 6 | class Trie { 7 | 8 | companion object { 9 | @JvmStatic 10 | fun main(args: Array) { 11 | Trie().apply { 12 | insert("hello".toCharArray()) 13 | insert("her".toCharArray()) 14 | insert("hi".toCharArray()) 15 | insert("how".toCharArray()) 16 | insert("so".toCharArray()) 17 | insert("see".toCharArray()) 18 | println(find("see".toCharArray())) 19 | } 20 | } 21 | } 22 | 23 | private val root = TrieNode('/') 24 | 25 | class TrieNode(val data: Char) { 26 | val children = Array(26) { null } 27 | var isEndingChar = false 28 | } 29 | 30 | /** 31 | * O(n)所有字符串的长度之和 32 | */ 33 | fun insert(text: CharArray) { 34 | var p = root 35 | text.forEach { 36 | val index = it - 'a' 37 | if (p.children[index] == null) { 38 | p.children[index] = TrieNode(it) 39 | } 40 | p = p.children[index]!! 41 | } 42 | p.isEndingChar = true 43 | } 44 | 45 | /** 46 | * O(k)查询的字符串长度 47 | */ 48 | fun find(text: CharArray): Boolean { 49 | var p = root 50 | text.forEach { 51 | val index = it - 'a' 52 | if (p.children[index] == null) return false 53 | p = p.children[index]!! 54 | } 55 | return p.isEndingChar 56 | } 57 | 58 | } --------------------------------------------------------------------------------