【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;
}
相关推荐
春日见1 小时前
丝滑快速拓展随机树 S-RRT(Smoothly RRT)算法核心原理与完整流程
人工智能·算法·机器学习·路径规划算法·s-rrt
Code小翊1 小时前
”回调“高级
算法·青少年编程
云里雾里!1 小时前
力扣 977. 有序数组的平方:双指针法的优雅解法
算法·leetcode·职场和发展
一只侯子4 小时前
Face AE Tuning
图像处理·笔记·学习·算法·计算机视觉
Cinema KI4 小时前
吃透C++继承:不止是代码复用,更是面向对象设计的底层思维
c++
jianqiang.xue4 小时前
别把 Scratch 当 “动画玩具”!图形化编程是算法思维的最佳启蒙
人工智能·算法·青少年编程·机器人·少儿编程
不许哈哈哈5 小时前
Python数据结构
数据结构·算法·排序算法
J***79395 小时前
后端在分布式系统中的数据分片
算法·哈希算法
Dream it possible!6 小时前
LeetCode 面试经典 150_二叉搜索树_二叉搜索树中第 K 小的元素(86_230_C++_中等)
c++·leetcode·面试
sin_hielo7 小时前
leetcode 2872
数据结构·算法·leetcode