LeetCode算法-二分查找-简单

35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:

输入: [1,3,5,6], 5

输出: 2

示例 2:

输入: [1,3,5,6], 2

输出: 1

示例 3:

输入: [1,3,5,6], 7

输出: 4

        n = len(nums)
        if n == 0:
            return 0
        if target < nums[0]:
            return 0
        if target > nums[n-1]:
            return n
        l = 0
        r = n-1
        while l <= r:
            mid = (l+r)//2
            if nums[mid] == target:
                return mid
            elif nums[mid] > target:
                r = mid - 1
            else:
                l = mid + 1
        return l

69. x 的平方根

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:

输入: 4

输出: 2

示例 2:

输入: 8

输出: 2

说明: 8 的平方根是 2.82842...,

 由于返回类型是整数,小数部分将被舍去。
class Solution(object):
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        l = 0
        r = x
        while l<=r:
            m = (l+r)//2
            if m*m == x:
                return m
            elif m*m > x:
                r = m - 1
            else:
                l = m + 1
        return r

167. 两数之和 II - 输入有序数组

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:

返回的下标值(index1 和 index2)不是从零开始的。

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

示例:

输入: numbers = [2, 7, 11, 15], target = 9

输出: [1,2]

解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

class Solution(object):
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        l = 0
        r = len(numbers) - 1
        while l<r:
            if numbers[l] + numbers[r] == target:
                return [l+1,r+1]
            elif numbers[l] + numbers[r] > target:
                r -= 1
            else:
                l += 1

278. 第一个错误的版本

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

示例:

给定 n = 5,并且 version = 4 是第一个错误的版本。

调用 isBadVersion(3) -> false

调用 isBadVersion(5) -> true

调用 isBadVersion(4) -> true

所以,4 是第一个错误的版本。

class Solution(object):
    def firstBadVersion(self, n):
        """
        :type n: int
        :rtype: int
        """
        l = 1
        r = n
        while l<r:
            m = (l+r)//2
            if isBadVersion(m):
                r = m
            else:
                l = m + 1
        return l

349. 两个数组的交集

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]

输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]

输出:[9,4]

说明:

输出结果中的每个元素一定是唯一的。

我们可以不考虑输出结果的顺序。

class Solution(object):
    def intersection(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        res = set(nums1) & set(nums2)
        return list(res)

350. 两个数组的交集 II

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]

输出: [2,2]

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]

输出: [4,9]

说明:

输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。

我们可以不考虑输出结果的顺序。

class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        '''
        res = []
        for num in nums1:
            if num in nums2:
                nums2.remove(num)
                res.append(num)
        retun res
        '''
        nums1.sort()
        nums2.sort()
        res = []
        left, right = 0, 0
        while left < len(nums1) and right < len(nums2):
            if nums1[left] < nums2[right]:
                left += 1
            elif nums1[left] > nums2[right]:
                right += 1    
            else:
                res.append(nums1[left])
                left += 1
                right += 1
        return res

367. 有效的完全平方数

给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False。

说明:不要使用任何内置的库函数,如  sqrt。

示例 1:

输入:16

输出:True

示例 2:

输入:14

输出:False

class Solution(object):
    def isPerfectSquare(self, num):
        """
        :type num: int
        :rtype: bool
        """
        l = 0
        r = num // 2 + 1
        while l<=r:
            m = (l+r)//2
            if m * m == num:
                return True
            elif m * m > num:
                r = m - 1
            else:
                l = m + 1
        else:
            return False

374. 猜数字大小

我们正在玩一个猜数字游戏。 游戏规则如下:

我从 1 到 n 选择一个数字。 你需要猜我选择了哪个数字。

每次你猜错了,我会告诉你这个数字是大了还是小了。

你调用一个预先定义好的接口 guess(int num),它会返回 3 个可能的结果(-1,1 或 0):

-1 : 我的数字比较小

1 : 我的数字比较大

0 : 恭喜!你猜对了!
 
示例 :

输入: n = 10, pick = 6

输出: 6

class Solution(object):
    def guessNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        l = 1
        r = n
        while True:
            m = (l+r) // 2
            if guess(m) == 0:
                return m
            elif guess(m) == 1:
                l = m + 1
            else:
                r = m - 1

392. 判断子序列

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

示例 1:

s = "abc", t = "ahbgdc"

返回 true.

示例 2:

s = "axc", t = "ahbgdc"

返回 false.

后续挑战 :

如果有大量输入的 S,称作S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

