leetcode刷题记录:算法(二)二分法

二分法就不多讲了,很基础的算法,适用于排好序的数,可以提升很高的效率。

704.二分查找
执行用时:276 ms, 在所有 Python3 提交中击败了98.03%的用户

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        low = 0
        high = len(nums)-1
        while(low<=high):
            temp = (low+high)//2
            if nums[temp]==target:
                return temp
            elif nums[temp]>target:
                high = temp-1
            elif nums[temp]<target:
                low = temp+1
        return -1

25.搜索插入位置
执行用时:44 ms, 在所有 Python3 提交中击败了48.98%的用户
基本上是上一道题没有修改,不过使用二分法有点慢啊。

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        low, high = 0, len(nums)-1
        while(low<=high):
            temp = (low+high)//2
            if nums[temp]==target:
                return temp
            elif nums[temp]>target:
                high = temp-1
            elif nums[temp]<target:
                low = temp+1
        return low

162.查找峰值。
这道题比较难(中等难度的对于我这种小白来说就是难的了),一开始还是没做出来,看了官方给的解题思路。

力扣的描述是:
峰值元素是指其值大于左右相邻值的元素。
给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。
数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞。

而且要求了O(logN)的时间复杂度。

看题目:
1.只要找到一个峰值就可以
2.相邻元素不相等
3.nums[-1] = nums[n] = -∞
这样三个条件。

一开始我写代码的时候,总是以nums[i-1]<nums[i] > nums[i+1]作为峰值的判别条件,从而导致列表的两端很难处理,总是溢出,需要进行很多条件判断,越写越长,代码逐渐复杂了起来,想来应该不会出这么没有营养的题目,就没忍住看了答案(哭)。

官方解答中,最重要的一点就是可以通过只比较nums[i] 和 nums[i+1]的大小,就能达到判断的目的。
取i为当前要处理的列表的中点,考虑如下几种情况:

  1. nums[i] > nums[i+1]
    此时,将游标从中点[i]向右侧移动,值是下降的;
    又因为nums[-1]可以看作负无穷,所以将游标从[-1]向右移动,值必然是上升的;
    所以在列表的左半部分,[0, i+1]中(两侧都包含,因为i可能是峰值)值先上升在下降,必然存在一个峰值。
  2. nums[i] < nums[i+1]
    此时,将游标从中点[i]向右侧移动,值是上升的;
    又因为nums[n]可以看作负无穷,所以将游标从[n]向左移动,值必然是上升的;
    所以在列表的右半部分,(i, n-1]中(左侧i不包含,因为i必然不可能是峰值)值先上升在下降,必然存在一个峰值。

很容易想到,这里应该使用递归,但是我还没学到递归,就暂时用迭代写了一下。

可见做算法题主要还是思路。

class Solution:
    def findPeakElement(self, nums: List[int]) -> int:
        left,right = 0,len(nums)-1
        while(left<=right):
            if left == right:
                return left
            temp = (left+right)//2
            if nums[temp]>nums[temp+1]:
                right = temp
            elif nums[temp]<nums[temp+1]:
                left = temp+1  ##+1抛弃无用值,而且如果left和right都不+-1的话,最终left无法等于right,会无限循环。

然后是74题,搜索二维矩阵。
这道题也是比较简单的,读题可以了解到,如果将矩阵铺平,其实就是一个已经排好序的列表,我们完全可以套用之前的代码,只不过将temp进行一下换算就可以满足要求。

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
    	##  这里排除了一个特殊情况,因为如果是空矩阵,下面的代码会报错
        if(len(matrix)==0): 
            return False
        ##  获取矩阵的维度,如果用numpy的话应该是matrix.shape
        m, n = len(matrix), len(matrix[0]) 
        length = m*n     ##计算总长度                  
        left, right = 0, length-1
        while(left <= right):
            temp = (left+right)//2
            ##  与前面的代码相比只有这里不一样,将长度换算为行列数
            x = temp // n                  
            y = temp % n
            if matrix[x][y] == target:
                return True
            elif matrix[x][y] > target:
                right = temp-1
            elif matrix[x][y] < target:
                left = temp+1
        return False

好啦,二分法就先做这几道题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值