Leetcode二分查找11:1346. 检查整数及其两倍数是否存在

链接:https://leetcode-cn.com/problems/check-if-n-and-its-double-exist/https://leetcode-cn.com/problems/check-if-n-and-its-double-exist/

题意就在题目中。 

一.初步分析

初看题目可以暴力解,二重循环解决。

时间复杂度:O(n^2)

空间复杂度:O(1)

class Solution {
public:
    bool checkIfExist(vector<int>& arr) {
        for (auto i = arr.begin(); i != arr.end(); ++i)
            for (auto j = arr.begin(); j != arr.end(); ++j)
                if (i != j && *i * 2 == *j)
                    return true;
        return false;
    }
};

二.对暴力进行优化

首先想到二分、双指针。

但是这样开始也必须排序,然后定义两个指针:指针p遍历x,指针q找2x。分为两种情况:

1.对于 x>0 的情况,指针只需要一直前进。若q在前进过程中找到一个比 2x大的数字,那么2x必然不存在(数组元素已经升序排列)。在p前进的过程中p所指向的x会不断递增,2x也会不断递增,因此指针q不需要后退。
2.对于 x<0 的情况,指针只需要一直后退。若q在后退过程中找到一个比2x小的数字,那么2x必然不存在(数组元素已经升序排列)。在p后退的过程中p所指向的x会不断递减,2x也会不断递减,因此指针q不需要前进。

时间复杂度:O(nlogn)
排序的时间复杂度为O(nlogn),两次指针遍历的过程时间复杂度为O(n),综合起来,复杂度为 O(nlogn)。
空间复杂度:O(n)
sort 函数空间复杂度为 O(n),双指针遍历的空间复杂度为 O(1),综合起来,复杂度为 O(n)。

class Solution {
public:
    bool checkIfExist(vector<int>& arr) {
        sort(arr.begin(), arr.end());
        for (auto i = arr.begin(), j = arr.begin(); i != arr.end(); ++i) {//从前向后
            while (j != arr.end() && *i * 2 > *j)//必须写成*i(像指针一样),且j在i后,肯定是i*2==j
                ++j;
            if (j != arr.end() && i != j && *i * 2 == *j)
                return true;
        }
        for (auto i = arr.rbegin(), j = arr.rbegin(); i != arr.rend(); ++i) {//从后往前
            while (j != arr.rend() && *i * 2 < *j)
                ++j;
            if (j != arr.rend() && i != j && *i * 2 == *j)
                return true;
        }
        return false;
    }
};

三:神级方法:哈希

哈希法适用于数组值与下标之间相互查找,用一个auto类型的变量x去遍历数组arr,如果m[2*x]或者m[x/2](x为偶数)存在,返回true;如果遍历的值不存在那么m[x]就自增,继续查找。

时间复杂度:O(n)
哈希表的查询时间复杂度为O(1),查询次数为O(n),综合起来,时间复杂度为O(n)。
空间复杂度:O(n)
哈希表最多需要存储n个元素。

class Solution {
public:
    bool checkIfExist(vector<int>& arr) {
        unordered_map<int,int> m;
        for(auto x:arr){
            if(m[x*2]||(m[x/2]&&x%2==0)) return true;
            else m[x]++;
        }
        return false;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

华梦天下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值