力扣之1550题219题2021-03-24

这篇博客探讨了两种常见的数组问题解决方案。一是通过优化循环条件和位运算来提高寻找连续三个奇数的效率,避免数组越界。二是利用哈希表实现滑动窗口查找,以线性时间复杂度解决存在重复元素且距离限定的问题。文章强调了哈希表在快速查找和减少时间复杂度中的关键作用,并给出了具体的C++实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、#1550存在连续三个奇数的数组 #数组

时间复杂度o(n),空间复杂度o(1)

①关键:报错,堆缓冲区溢出,内存错误。

解决:把在前面加上int n=arr.size(),后面直接写i<n-2。或者直接在后面写上i+2<arr.size()。

原因:用到size()运算时,因为size()的返回值类型是unsigned int,会把后面的相关运算数-2都强制换成无符号整型,于是报错数组越界。

参考:【LeetCode/C++】循环条件i小于size()-1越界_半盒果酱的博客-优快云博客

②位运算比取模运算快很多,所以写成位运算&1取代%2。

a % (2^n) 等价于 a & (2^n - 1);a % 2 等价于 a & 1       

③C++与运算写成&就可以

&与| 既可以进行逻辑运算,又可以进行位运算,两边既可以是bool类型,又可以是数值类型

class Solution {
public:
    bool threeConsecutiveOdds(vector<int>& arr) {
        /*int n=arr.size();
        for(int i=0;i<n-2;++i){*/
        for(int i=0;i+2<arr.size();++i){
            if((arr[i]&1)&(arr[i+1]&1)&(arr[i+2]&1))return true;
        }
        return false;
    }
};

/*我:
class Solution {
public:
    bool threeConsecutiveOdds(vector<int>& arr) {
        int n=arr.size();
        for(int i=0;i<n-2;++i){
            int cnt=0;
            for(int j=i;j<i+3;++j){
                if(arr[j]%2!=0)++cnt;
            }
            if(cnt==3)return true;
        }
        return false;
    }
};*/

2、#219 存在重复元素  #数组 #哈希表

时间复杂度o(n),空间复杂度o(min(n,k)),开辟的额外空间取决于散列表中存储的元素的个数,也就是滑动窗口的大小 O(min(n,k))。

????

①关键:用自己的暴力直接求法,不管是把给出的相等和距离的两个条件都用到for循环内,或者把距离用在for条件内、判断相等放在for循环内,不管怎样,用了两个for循环都会超时,光执行时间就是4ms。时间复杂度要么是o(n²),要么是o(nk),总之这样不行,想办法最好是o(n)才可以。

解决:此时就要用另外一种数据结构哈希表,哈希表可以常数时间实现查找,插入,删除等操作。用STL里面的unordered_map容器,其内部实现哈希表,容器元素的排列顺序不同于map,是杂乱无序的,对于查找非常快非常适合,因为键可以不通过搜索就访问无序 map 中的对象,所以可以很快检索出无序 map 中的元素。对于顺序要求高的使用map更适合。

unordered_map将相同哈希值得键值放在相同的桶里。

注意,平时说的vector也是一种容器。STL 是 C++ 标准程序库的核心,STL 组件主要包括容器,迭代器、算法和仿函数。迭代器用于在一个对象群集的元素上进行遍历动作。

②整个过程:比如数组元素有1231,一开始map里面无。当1,map:插入<1,0>,当2,map:插入<2,1>,当3,map:插入<3,2>,当1,map:找到1的键值对为0,此时if可行,算距离为3-0=3,返回true。

③建立基本数据类型的哈希表unordered_map<int,int> map;

map.end()指向哈希表的最后一个容器,实则超出了哈希表的范围,为空

map.find(nums[i]) 查找key为nums[i]数组元素的键值对是否存在 ,未找到则返回map.end()。所以如果==map.end(),则未找到

if(map.find(nums[i])!=map.end()) 说明找到了key为数组元素的键值对。

注意,所有哈希表题目总结参考哈希集合与哈希表的刷题总结_Leopiglet的博客-优快云博客_哈希集合和哈希表

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        unordered_map<int,int> map;// key: 数组元素, value:元素所在下表,注意,此时还没有map键值对
        for(int i=0;i<nums.size();i++){
            if(map.find(nums[i])!=map.end()&&i-map[nums[i]]<=k){//找到此元素的键值对,会返回当前迭代器,但没找到就会返回map.end(),然后
                return true;
            }
            map[nums[i]]=i;// 这个语句包括两个功能:不是插入,只是把原来那个键值对,更新一下值;插入值,数组访问模式插入(和数组的[]操作很相似)
        }
        return false;
    }
};


/*我:
class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        int n=nums.size();
        for(int i=1;i<=k;i++){
            for(int j=0;j<n-i;j++){
                if(nums[j]==nums[j+i])return true;
            }
        }
        return false;
    }
};*/

/*class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        int n=nums.size();
        for(int i=0;i<n-1;i++){
            for(int j=i+1;(j<i+k+1)&(j<n);j++){
                if(nums[i]==nums[j])return true;
            }
        }
        return false;
    }
};*/

/*class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        for(int i=0;i+1<nums.size();i++){
            for(int j=i+1;j<nums.size();j++){
                if((nums[i]==nums[j])&(abs(j-i)<=k))return true;
            }
        }
        return false;
    }
};*/

总结:在做数组题时,思考时的小tip,先写出一串a1a2a3...这种数组形式,根据题意写出一些遍历的过程,通过遍历的过程去设置无论几个for循环的条件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值