gh_mirrors/leet/leetcode项目:双指针技巧在题解中的应用

gh_mirrors/leet/leetcode项目:双指针技巧在题解中的应用

【免费下载链接】leetcode LeetCode题解,151道题完整版。广告:推荐刷题网站 https://www.lintcode.com/?utm_source=soulmachine 【免费下载链接】leetcode 项目地址: https://gitcode.com/gh_mirrors/leet/leetcode

在解决LeetCode算法问题时,我们经常会遇到需要优化时间复杂度的场景。双指针(Two Pointers)技巧作为一种高效的解题思路,能够帮助我们将嵌套循环的O(n²)复杂度降低到O(n),尤其适用于数组和字符串处理。本文将结合gh_mirrors/leet/leetcode项目中的题解,详细介绍双指针技巧的应用场景与实现方法。

一、双指针技巧的核心原理

双指针技巧通过使用两个指针(索引)在数据结构中移动,协同完成遍历或查找任务。根据指针移动方向,可分为两类:

  • 同向指针:两个指针朝同一方向移动,如滑动窗口问题
  • 相向指针:两个指针从两端向中间移动,如二分查找、回文判断

项目中C++/chapImplement.tex文件明确指出:"双指针,动态维护一个区间。尾指针不断往后扫,当扫到有一个窗口包含了所有T的字符后,然后再收缩头指针,直到不能再收缩为止。"这种滑动窗口思想是双指针技巧的典型应用。

二、滑动窗口:最小覆盖子串问题

问题描述

给定字符串S和T,在S中找出包含T所有字符的最小子串,时间复杂度要求O(n)。

双指针实现思路

  1. 使用左右两个指针表示窗口的边界
  2. 右指针不断扩展,直到窗口包含T的所有字符
  3. 左指针不断收缩,直到窗口不再包含T的所有字符
  4. 记录最小窗口长度

代码实现

// LeetCode, Minimum Window Substring
// 时间复杂度O(n),空间复杂度O(1)
class Solution {
public:
    string minWindow(string S, string T) {
        if (S.empty()) return "";
        if (S.size() < T.size()) return "";

        const int ASCII_MAX = 256;
        int appeared_count[ASCII_MAX];
        int expected_count[ASCII_MAX];
        fill(appeared_count, appeared_count + ASCII_MAX, 0);
        fill(expected_count, expected_count + ASCII_MAX, 0);

        for (size_t i = 0; i < T.size(); i++) expected_count[T[i]]++;

        int minWidth = INT_MAX, min_start = 0;  // 窗口大小,起点
        int wnd_start = 0;
        int appeared = 0;  // 完整包含了一个T
        //尾指针不断往后扫
        for (size_t wnd_end = 0; wnd_end < S.size(); wnd_end++) {
            if (expected_count[S[wnd_end]] > 0)  {  // this char is a part of T
                appeared_count[S[wnd_end]]++;
                if (appeared_count[S[wnd_end]] <= expected_count[S[wnd_end]])
                    appeared++;
            }
            if (appeared == T.size()) {  // 完整包含了一个T
                // 收缩头指针
                while (appeared_count[S[wnd_start]] > expected_count[S[wnd_start]]
                        || expected_count[S[wnd_start]] == 0) {
                    appeared_count[S[wnd_start]]--;
                    wnd_start++;
                }
                if (minWidth > (wnd_end - wnd_start + 1)) {
                    minWidth = wnd_end - wnd_start + 1;
                    min_start = wnd_start;
                }
            }
        }

        if (minWidth == INT_MAX) return "";
        else return S.substr(min_start, minWidth);
    }
};

三、区间合并:插入区间问题

问题描述

给定一组非重叠区间,插入一个新区间并合并所有重叠区间。

双指针实现思路

  1. 遍历区间列表,找到新区间需要插入的位置
  2. 合并所有与新区间重叠的区间
  3. 维护一个结果列表,用指针记录当前位置

代码实现

struct Interval {
    int start;
    int end;
    Interval() : start(0), end(0) { }
    Interval(int s, int e) : start(s), end(e) { }
};
 
//LeetCode, Insert Interval
// 时间复杂度O(n),空间复杂度O(1)
class Solution {
public:
    vector<Interval> insert(vector<Interval> &intervals, Interval newInterval) {
        vector<Interval>::iterator it = intervals.begin();
        while (it != intervals.end()) {
            if (newInterval.end < it->start) {
                intervals.insert(it, newInterval);
                return intervals;
            } else if (newInterval.start > it->end) {
                it++;
                continue;
            } else {
                newInterval.start = min(newInterval.start, it->start);
                newInterval.end = max(newInterval.end, it->end);
                it = intervals.erase(it);
            }
        }
        intervals.insert(intervals.end(), newInterval);
        return intervals;
    }
};

四、双指针技巧的典型应用场景

根据项目题解分析,双指针技巧主要应用于以下场景:

应用场景典型问题时间复杂度优化
滑动窗口最小覆盖子串、最长无重复子串O(n²)→O(n)
区间合并插入区间、合并区间O(n)
数组排序颜色分类、有序数组去重O(n)
链表操作检测环、寻找中点O(n)

项目中C++/chapSorting.tex明确提到:"// 双指针,时间复杂度O(n),空间复杂度O(1)",印证了双指针在排序问题中的高效性。

五、实战技巧与注意事项

  1. 指针初始化:根据问题类型选择合适的起始位置
  2. 循环条件:注意避免越界,明确指针移动终止条件
  3. 移动策略:同向指针注重窗口大小调整,相向指针注重边界条件判断
  4. 复杂度分析:双指针通常能将时间复杂度降低一个数量级

六、总结与扩展学习

双指针技巧是解决数组、字符串类问题的利器,通过gh_mirrors/leet/leetcode项目中的题解可以看出,掌握这一技巧能显著提升解题效率。建议进一步学习:

通过持续练习,你将能够灵活运用双指针技巧解决各类复杂问题,大幅提升算法效率与代码质量。

欢迎点赞收藏本教程,关注项目获取更多算法解题技巧!

【免费下载链接】leetcode LeetCode题解,151道题完整版。广告:推荐刷题网站 https://www.lintcode.com/?utm_source=soulmachine 【免费下载链接】leetcode 项目地址: https://gitcode.com/gh_mirrors/leet/leetcode

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值