【C/C++】双指针与前缀和

发布于:2025-04-09 ⋅ 阅读:(31) ⋅ 点赞:(0)

- 第 88 篇 -
Date: 2025 - 04 - 06(发博客时间)
Author: 郑龙浩/仟墨
【双指针与前缀和 C/C++】

双指针与前缀和

记笔记时间: 2025-04-02

1 基本介绍

准确来说,双指针只能说是算法中的一个技巧。

它并没有一个固定的模板,只是一个思想

双指针在遍历数据的过程当中不是简单的使用单个指针进行访问(也就是不是遍历一遍),而是使用两个相同方向或者相反方向的指针进行扫描。

双指针也可和前缀和结合使用

两种

  • 最常见

    在一个序列里边, 用两个指针维护一段区间

  • 不常见

    在两个序列里边,一个指针指向其中一个序列,另一个指针指向另一个序列,来维护某种次序。

核心思想

当暴力过不了的时候,可以使用双指针进行优化

2 双指针 - 例题

将两个有序顺序表合并成一个新的有序顺序表,并由函数返回结果顺序表

[38, 49, 65, 97]  [13, 27, 76]

代码

// 将两个有序顺序表合并成一个新的有序顺序表,并由函数返回结果顺序表

// ```cpp
// [38, 49, 65, 97]  [13, 27, 76]
// ```
#include <bits/stdc++.h>
using namespace std;
const int N = 4;
const int M = 3;
int arr[N] = {38, 49, 65, 97}, arr2[M] = {13, 27, 76}, ans[N + M];
int k = 0; // ans的长度
int main( void ) {
    int i = 0, j = 0;
    while (i < N && j < M) {
        if (arr[i] < arr2[j]) ans[k ++] = arr[i ++];
        else ans[k ++] = arr2[j ++];
    }
    // 为什么还要再写两遍while呢
    // 因为会出现两种情况
    // 1 当arr2数组全部放到ans数组中时,arr2数组中的数没完全或者没有放到ans数组中,所以需要二次遍历
    // 2 当arr数组全部放到ans数组中时,arr数组中的数没完全或者没有放到ans数组中,所以需要二次遍历
    
    // i < N  意思是 arr 数组中还有数值没有被遍历
    // j == M 意思是 arr2 数值中的数值已经全部被遍历,因为只有全部被遍历之后才会指向M
    while (i < N && j == M) ans[k ++] = arr[i ++]; //j == m 写不写都行,主要是便于理解的
    while (j < M && i == N) ans[k ++] = arr2[j ++]; //i == N 写不写都行
    for (int i = 0; i < N + M; i ++) {
        cout << ans[i] << ' ';
    }
    return 0;
}

蓝桥杯第15届C/C++B组省赛 H题 - 拔河

// 试题H 洛谷P10429 拔河  第二次写
// Date: 2025-04-04
// Author: 郑龙浩 / 仟墨
// 算法: 双指针 + 前缀和
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e3 + 5;
int n;// 人数
ll arr[N], sumA = 0, sumB = 0, minNum = LLONG_MAX;
int main( void ) {
    cin >> n;
    for (int i = 0; i < n; i ++) cin >> arr[i];
    for (int i = 0; i < n - 1; i ++) {
        for (int j = i + 1; j < n; j ++) {
            sumA = arr[i], sumB = arr[j]; // 重置总和
            minNum = min(minNum, abs(sumB - sumA));
            int l = i - 1, r = j + 1; // 左右
            while (l >= 0 && r < n) { // 若指针指向的是队伍内
                if (sumA < sumB) {
                    sumA += arr[l];
                    l --;
                    minNum = min(minNum, abs(sumB - sumA));
                } else {
                    sumB += arr[r];
                    r ++;
                    minNum = min(minNum, abs(sumB - sumA));
                }
            }
            while (l >= 0 && r == n) {
                sumA += arr[l];
                l --;
                minNum = min(minNum, abs(sumB - sumA));
            }
            while (r < n && l == 0) {
                sumB += arr[r];
                r ++;
                minNum = min(minNum, abs(sumB - sumA));
            }
        }
    }
    cout << minNum << '\n';
    return 0;
}