Leetcode中级算法排序与搜索(3-8)动态规划(1-2)

在这里插入图片描述
写个最小堆呗,构建堆时用上浮算法(就是添加于末尾,若小于父节点,交换,直到到根节点为止),堆构建完成后,使用下沉算法,若大于根节点,与它交换,然后判断是否大于下面的值,直到最后一层。父节点 = 子结点-1>>1 子结点 = (父节点<<1)+1 or 前一个节点+1.

class Solution(object):
    class heap:
        __slots__ = ['k','h','size']
        def __init__(self,k):
            self.h = []
            self.k = k
            self.size = 0
        def add(self,val):
            
            if self.size<self.k:
                self.flow(val)
            else:
                self.sink(val)
            # print self.h


        def flow(self,val):
            self.h.append(val)
            self.size+=1
            inx = self.size-1
            while inx>0 and self.h[inx-1>>1]>self.h[inx]:
                inx_n = inx-1>>1
                self.h[inx],self.h[inx_n] = self.h[inx_n],self.h[inx]
                inx = inx_n
        
        def sink(self,val):
            if val<=self.h[0]:
                return
            self.h[0] = val
            inx =0
            while inx<self.k:
                inx_n = (inx<<1)+1
                if inx_n+1<self.k and self.h[inx_n+1]<self.h[inx_n]:
                    inx_n += 1
                if inx_n<self.k and self.h[inx_n]<self.h[inx]:
                    self.h[inx],self.h[inx_n] = self.h[inx_n],self.h[inx]
                else:
                    return
                inx = inx_n



            
    def findKthLargest(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        h = self.heap(k)
        for i in nums:
            h.add(i)
        return h.h[0]

在这里插入图片描述
看到logN的时间复杂度估计得二分,但是这玩意也没有顺序呀,不过其实这也不需要顺序,二分的核心思路就是每次扔一半的数呗。
这题只需要存在任意一个峰值即可,如果中间值的左大于它,那么左+中间值,必有峰值存在。但是因为是取左边界,为了避免死循环,取到的数必然是峰值的右一位。

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

在这里插入图片描述
二次二分搜索,一次找左边界一次找右边界,

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        

        left = 0
        right = len(nums)-1
        
        ans = [-1,-1]
        if nums==None or len(nums)==0:
            return ans 
        while left<right:
            mid = left+right>>1
            
            if nums[mid]<target:
                left = mid+1
            else:
                right = mid
   
        ans[0] = left if nums[left]==target else -1
        left = 0
        right = len(nums)-1
        while left<right:
            mid = left+right+1>>1
            if nums[mid]<=target:
                left = mid
            else:
                right = mid-1
        ans[1] = left  if nums[left]==target else -1
        return ans

在这里插入图片描述
首先一个左端排序,用一个数组保存结果,然后如果新来的元素,左端点大于右端点,那加一个新的,后面的必然比前一个大,和最后一个比较即可,若小于则合并。

class Solution:
    def merge(self, intervals):
        if len(intervals)<1:
            return intervals
        intervals.sort(key=lambda x: x[0])
        
        merged = [intervals[0]]
        for interval in intervals[1:]:
            if merged[-1][1] < interval[0]:
                merged.append(interval)
            else:
                merged[-1][1] = max(merged[-1][1], interval[1])

        return merged

在这里插入图片描述
老题了,就是正常判断然后加一波是否包含旋转。

var search = function(nums, target) {
    let left = 0,right = nums.length-1
    while(left<right){
        let mid = left+right>>1
        if(nums[mid]==target) {
                    left = mid;
                    break;
                }
                if(target>nums[nums.length-1]){
                    if(nums[mid]<target&&nums[mid]>nums[nums.length-1])
                        left = mid+1;
                    else
                        right = mid-1;
                }else{
                    if((nums[mid]>target&&nums[mid]<nums[0])||(nums[0]<nums[nums.length-1]&&nums[mid]>target))
                        right = mid-1;
                    else
                        left = mid+1;
                }
        
    }
    return nums[left]==target?left:-1
};

在这里插入图片描述
从左下角找起。

var searchMatrix = function(matrix, target) {
  if (!(matrix && matrix.length > 0 && typeof matrix[0][0] === 'number')) {
    return false;
  }
  if (target < matrix[0][0]) {
    return false;
  }
  let row = matrix.length - 1;
  let col = 0;
  while(col < matrix[0].length && row >= 0) {
    if (matrix[row][col] > target) {
      row--;
    } else if (matrix[row][col] < target) {
      col++
    } else {
      return true;
    }
  }
  return false;
};

在这里插入图片描述
这题更像是贪心,每次都一策略,选择当下最远能跳到的范围。

var canJump = function(nums) {
    let dis = nums[0];
    for(let i=0;i<nums.length-1;++i){
        if(nums[i]>nums.length-2)
            return true;
        dis--;
        dis = Math.max(nums[i],dis);
         if(dis<=0)
            return false;
    }

    return dis>=0;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值