算法——滑动窗口

题目一:. - 力扣(LeetCode)

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

        // for(int length=2;length<=k+1;length++)
        // {
        //     int temp=nums.size()-length;
        //     for(int i=0;i<=temp;i++)
        //     {
        //         if(nums[i]==nums[i+length-1])return true;
        //     }
        // }

        unordered_set<int>s;
        for(int i=0;i<nums.size();i++)
        {
            if(i>k)s.erase(nums[i-k-1]);
            if(s.find(nums[i])!=s.end())return true;
            s.insert(nums[i]);
        }
        return false;
    }
};

前两个都能过,但是第二个显然效率低得多。第二个严格意义上还是暴力,不算滑动窗口。

维护一个哈希表,哈希表最大长度为k+1,如果超过该长度则移除最前面的元素。不断判断直到哈希表内出现重复元素,即满足条件。

题目二:哈希表+滑动窗口+位运算

. - 力扣(LeetCode)

class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        // vector<string>res;
        // if (s.length() <= 10)return  res;
        // unordered_multiset<string>set;
        // int left = 0, right = 10;
        // string str(s.begin(), s.begin() + 10);
        // set.insert(str);
        // while (right < s.length())
        // {
        //     str.erase(str.begin());
        //     str += s[right];
        //     if (set.count(str) == 1)
        //     {
        //         set.insert(str);
        //         res.push_back(str);
        //     }
        //     else if(set.count(str)==0)
        //         set.insert(str);
        //     right++;
        // }
        // return res;

        unordered_map<char, int>bin = { {'A',0},{'C',1},{'G',2},{'T',3} };
        vector<string>res;
        if (s.length() <= 10)return res;
        int x = 0;
        for (int i = 0; i < 10; i++)
        {
            x = (x << 2) | bin[s[i]];
        }
        unordered_map<int, int>map;
        map[x] = 1;
        for (int i = 10; i < s.length(); i++)
        {
            x = ((x << 2) | bin[s[i]]) & ((1 << 20) - 1);
            if (map[x] == 1)
            {
                res.push_back(s.substr(i - 10 + 1, 10));
                map[x] = 2;
            }
            else if(map[x]==0)map[x] = 1;
        }
        return res;
    }
};

第一种方式(注释代码):即维护一个长度为10的set,当发现集合中元素已经出现过时将该元素加入集合,使用mulitiseset,可以加入重复元素,仅当个数为1时才加入结果集中,防止重复。

第二种方式使用了位运算,因为只有4种状态,可以使用二进制00,01,10,11来表示。10个便是20位,使用一个int,32位完全足够,且只需要使用低20位。存哈希表时不再存字符串而存储其对应的int值,保证能一一映射。滑动窗口时,当前数x左移两位,或运算上新来的数字,并且与运算(1<<20)-1,即低20位不变高12位清零。

位运算,很巧妙。

相关推荐
好奇龙猫36 分钟前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
sp_fyf_20241 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
ChoSeitaku2 小时前
链表交集相关算法题|AB链表公共元素生成链表C|AB链表交集存放于A|连续子序列|相交链表求交点位置(C)
数据结构·考研·链表
偷心编程2 小时前
双向链表专题
数据结构
香菜大丸2 小时前
链表的归并排序
数据结构·算法·链表
jrrz08282 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time2 小时前
golang学习2
算法
@小博的博客2 小时前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
南宫生3 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法
懒惰才能让科技进步3 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