刷题 双指针 滑动窗口

面试经典 150 题 - 双指针

⭐️125. 验证回文串

在这里插入图片描述
学会内部字母处理函数的使用

class Solution {
public:
    bool isPalindrome(string s) {
        int left = 0, right = s.size() - 1;
        while (left <= right) {
            // 处理左边字符
            if (!isalnum(s[left])) {
                ++left;
                continue;
            }
            // 处理右边字符
            if (!isalnum(s[right])) {
                --right;
                continue;
            }
            // 忽略大小写后比较字符
            if (tolower(s[left]) != tolower(s[right])) {
                return false;
            }
            ++left;
            --right;
        }
        return true;
    }
};

392. 判断子序列 - 贪心

在这里插入图片描述

class Solution {
public:
    // 双指针
    bool isSubsequence(string s, string t) {
        int i = 0;
        for (int j = 0; i < s.size() && j < t.size(); ++j) {
            if (s[i] == t[j]) {
                ++i;
            }
        }
        return (i == s.size());
    }
};

167. 两数之和 II - 输入有序数组 - 双向双指针

在这里插入图片描述

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        int left = 0, right = numbers.size() - 1;
        while(left < right) {
            int sum = numbers[left] + numbers[right];
            if (sum > target) --right;
            else if (sum < target) ++left;
            else return {left + 1, right + 1};
        }
        return {-1, -1};
    }
};

⭐️11. 盛最多水的容器

在这里插入图片描述

class Solution {
public:
    int maxArea(vector<int>& height) {
        int ans = 0, n = height.size();
        for (int l = 0, r = n - 1; l < r;) {
            ans = max(ans, min(height[l], height[r]) * (r - l));
            // 移动较长边:面积一定缩小
            // 移动较短边: 面积有可能变大
            if (height[l] < height[r]) {
                ++l; 
            } else {
                --r;
            }
        }
        return ans; 
    }
};

15. 三数之和 - 双向双指针

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        int n = nums.size();
        sort(nums.begin(), nums.end());
        for (int i = 0; i < n - 2; ++i) {
            while (i > 0 && i < n - 2 && nums[i] == nums[i - 1]) {
                ++i;
            }
            if (nums[i] > 0) {
                break;
            }
            for (int j = i + 1, k = n - 1; j < k;) {
                if (nums[k] < 0) {
                    break;
                }
                int sum = nums[i] + nums[j] + nums[k];
                if (sum < 0) {
                    ++j;
                } else if (sum > 0) {
                    --k;
                } else {
                    result.push_back({nums[i], nums[j], nums[k]});
                    ++j;
                    --k;
                    while (j < k && nums[j] == nums[j - 1]) {
                        ++j;
                    }
                    // while (k > j && nums[k] == nums[k - 1]) {
                    //     --k;
                    // }
                }
            }
        }
        return result;
    }
};

面试经典 150 题 - 滑动窗口

209. 长度最小的子数组

在这里插入图片描述

class Solution {
public:
    // 题目要求:总和大于等于 target 的长度最小的 子数组
    // 当找到窗口总和 大于等于 target,记录窗口宽度,再从左侧缩小窗口直至小于 target
    int minSubArrayLen(int target, vector<int>& nums) {
        int sum = 0;
        size_t ans = INT_MAX;
        for (size_t left = 0, right = 0; right < nums.size(); ++right) {
            sum += nums[right];
            while (sum >= target) {
                ans = min(ans, right - left + 1);
                sum -= nums[left];
                ++left;
            }
        }
        return ((ans == INT_MAX) ? 0 : ans);
    }
};

3. 无重复字符的最长子串

在这里插入图片描述

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        size_t ans = 0;
        array<char, 128> hash = {0};    // 包含所有 ASCII 码
        for (size_t left = 0, right = 0; right < s.size(); ++right) {
            while (hash[s[right]] == 1) {
                --hash[s[left]];
                ++left;
            }
            ++hash[s[right]];
            ans = max(ans, right - left + 1);
        }
        return ans;
    }
};

⭐️⭐️⭐️⭐️⭐️30. 串联所有单词的子串 - 分组滑动窗口

在这里插入图片描述

class Solution {
public:
    // 题目的特别之处:words 中所有字符串的长度都相同
    // 那我们是不是可以先获得子串的长度
    // 暴力解法: 根据 子串长度 * 单词表的大小 截取来做匹配
    // 复杂度: O(n * m)

    // 如何优化?分组滑动窗口 --> 分成 m 组
    // eg. barfoothefoobarman
    //      i = 0   [bar][foo][the][foo][bar][man]
    //      i = 1   b[arf][oot][hef][oob][arm]an
    //      i = 2   ba[rfo][oth][efo][oba][rma]n
    vector<int> findSubstring(string s, vector<string>& words) {
        size_t n = words.size(), m = words[0].size(), total_len = m * n;
        if (total_len > s.size()) return vector<int>{};
        unordered_map<string, int> word_count;
        vector<int> ans;
        for (auto& word : words) {
            word_count[word]++;
        }
        for (size_t i = 0; i < m; ++i) {    
            unordered_map<string, int> window_count;
            int words_used = 0;
            for (size_t left = i, right = i; right + m <= s.size(); right += m) {
                string word = s.substr(right, m);
                if (word_count.find(word) != word_count.end()) {
                    // 单词存在
                    window_count[word]++;
                    words_used++;
                    // 检测单词频率是否超过限制
                    while (window_count[word] > word_count[word]) {
                        window_count[s.substr(left, m)]--;
                        words_used--;
                        left += m;
                    }
                    if (words_used == n) {
                        ans.push_back(left);
                    }
                } else {
                    // 出现不存在的单词,直接清空重新开始即可
                    window_count.clear();
                    words_used = 0;
                    left = right + m;   // 将left移动到下一个位置
                }
            }
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值