class Solution(object):
    def isSubsequence(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if not s:
            return True
        p = q = 0
        while p < len(s) and q < len(t):
            if s[p] == t[q]:
                p += 1
                q += 1
                continue
            else:
                q += 1
        return p == len(s)

441. 排列硬币

你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。

给定一个数字 n,找出可形成完整阶梯行的总行数。

n 是一个非负整数,并且在32位有符号整型的范围内。

示例 1:

n = 5

硬币可排列成以下几行:

¤

¤ ¤

¤ ¤

因为第三行不完整,所以返回2.

示例 2:

n = 8

硬币可排列成以下几行:

¤

¤ ¤

¤ ¤ ¤

¤ ¤

因为第四行不完整,所以返回3.

class Solution(object):
    def arrangeCoins(self, n):
        """
        :type n: int
        :rtype: int
        """
        res = ((1+8*n)**0.5-1)/2
        return int(res)

475. 供暖器

冬季已经来临。 你的任务是设计一个有固定加热半径的供暖器向所有房屋供暖。

现在,给出位于一条水平线上的房屋和供暖器的位置,找到可以覆盖所有房屋的最小加热半径。

所以,你的输入将会是房屋和供暖器的位置。你将输出供暖器的最小加热半径。

说明:

给出的房屋和供暖器的数目是非负数且不会超过 25000。

给出的房屋和供暖器的位置均是非负数且不会超过10^9。

只要房屋位于供暖器的半径内(包括在边缘上),它就可以得到供暖。

所有供暖器都遵循你的半径标准,加热的半径也一样。

示例 1:

输入: [1,2,3],[2]

输出: 1

解释: 仅在位置2上有一个供暖器。如果我们将加热半径设为1,那么所有房屋就都能得到供暖。

示例 2:

输入: [1,2,3,4],[1,4]

输出: 1

解释: 在位置1, 4上有两个供暖器。我们需要将加热半径设为1,这样所有房屋就都能得到供暖。

res = []
        heaters.sort()
        for c in houses:
            """二分查找"""
            left = 0
            right = len(heaters) - 1
            while left < right:
                mid = (left + right) // 2
                if heaters[mid] < c:
                    left = mid + 1
                else:
                    right = mid
            """得出的 left 所指的加热器并不一定是离房屋 c 最近的一个,需要判断以下情况"""
            if heaters[left] == c:
                """若找到的值等于 c ,则说明 c 房屋处放有一个加热器,c 房屋到加热器的最短距离为 0"""
                res.append(0)

            elif heaters[left] < c:
                """若该加热器的坐标值小于 c ,说明该加热器的坐标与 c 之间没有别的加热器"""
                res.append(c - heaters[left])

            elif left == 0:
                """
                若left == 0 即二分查找的结果指向第一个加热器的坐标,说明 heaters[left] 坐标的房屋之前的位置
                未放置加热器,直接相减就是到房屋 c 最近加热器的距离
                """
                res.append(heaters[left] - c)
                
            else:
                """
                若left不等于 0 ,说明 c 介于left和left-1之间,房屋到加热器的最短距离就是left和left - 1处
                加热器与 c 差值的最小值.
                """
                res.append(min(heaters[left] - c, c - heaters[left - 1]))
                
        return max(res)

704. 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9

输出: 4

解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2

输出: -1

解释: 2 不存在 nums 中因此返回 -1

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        l = 0
        r = len(nums) - 1
        while l<=r:
            m = (l+r)//2
            if nums[m] == target:
                return m
            elif nums[m] > target:
                r = m - 1
            else:
                l = m + 1
        else:
            return -1

744. 寻找比目标字母大的最小字母

给你一个排序后的字符列表 letters ,列表中只包含小写英文字母。另给出一个目标字母 target,请你寻找在这一有序列表里比目标字母大的最小字母。

在比较时,字母是依序循环出现的。举个例子:

如果目标字母 target = 'z' 并且字符列表为 letters = ['a', 'b'],则答案返回 'a'

示例:

输入:

letters = ["c", "f", "j"]

target = "a"

输出: "c"

输入:

letters = ["c", "f", "j"]

target = "c"

输出: "f"

输入:

letters = ["c", "f", "j"]

target = "d"

输出: "f"

输入:

letters = ["c", "f", "j"]

target = "g"

输出: "j"

输入:

letters = ["c", "f", "j"]

target = "j"

输出: "c"

输入:

letters = ["c", "f", "j"]

target = "k"

输出: "c"

class Solution(object):
    def nextGreatestLetter(self, letters, target):
        """
        :type letters: List[str]
        :type target: str
        :rtype: str
        """
        
        left,right=0,len(letters)-1
        while left<=right:
            mid = (left + right)//2
            if letters[mid]<=target:
                left=mid+1
            else:
                right=mid-1
        
        return letters[left] if left<len(letters) else letters[0]

852. 山脉数组的峰顶索引

我们把符合下列属性的数组 A 称作山脉:

A.length >= 3

存在 0 < i < A.length - 1 使得A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]

