美文网首页
LeetCode #35 #34 #69 #74 #240 20

LeetCode #35 #34 #69 #74 #240 20

作者: 40巨盗 | 来源:发表于2018-08-14 23:15 被阅读0次

35. Search Insert Position

https://leetcode.com/problems/search-insert-position/description/

left <= right, 以上实现方式有一个好处,就是当循环结束时,如果没有找到目标元素,那么left一定停在恰好比目标大的index上,right一定停在恰好比目标小的index上,所以个人比较推荐这种实现方式。所以直接返回left即可。
代码如下:

class Solution:
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        left = 0
        right = len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] == target:
                return mid
            if nums[mid] > target:
                right = mid - 1
            else:
                left = mid + 1
        return left

34. Find First and Last Position of Element in Sorted Array

https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/description/

如果直接相等的时候也向一个方向继续夹逼,如果向右夹逼,最后就会停在右边界,而向左夹逼则会停在左边界,如此用停下来的两个边界就可以知道结果了,只需要两次二分查找。实现中用到了在Search Insert Position中提到的方法,可以保证当搜索结束时,l和r所停的位置正好是目标数的后面和前面
代码如下:

class Solution:
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        result = []
        left = 0
        right = len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] < target:
                left = mid + 1
            else:
                right = mid - 1
        result.append(left)
        left = 0
        right = len(nums) - 1
        while left <= right:
            mid = (left + right) // 2
            if nums[mid] <= target:
                left = mid + 1
            else:
                right = mid - 1
        result.append(right)
        if result[0] > result[1]:
            return [-1, -1]
        return result

69. Sqrt(x)

https://leetcode.com/problems/sqrtx/description/

这道题一般采用数值中经常用的另一种方法:二分法。基本思路是跟二分查找类似,要求是知道结果的范围,取定左界和右界,然后每次砍掉不满足条件的一半,直到左界和右界相遇。算法的时间复杂度是O(logx),空间复杂度是O(1)
代码如下:

class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        if x < 0:
            return -1
        if x == 0 or x == 1:
            return x
        left = 1
        right = x // 2 + 1
        while left <= right:
            mid = (left + right) // 2
            if mid * mid <= x < (mid + 1) * (mid + 1):
                return mid
            if mid * mid > x:
                right = mid - 1
            else:
                left = mid + 1
        return -1

二分法在数值计算中非常常见,还是得熟练掌握。这个题目还有另一种方法,称为牛顿法。一般牛顿法是用数值方法来解一个f(y)=0的方程。牛顿法需要记住公式:

image.png
代码如下:
class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        if x < 0:
            return -1
        if x == 0 or x == 1:
            return x
        r = x
        while r*r > x:
            r = (r + x/r) // 2
        return int(r)

其实,这道题还有一个巧妙的做法就是用位运算来进行求解,而且最多只需要判断16位,所以时间复杂度是O(1).
代码如下:

class Solution:
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        if x < 0:
            return -1
        if x == 0 or x == 1:
            return x
        result = 0
        bit = 1 << 16
        while bit:
            result |= bit
            if result * result == x:
                break
            elif result * result > x:
                result ^= bit
            bit >>= 1
        return result

74. Search a 2D Matrix

https://leetcode.com/problems/search-a-2d-matrix/description/

(1)Linear Search - O(m + n)
解法代码最容易实现,但时间复杂度最差,是线性的时间复杂度。思路即是从矩阵右上角开始向左搜索,找到第一个比目标小的元素再向下继续搜索即可。
代码如下:

class Solution:
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if not matrix or not len(matrix) or not len(matrix[0]):
            return False
        row, col = 0, len(matrix[0]) - 1
        while row < len(matrix) and col >= 0:
            if matrix[row][col] == target:
                return True
            if matrix[row][col] < target:
                row += 1
            else:
                col -= 1
        return False

(2)Double Binary Search - O(log(m) + log(n))
法只需要先按行查找,定位出在哪一行之后再进行列查找即可,所以就是进行两次二分查找。时间复杂度是O(logm+logn),空间上只需两个辅助变量,因而是O(1).
代码如下:

class Solution:
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if not matrix or not len(matrix) or not len(matrix[0]):
            return False
        left, right = 0, len(matrix) - 1
        while left <= right:
            mid = (left + right) // 2
            if matrix[mid][0] == target:
                return True
            if matrix[mid][0] < target:
                left = mid + 1
            else:
                right = mid - 1
        row = right
        left, right = 0, len(matrix[0]) - 1
        while left <= right:
            mid = (left + right) // 2
            if matrix[row][mid] == target:
                return True
            if matrix[row][mid] < target:
                left = mid + 1
            else:
                right = mid - 1
        return False

(3)Divide and Conquer - O(log(n)) - CC 11.6
Divide and Conquer解法时间复杂度最优,但代码过于繁琐。思路是利用左上-右下对角线的中点将矩阵划为4块进行分治,代码详见CC150.

240. Search a 2D Matrix II

https://leetcode.com/problems/search-a-2d-matrix-ii/description/

上一题的第一种解法即可。

相关文章

网友评论

      本文标题:LeetCode #35 #34 #69 #74 #240 20

      本文链接:https://www.haomeiwen.com/subject/uxmnvftx.html