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

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

双指针与前缀和

记笔记时间: 2025-04-02

文章目录

  • 双指针与前缀和
    • [1 基本介绍](#1 基本介绍)
    • [2 双指针 - 例题](#2 双指针 - 例题)
  • [蓝桥杯第15届C/C++B组省赛 H题 - 拔河](#蓝桥杯第15届C/C++B组省赛 H题 - 拔河)

1 基本介绍

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

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

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

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

两种

  • 最常见

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

  • 不常见

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

核心思想

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

2 双指针 - 例题

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

cpp 复制代码
[38, 49, 65, 97]  [13, 27, 76]

代码

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

// ```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题 - 拔河

cpp 复制代码
// 试题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;
}
相关推荐
短尾黑猫19 分钟前
[LeetCode 1871] 跳跃游戏 7(Ⅶ)
算法·leetcode
杰瑞学AI43 分钟前
LeetCode详解之如何一步步优化到最佳解法:27. 移除元素
数据结构·python·算法·leetcode·面试·职场和发展
天天扭码1 小时前
一杯咖啡的时间吃透一道算法题——2.两数相加(使用链表)
前端·javascript·算法
写个博客2 小时前
代码随想录算法训练营第十八天
算法
时光の尘2 小时前
FreeRTOS菜鸟入门(五)·空闲任务与阻塞延时的实现
c语言·stm32·嵌入式硬件·mcu·物联网·freertos
岩中竹2 小时前
力扣热题100—滑动窗口(c++)
数据结构·c++·算法·leetcode
originalHSL2 小时前
同步/异步日志系统
c++
LIUDAN'S WORLD2 小时前
C++零基础实践教程 函数 数组、字符串与 Vector
开发语言·c++·算法
ChoSeitaku2 小时前
NO.95十六届蓝桥杯备战|图论基础-单源最短路|负环|BF判断负环|SPFA判断负环|邮递员送信|采购特价产品|拉近距离|最短路计数(C++)
c++·蓝桥杯·图论
南川琼语2 小时前
算法——希尔排序
数据结构·算法·排序算法