leetcode-Contains Duplicate III-220

输入一个数组,求是否存在abs(i-j)<=k使得abs(nums[i]-nums[j])<=t
既要比较元素值又要比较下标,可以二重循环,但是这题的本意肯定不在此
我的做法:
set自定义数据类型和比较函数,如果nums[i]不同就按照升序排列,如果nums[i]相同按照下标降序排列
然后用两个指针,开始都指向开头,it指向当前判断的元素,it2指向it之前的元素:
1.如果it和it2的差值>t,说明it2指向的元素过时了,it2++
2.如果差值<=t:
1)如果下标满足条件,return true;
2)否则it++这里就是为什么自定义比较函数时按照下标降序,非常重要:
假设xxxxyyyzzz,指针it2,指向第一个x,指针it指向第一个y,且差值<=k,但是下标不满足<=t,这时该移动it2还是it?
如果是按下标升序排列,那么为了得到结果,(情况1)因为有可能中间的x的下标满足条件,所以应该移动it2,(情况2)但是万一所有x的下标都不满足条件,但是第一个x和后面的某个z满足条件,而我们已经移动了it2,导致第一个x不能参与计算,这就有错了。
也就是移动第一个指针的唯一条件是当元素差值>k,否则它都可能对后面的结果做出贡献而不能移动
所以这里应该移动it,不过移动it不就把情况1跳过了吗,也出错
所以这里下标降序排列,证明它的合法性:
1.假设第一个x的下标比第一个y的下标小,这时it往后移动,使得y的下标更小,更接近x的下标,这个思路是对的
2.假设第一个x的下标比第一个y的下标大,这时it往后移动,获得的y得下标会更大,离x的下标会更远,不可能得到true,但这个思路也是对的,为什么呢,因为最接近x的下标的就是前面的y的下标,它的不满足条件,后面的肯定不满足,不过我们还是移动it,这时移动it不是为了得到满足条件的情况,只是移动it而已,目的其实是移动到z
综上,即证

class Solution {
private:
    struct node{
        long long x,indx;
        node(long long x=0,long long indx=0):x(x),indx(indx){}
        bool operator<(const node &n)const{
            if(x<n.x) return true;
            if(x==n.x) return indx>n.indx;
            return false;
        }
    };
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
        int len=nums.size();
        if(len==0||len==1) return false;
        set<node> s;
        for(int i=0;i<len;i++){
            node no(nums[i],i);
            s.insert(no);
        }
        set<node>::iterator it=s.begin();
        node no=*it;
        set<node>::iterator it2=s.begin();
        it++;
        while(1){
            if(it->x-it2->x<=t&&abs(it->indx-it2->indx)<=k) return true;
            if(it->x-it2->x>t){
                it2++;
                if(it2==it) it++;
                if(it==s.end()) break;
                // no.x=it->x;
                // no.indx=it->indx;
            }
            else{
                it++;
                if(it==s.end()) break;
            }
        }
//        it2++;
//        while(it2!=it){
//            if(it->x-it2->x<=t&&abs(it->indx-it2->indx)<=k) return true;
//            it2++;
//        }
        return false;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值