给定一个确定为山脉的数组,返回任何满足 A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] 的 i 的值。

示例 1:

输入:[0,1,0]

输出:1

示例 2:

输入:[0,2,1,0]

输出:1

class Solution(object):
    def peakIndexInMountainArray(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        n = max(A)
        return A.index(n)
        '''
        low=0
        high=len(A)-1
        while low<high:
            mid=(low+high)//2
            if A[mid]>A[mid-1] and A[mid]>A[mid+1]:
                return mid
            elif A[mid]>A[mid-1]:
                low=mid+1
            else:
                high=mid
        '''

1237. 找出给定方程的正整数解

给出一个函数  f(x, y) 和一个目标结果 z,请你计算方程 f(x,y) == z 所有可能的正整数 数对 x 和 y。

给定函数是严格单调的,也就是说:

f(x, y) < f(x + 1, y)

f(x, y) < f(x, y + 1)

函数接口定义如下:

interface CustomFunction {

public:

// Returns positive integer f(x, y) for any given positive integer x and y.

int f(int x, int y);

};

如果你想自定义测试,你可以输入整数 function_id 和一个目标结果 z 作为输入,其中 function_id 表示一个隐藏函数列表中的一个函数编号,题目只会告诉你列表中的 2 个函数。

你可以将满足条件的 结果数对 按任意顺序返回。

示例 1:

输入:function_id = 1, z = 5

输出:[[1,4],[2,3],[3,2],[4,1]]

解释:function_id = 1 表示 f(x, y) = x + y

示例 2:

输入:function_id = 2, z = 5

输出:[[1,5],[5,1]]

解释:function_id = 2 表示 f(x, y) = x * y

"""
   This is the custom function interface.
   You should not implement it, or speculate about its implementation
   class CustomFunction:
       # Returns f(x, y) for any given positive integers x and y.
       # Note that f(x, y) is increasing with respect to both x and y.
       # i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1)
       def f(self, x, y):
"""

class Solution(object):
    def findSolution(self, customfunction, z):
        """
        :type num: int
        :type z: int
        :rtype: List[List[int]]
        """
        output = []
        a = 1
        b = 1000
        while a <= 1000 and b >= 1:
            if customfunction.f(a, b) < z:
                a += 1
            elif customfunction.f(a, b) > z:
                b -= 1
            else:
                output.append([a, b])
                a += 1
                b -= 1
        return output

1337. 方阵中战斗力最弱的 K 行

给你一个大小为 m * n 的方阵 mat,方阵由若干军人和平民组成,分别用 1 和 0 表示。

请你返回方阵中战斗力最弱的 k 行的索引,按从最弱到最强排序。

如果第 i 行的军人数量少于第 j 行,或者两行军人数量相同但 i 小于 j,那么我们认为第 i 行的战斗力比第 j 行弱。

军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。

示例 1:

输入:mat =

[[1,1,0,0,0],

[1,1,1,1,0],

[1,0,0,0,0],

[1,1,0,0,0],

[1,1,1,1,1]],

k = 3

输出:[2,0,3]

解释:

每行中的军人数目:

行 0 -> 2

行 1 -> 4

行 2 -> 1

行 3 -> 2

行 4 -> 5

从最弱到最强对这些行排序后得到 [2,0,3,1,4]

class Solution(object):
    def kWeakestRows(self, mat, k):
        """
        :type mat: List[List[int]]
        :type k: int
        :rtype: List[int]
        """
        counts = [l.count(1) for l in mat]
        res = []
        for i in range(k):
            m = min(counts)
            ind = counts.index(m)
            res.append(ind)
            counts[ind] = 10
        return res

1351. 统计有序矩阵中的负数

给你一个 m * n 的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。

请你统计并返回 grid 中 负数 的数目。

示例 1:

输入:grid = [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]

输出:8

解释:矩阵中共有 8 个负数。

示例 2:

输入:grid = [[3,2],[1,0]]

输出:0

示例 3:

输入:grid = [[1,-1],[-1,-1]]

输出:3

示例 4:

输入:grid = [[-1]]

输出:1

class Solution(object):
    def countNegatives(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        count = 0
        for arr in grid:
            arr.append(0)
            arr.sort()
            count += arr.index(0)
        return count

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-insert-position
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

posted @ 2020-07-24 01:05  MrDoghead  阅读(331)  评论(0编辑  收藏  举报