cen's blog cen's blog
首页
  • 编程文章

    • markdown使用
  • 学习笔记

    • C++学习
    • C++数据结构
    • MySQL
    • Linux
    • 网络编程
算法
  • CLion
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 分类
  • 标签
  • 归档
关于
GitHub (opens new window)

cen

十年饮冰,难凉热血
首页
  • 编程文章

    • markdown使用
  • 学习笔记

    • C++学习
    • C++数据结构
    • MySQL
    • Linux
    • 网络编程
算法
  • CLion
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 分类
  • 标签
  • 归档
关于
GitHub (opens new window)
  • 双指针算法
    • 相向双指针
      • 633.平方数之和
    • 定长滑动窗口
      • 1456.定长子串中元音的最大数目
      • 3439.重新安排会议得到最多空余时间 I
    • 不定长滑动窗口
      • 最长子数组
      • 3.无重复字符的最长子串
      • 最短子数组
      • 209.长度最小的子数组
      • 子数组个数
  • 二分算法
  • 常用数据结构
  • 算法
cen
2025-08-02
目录

双指针算法

# 相向双指针

两个指针left=0, right=n−1,从数组的两端开始,向中间移动,这叫相向双指针

# 633.平方数之和

例题:给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a^2 + b^2 = c

示例:输入:c = 5 输出:true 解释:1^1 + 2^2 = 5

class Solution {
public:
    bool judgeSquareSum(int c) {
        int r = sqrt(c);
        int l = 0;
        while (l <= r) {
            // 做差:防止溢出
            int diff = c - r * r - l * l;
            if (diff < 0)
                r--;
            else if (diff > 0)
                l++;
            else
                return true;
        }
        return false;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 定长滑动窗口

三步走:

  • 入:下标为 i 的元素进入窗口,更新相关统计量。如果窗口左端点i − k + 1 < 0,即 i < k − 1,则尚未形成第一个窗口,重复第一步。
  • 更新:更新答案。一般是更新最大值/最小值。
  • 出:下标为 i − k + 1 的元素离开窗口,更新相关统计量,为下一个循环做准备。

# 1456.定长子串中元音的最大数目

例题:给你字符串 s 和整数 k。请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数,元音字母为(a, e, i, o, u)

示例:输入:s = "abciiidef", k = 3 输出:3 解释:子字符串 "iii" 包含 3 个元音字母

class Solution {
public:
    bool isVowel(char c) {
        return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
    }
    int maxVowels(string s, int k) {
        int l = 0;
        int r = l + k - 1;
        int ans = 0;
        int temp = 0;
        for (int r = l; r < s.size(); r++) {
            if (isVowel(s[r])) {
                temp++;
            }
            if (r - l + 1 < k)
                continue;
            ans = max(ans, temp);
            if (isVowel(s[l])) {
                temp--;
            }
            l++;
        }
        return ans;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 3439.重新安排会议得到最多空余时间 I

例题:给你一个整数 eventTime 表示一个活动的总时长,这个活动开始于 t = 0 ,结束于 t = eventTime 。同时给你两个长度为 n 的整数数组 startTime 和 endTime 。它们表示这次活动中 n 个时间 没有重叠 的会议,其中第 i 个会议的时间为 [startTime[i], endTime[i]] 。你可以重新安排 至多 k 个会议,安排的规则是将会议时间平移,且保持原来的会议时长,你的目的是移动会议后 最大化相邻两个会议之间的 最长连续空余时间。移动前后所有会议之间的相对顺序需要保持不变,而且会议时间也需要保持互不重叠。请你返回重新安排会议以后,可以得到的最大空余时间。

示例:输入:eventTime = 5, k = 1, startTime = [1,3], endTime = [2,5] 输出:2 解释:将 [1, 2] 的会议安排到 [2, 3] ,得到空余时间 [0, 2]

class Solution {
public:
    int maxFreeTime(int eventTime, int k, vector<int>& startTime,
                    vector<int>& endTime) {
        int n = startTime.size();
        int ans = 0;
        vector<int> spaceArea(n + 1, 0);
        // 最优就是(k + 1)个会议块连到一起
        for (int i = 0; i < n + 1; i++) {
            if (i == 0)
                spaceArea[i] = startTime[0];
            else if (i == n)
                spaceArea[i] = eventTime - endTime[n - 1];
            else
                spaceArea[i] = startTime[i] - endTime[i - 1];
        }
        int l = 0;
        int sum = 0;
        for (int r = l; r < n + 1; r++) {
            sum += spaceArea[r];
            if (r - l < k)
                continue;
            ans = max(ans, sum);
            sum -= spaceArea[l];
            l++;
        }
        return ans;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 不定长滑动窗口

# 最长子数组

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

题目:给定一个字符串 s,请你找出其中不含有重复字符的最长子串的长度。

示例:输入: s = "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是"abc",所以其长度为 3

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int ans = 0;
        int l = 0;
        unordered_map<char, int> map;
        // How to deal with ' '
        for (int r = l; r < s.size(); r++) {
            map[s[r]]++;
            while (map[s[r]] > 1) {
                map[s[l]]--;
                l++;
            }
            ans = max(ans, r - l + 1);
        }
        return ans;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 最短子数组

# 209.长度最小的子数组

题目:给定一个含有 n 个正整数的数组和一个正整数 target。找出该数组中满足其总和大于等于 target 的长度最小的子数组并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例:输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int ans = INT_MAX;
        int l = 0;
        int sum = 0;
        for (int r = l; r < nums.size(); r++) {
            sum += nums[r];
            while (sum >= target) {
                ans = min(ans, r - l + 1);
                sum -= nums[l];
                l++;
            }
        }
        return ans == INT_MAX ? 0 : ans;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 子数组个数

  1. 越短越合法:一般要写ans += right - left + 1
  2. 越长越合法:一般要写 ans += left
  3. 恰好型滑动窗口:例如,要计算有多少个元素和恰好等于 k 的子数组,可以把问题变成:
  • 计算有多少个元素和 ≥k 的子数组
  • 计算有多少个元素和 >k,也就是 ≥k+1 的子数组

答案就是元素和 ≥k 的子数组个数,减去元素和 ≥k+1 的子数组个数。

上次更新: 2025/09/03, 18:26:17
二分算法

二分算法→

最近更新
01
网络协议
09-03
02
套接字和TCP
08-26
03
常用数据结构
08-23
更多文章>
Theme by Vdoing | Copyright © 2024-2025 京ICP备2020044002号-3 京公网安备11010502056119号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式