704. Binary Search
二分法在有序数组中查找元素。原题
1 | Input: nums = [-1,0,3,5,9,12], target = 9 |
1 | def binary_search(nums, target): |
方法二:使用标准库。
1 | def search(self, nums, target): |
35. Search Insert Position
给定一个target,插入到一个有序数组中,假定数组中无重复元素。原题
1 | Input: [1,3,5,6], 5 |
1 | def binary_insert(nums, target): |
方法二:使用标准库。
1 | def searchInsert(self, nums, target): |
153. Find Minimum in Rotated Sorted Array
通过一个排序数组旋转后的结果,找出最小元素。原题
1 | Input: [3,4,5,1,2] |
思路:通过二分法不断缩小范围,由于mid是整除,最后l==mid,并且nums[mid] > nums[r]的。
1 | def findMin(self, nums: List[int]) -> int: |
34. Find First and Last Position of Element in Sorted Array
有序数组中查找数组,返回数字的索引范围。原题
1 | Input: nums = [5,7,7,8,8,10], target = 8 |
1 | def searchRange(self, nums, target): |
278. First Bad Version
找出提交版本中的bad version。原题
1 | Given n = 5, and version = 4 is the first bad version. |
1 | def firstBadVersion(self, n): |
374. Guess Number Higher or Lower
猜数游戏1~n,每猜一次会告诉你答案是更小还是更大。原题
1 | def guess(num): |
1 | def guessNumber(self, n): |
方法二:使用标准库。此答案受stefan大神启发。核心思想为将guess返回的结果转为一个数组,然后使用二分法查找。
1 | def guessNumber(self, n): |
解析:以n=10, pick=6为例。实际上C class相当于:
1 | ary = map(lambda x: -guess(x), range(1, n+1)) |
而索引又是从1开始,所以这里在前面添加了一个None,实际上将题转为了查找ary
的0
,问题便迎刃而解。值得注意的是,如果使用了map,会导致空间,时间复杂度增加,而使用class的方法,并没有求出整个的list
,所以效率更高。
744. Find Smallest Letter Greater Than Target
找出比目标大的最小字母,没有的返回首字母。原题
1 | Input: |
方法一:二分法实现。
1 | def nextGreatestLetter(self, letters: 'List[str]', target: 'str') -> 'str': |
1 | def nextGreatestLetter(self, letters: 'List[str]', target: 'str') -> 'str': |
852. Peak Index in a Mountain Array
找到数组中的峰值。假设峰值一定存在。原题
1 | Input: [0,2,1,0] |
方法一:Linear Scan. Time: O(N)
1 | def peakIndexInMountainArray(self, A: 'List[int]') -> 'int': |
方法二:one-line.
1 | def peakIndexInMountainArray(self, A: 'List[int]') -> 'int': |
1 | def peakIndexInMountainArray(self, A: 'List[int]') -> 'int': |
1 | def peakIndexInMountainArray(self, A: 'List[int]') -> 'int': |
1014. Capacity To Ship Packages Within D Days
n天内轮船运送的最小容量。原题
1 | Input: weights = [1,2,3,4,5,6,7,8,9,10], D = 5 |
贴一下竞赛时AC的丑陋写法。
1 | def shipWithinDays(self, weights: List[int], D: int) -> int: |
优化。遇见一个诡异的现象,同样的代码用python比python3快了60ms,和3MB的内存。这解法也没涉及两者的区别。
1 | def shipWithinDays(self, weights: List[int], D: int) -> int: |
875. Koko Eating Bananas
这道题思路和1014一样。不同的是,如果当前堆的香蕉小于吃的速度,那么也不能吃下一堆。原题
1 | Input: piles = [3,6,7,11], H = 8 |
方法一:写习惯了Python3,老是想写//
,注意是p/mid
。
1 | def minEatingSpeed(self, piles: List[int], H: int) -> int: |
1145. Binary Tree Coloring Game
二叉树染色游戏。两个人轮流给二叉树染色,每次只能染相邻位的节点,给定第一个人染色的位置,问第二个人是否能够必胜。原题
方法一:关键的一点需要想明白,从第一个人染色的地方,有三个分支,如果有一个分支可以大于整个节点的一半,那么第二个人选择这个分支,就能赢得比赛
1 | def btreeGameWinningMove(self, root: TreeNode, n: int, x: int) -> bool: |
33. Search in Rotated Sorted Array
在有序数组旋转后查找目标索引。原题
1 | Input: nums = [4,5,6,7,0,1,2], target = 0 |
方法一:这个题开始的时候结合两个题,一个是旋转数组中的最小值,然后重组成一个原数组,最后在二分搜索加上原来偏移的索引值。但是这样使用了两次二分法,所以效率不高。看了stefan的答案后明白了,需要找到另一个比较的值就是nums[0]
。这里分了两种情况,一种是当nums[0]<=nums[mid]
,这种情况说明了nums[:mid]
是有序的;另一种是nums[mid]<nums[0]
,说明nums[:mid]
中存在一个下落点,然后又根据target在下落点的左右分为两种情况。记住条件中target始终有=
。其实有一个等号可以去掉,但是为了方便好记。
1 | def search(self, nums: List[int], target: int) -> int: |
81. Search in Rotated Sorted Array II
同33题,区别在于数组中可能有重复的数字,返回是否存在即可。
1 | Input: nums = [2,5,6,0,0,1,2], target = 0 |
方法一:核心代码在于七八行,当左边界和中间相等时,左边界递增。
1 | def search(self, nums: List[int], target: int) -> bool: |
1283. Find the Smallest Divisor Given a Threshold
找到一个除数,用数组所有元素除它得到的天花板数和刚好小于等于阈值。求这个数最小是多少。原题
1 | Input: nums = [1,2,5,9], threshold = 6 |
方法一:这道题和大佬的解法差不多。区别在于我用了math的库,而他用了一个式子来求的天花板数。知识点(a + b - 1) // b == math.ceil(a/b)
1 | def smallestDivisor(self, nums: List[int], threshold: int) -> int: |
1268. Search Suggestions System
单词推荐系统。原题
1 | Input: products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse" |
方法一:二分法。此题暴力法求解也能过。更好的方法还是二分或者Trie,但是Trie的方式实现过于复杂。
1 | def suggestedProducts(self, p: List[str], w: str) -> List[List[str]]: |
392. Is Subsequence
判断一个字符串是否是另一个的子序列。原题
1 | Input: s = "abc", t = "ahbgdc" |
方法一:生成器。
1 | def isSubsequence(self, s: str, t: str) -> bool: |
方法二:二分法。将每个字符的索引用列表记录下来,每次用二分法找后序出现的匹配的字符。
1 | def isSubsequence(self, s: str, t: str) -> bool: |
1482. Minimum Number of Days to Make m Bouquets
花圃里有若干的花束记录了第几天会开花。最小的天数,可以做出m束花,必须使用连续的花才能做成一朵花束。需要k束花。原题
1 | Input: bloomDay = [1,10,3,10,2], m = 3, k = 1 |
方法一:比赛的时候真是一点都没往二分法想、这个是Lee的答案。
1 | def minDays(self, A: List[int], m: int, k: int) -> int: |
1201. Ugly Number III
找到第n个能被a或b或c整除的数。原题
1 | Input: n = 3, a = 2, b = 3, c = 5 |
方法一:这题和 丑数2的题不一样,那道题是只能被2,3,5整除的数。这题一开始也是没想到用二分法。
1 | def nthUglyNumber(self, n: int, a: int, b: int, c: int) -> int: |
287. Find the Duplicate Number
找到重复的数字,在1~n中有一个数至少重复了一次,但是其它数可能没有,找到这个重复的数字。原题
方法一:用过这个方法,但是没想到能用在这道题上,方法是解环形链表中入口节点的那道题。因为数组中存在重复的数字,所以这样延伸下去一定是有环。1 | def findDuplicate(self, nums: List[int]) -> int: |
方法二:二分法。比较的是数字的多少。
1 | def findDuplicate(self, nums: List[int]) -> int: |
154. Find Minimum in Rotated Sorted Array II
旋转数组找到最小值,与1不同的是,这里有重复的值。原题
方法一:由于重复值的原因,[10, 1, 10, 10, 10]
,[10, 10, 10, 1, 10]
1 | def findMin(self, nums: List[int]) -> int: |
1539. Kth Missing Positive Number
找到第k个缺失的正数,数组可能会被耗尽。原题
1 | Input: arr = [2,3,4,7,11], k = 5 |
方法一:用了集合。
1 | def findKthPositive(self, arr: List[int], k: int) -> int: |
[2,3,4,7,11]
A[m]-1-m表示缺失了几个数。
1 | def findKthPositive(self, A: List[int], k: int) -> int: |
1552. Magnetic Force Between Two Balls
在若干的指定的位置可以放置球,问如何使球之间最小的距离最大化。原题
1 | Input: position = [1,2,3,4,7], m = 3 |
方法一:比赛的时候想了一下二分法,但是没多想。这里只要想明白这个辅助方法就能实现了。count方法表示距离为d时最多可以放几个球。
1 | def maxDistance(self, position: List[int], m: int) -> int: |
162. Find Peak Element
找到数组中的峰值,数组中元素两个挨着的元素不重复。可能存在多个值,返回任意一个即可。原题
1 | Input: nums = [1,2,1,3,5,6,4] |
方法一:因为挨着的元素不重复,所以可以用二分法。比较两个相邻的元素,如果做左小于右说明峰值在右侧。
1 | def findPeakElement(self, nums: List[int]) -> int: |
1095. Find in Mountain Array
查找山峰数组中的元素,优先返回左侧的索引,如果都没有返回-1。原题
1 | Input: array = [1,2,3,4,5,3,1], target = 3 |
方法一:三次二分法,想到了这个方式,犹豫了一下,因为觉得这种方式在最坏的情况下取值会超过100次。
第一次找到峰值,和162一样。
1 | def findInMountainArray(self, target: int, A: 'MountainArray') -> int: |
74. Search a 2D Matrix
在2d数组中搜索目标,把数组抻成一维的也是有序数组。原题
1 | Input: |
方法一:一开始没想到这个方法,而是先bisect_right找行,然后再在行里二分。
1 | def searchMatrix(self, matrix: List[List[int]], target: int) -> bool: |
436. Find Right Interval
找到每个段的右侧的段的索引,右侧的段意味着起始点大于等于该段结尾点的并且最近的段。原题
1 | Input: [ [3,4], [2,3], [1,2] ] |
方法一:二分法。理清题意后挺简单的。
1 | def findRightInterval(self, intervals: 'List[Interval]') -> List[int]: |
方法二:压缩一下。
1 | def findRightInterval(self, intervals: 'List[Interval]') -> List[int]: |
911. Online Election
找到某一时间的选举票最多的人。
1 | Input: ["TopVotedCandidate","q","q","q","q","q","q"], [[[0,1,1,0,0,1,0],[0,5,10,15,20,25,30]],[3],[12],[25],[15],[24],[8]] |
方法一:二分法,挺简单的。
1 | class TopVotedCandidate: |
1 | class TopVotedCandidate: |
378. Kth Smallest Element in a Sorted Matrix
有个二维矩阵行列都是有序的,找到第K个最小的元素。
1 | matrix = [ |
方法一:可以用堆,暴力地解决,效率也很高。不过这样的话,有序的条件相当于没有用上。
1 | def kthSmallest(self, matrix: List[List[int]], k: int) -> int: |
1 | def kthSmallest(self, matrix: List[List[int]], k: int) -> int: |
1 | def kthSmallest(self, matrix: List[List[int]], k: int) -> int: |
1157. Online Majority Element In Subarray
实时的最多元素查询。原题
1 | MajorityChecker majorityChecker = new MajorityChecker([1,1,2,2,1,1]); |
方法一:竞赛时,用了个dict
嵌套,内存溢出了。此题的解法是存索引,然后二分。
1 | class MajorityChecker: |
1146. Snapshot Array
数组的快照。原题
1 | Input: ["SnapshotArray","set","snap","set","get"] |
方法一:此题暴力法时,空间复杂度会过高。采用针对每个元素,变化时,记录该变化的历史。再用二分法查找。
注意查找时,是通过数组查找而不是数字,查找比其大的再-1。
1 | class SnapshotArray: |
1847. Closest Room
找到满足size的最近id的房间。
1 | Input: rooms = [[2,2],[1,2],[3,2]], queries = [[3,1],[3,3],[5,2]] |
方法一:看数据量很容易能够想到是二分法,但是还需要想到离线算法,这个题要将query顺序打乱。这里是官方的解法。
1 | import sortedcontainers |
2040. Kth Smallest Product of Two Sorted Arrays
两个有序数组的第k小的乘积。
1 | Input: nums1 = [2,5], nums2 = [3,4], k = 2 |
方法一:这题需要转换一下思路来二分,以乘积来二分,如果小于等于x的刚好有k个,那么乘积就是x。
1 | def kthSmallestProduct(self, nums1: List[int], nums2: List[int], k: int) -> int: |
792. Number of Matching Subsequences
求words里是s子序列的个数。
1 | Input: s = "abcde", words = ["a","bb","acd","ace"] |
方法一:二分法。如果暴力求子序列会超时,这里使用二分法判断是否是子序列
1 | def numMatchingSubseq(self, s: str, words: List[str]) -> int: |
方法二:这个方法很新颖,分桶
1 | def numMatchingSubseq(self, s: str, words: List[str]) -> int: |