【Leetcode】962. 最大宽度坡

地址:962. 最大宽度坡

题目

给定一个整数数组 A是元组 (i, j),其中  i < j 且 A[i] <= A[j]。这样的坡的宽度为 j - i

找出 A 中的坡的最大宽度,如果不存在,返回 0 。

示例

输入:[6,0,8,2,1,5]
输出:4
解释:
最大宽度的坡为 (i, j) = (1, 5): A[1] = 0 且 A[5] = 5.

思路

二分查找

  • 关于右边界的选择应该是降序的,比如存在j1,j2,且a[j1] <= a[j2],此时的右边界就该选择j2
  • 当a = [0,8,2,7,5]时,对于i=0的候选右边界位置candidates = [(v=5, j=4), (v=7, j=3), (v=8, j=1)]。我们要时刻维护候选列表 candidates 按照索引值降序,对应值升序

算法实现

  • 从右边开始循环降序,这一步就遵循了上面所说的索引值降序的原则,下面只需要保证对应值升序即可。
  • 每一次更新i值都要进行二分查找,观察现在遍历到的键值与候选键值的关系
  • 如果循环结束的左边指针指向的位置<候选队列的长度,说明在二分查找的过程中候选键中所有键值value都>=当前i指向的数值,由于维护的candidates按照对应值升序的原则,故没有新候选j加入
  • 但如果二分查找完毕后左边指针位置=候选列表长度,说明在此过程中存在nums[i]>candidates的所有键值,可以加入

代码

class Solution {
public:
    int maxWidthRamp(vector<int>& nums) {
        int len = nums.size();
        int ans = 0;
        vector<vector<int>> cd;
        cd.push_back({nums[len-1],len-1});
        //候选j降序,值升序的规则
        for(int i=len-2;i>=0;--i){  //倒着统计候选位置j
            int l = 0,r = cd.size();   //记录的是侯选j的个数
            while(l < r){
                int mid = l + (r - l) / 2;
                if(cd[mid][0]<nums[i]){ //如果没有遇见比候选键大的值就别进来了
                    l = mid + 1;
                }
                else
                    r = mid;
            }
            if(l < cd.size()){
                int j = cd[l][1];
                ans = max(ans,j-i);
            }
            else{
                cd.push_back({nums[i],i});  //继续统计降序的j
                for(int k=0;k<cd.size();k++){
                    cout<<cd[k][0]<<" "<<cd[k][1]<<endl;
                }
            }
        }
        return ans;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值