【错题集-编程题】比那名居的桃子(滑动窗口 / 前缀和)

简介: 【错题集-编程题】比那名居的桃子(滑动窗口 / 前缀和)

牛客对应题目链接:比那名居的桃子 (nowcoder.com)


一、分析题目

1、滑动窗口

由题意得,我们是要枚举所有大小为 k 的子数组,并且求出这段⼦数组中快乐值和羞耻度之和。因此,可以利用滑动窗口的思想,用两个变量维护大小为 k 的窗口的总和,并且不断更新即可。


2、前缀和

这个就比较简单了,先预处理出来快乐值和羞耻度的前缀和数组,然后枚举的过程中直接求出⼀段区间的和即可(sum[i+k-1] - sum[i-1])。但是相比较于滑动窗口的思想,会有空间消耗。


二、代码

1、看题解之前AC的代码

//滑动窗口
#include <iostream>
using namespace std;
 
typedef long long LL;
const int N=1e5+10, INF=1e9+7;
int happy[N], shame[N];
 
int main()
{
    LL n, k;
    cin >> n >> k;
    for(int i=0; i<n; i++) cin >> happy[i];
    for(int i=0; i<n; i++) cin >> shame[i];
    int left=0, right=0;
    LL sum_happy=0, sum_shame=0;
    LL max_happy=0, min_shame=INF;
    LL st=0;
    while(right<n)
    {
        sum_happy+=happy[right];
        sum_shame+=shame[right];
        while(right-left+1>k)
        {
            sum_happy-=happy[left];
            sum_shame-=shame[left];
            left++;
        }
        if(right-left+1==k)
        {
            if(sum_happy>=max_happy)
            {
                if(sum_happy==max_happy && sum_shame<min_shame)
                {
                    st=left;
                    max_happy=sum_happy;
                    min_shame=sum_shame;
                }
                else if(sum_happy>max_happy)
                {
                    st=left;
                    max_happy=sum_happy;
                    min_shame=sum_shame;
                }
            }
        }
        right++;
    }
    cout << st+1 << endl; 
    return 0;
}

2、看了题解之后AC的代码

//前缀和
#include <iostream>
using namespace std;
 
typedef long long LL;
const int N=1e5+10, INF=1e9+7;
int happy[N], shame[N];
LL preHappy[N], preShame[N]; 
 
int main()
{
    LL n, k;
    cin >> n >> k;
    for(int i=1; i<=n; i++) cin >> happy[i];
    for(int i=1; i<=n; i++) cin >> shame[i];
    for(int i=1; i<=n; i++)
    {
        preHappy[i]=preHappy[i-1]+happy[i];
        preShame[i]=preShame[i-1]+shame[i];
    }
    LL max_happy=0, min_shame=INF;
    int st=0;
    for(int i=1; i<=n-k+1; i++)
    {
        LL sum_happy=preHappy[i+k-1]-preHappy[i-1];
        LL sum_shame=preShame[i+k-1]-preShame[i-1];
        if(sum_happy==max_happy && sum_shame<min_shame)
        {
            st=i;
            max_happy=sum_happy;
            min_shame=sum_shame;
        }
        else if(sum_happy>max_happy)
        {
            st=i;
            max_happy=sum_happy;
            min_shame=sum_shame;
        }
    }
    cout << st << endl;
    return 0;
}

3、值得学习的代码

// 滑动窗⼝
#include <iostream>
 
using namespace std;
 
typedef long long LL;
 
const int N = 1e5 + 10;
 
LL n, k;
LL h[N], s[N];
 
int main()
{
    cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> h[i];
    for(int i = 1; i <= n; i++) cin >> s[i];
 
    LL left = 0, right = 0;
    LL hSum = 0, sSum = 0, hMax = 0, sMin = 0, begin = 0;
 
    while(right <= n)
    {
        hSum += h[right];
        sSum += s[right];
        while(right - left + 1 > k)
        {
            hSum -= h[left];
            sSum -= s[left];
            left++;
        }
        if(right - left + 1 == k)
        {
            if(hSum > hMax)
            {
                begin = left;
                hMax = hSum;
                sMin = sSum;
            }
            else if(hSum == hMax && sSum < sMin)
            {
                begin = left;
                hMax = hSum;
                sMin = sSum;
            }
        }
        right++;
    }
 
    cout << begin << endl;
 
    return 0;
}

三、反思与改进

像这种设计题目背景的,一定要结合用例将题意弄清楚,否则思路很有可能是错的。虽然没有想到前缀和的方法,但想到了滑动窗口。因为数据量的原因,这里得用 long long 来存变量。


相关文章
|
监控 安全 Java
Java多线程调试技巧:如何定位和解决线程安全问题
【4月更文挑战第6天】本文探讨了Java并发编程中的线程安全问题,包括数据不一致、死锁和性能下降。为解决这些问题,文章介绍了理解线程安全的重要性,如互斥、同步和避免死锁,并提供了识别问题的迹象和调试工具,如JConsole、VisualVM、堆栈跟踪和Thread Dump分析。此外,还建议使用原子类、线程安全数据结构和静态代码分析工具来加强同步和减少锁粒度。最后,强调了避免共享状态和合理设计的重要性,以确保多线程程序的正确性和效率。
636 2
|
Java 开发工具 Windows
IDEA启动报端口占用 The port may already be in use or the connector may be misconfigured
【10月更文挑战第8天】本文介绍了在使用IDEA开发工具时遇到的端口占用问题及其解决方法。首先尝试关闭IDEA和Java进程,若无效则通过命令行查询并结束占用端口的进程,以确保项目顺利启动。
|
安全 Linux 测试技术
Linux命令setpriv详解
`setpriv` 是Linux下的命令行工具,用于调整进程权限以增强安全性,尤其适用于自动化和非交互式权限切换。它不使用PAM,支持管理能力集、GID/UID及SELinux上下文。例如,`setpriv --reuid=1000 script.sh` 可以以低权限用户运行脚本,而`--selinux-label`可设定SELinux标签。在使用时,应最小化权限、充分测试、保持与其他安全机制的兼容性,并定期审核权限设置。
|
数据采集 存储 自然语言处理
【数据挖掘】数据清洗、数据集成、数据标准化的详解(超详细 附源码)
【数据挖掘】数据清洗、数据集成、数据标准化的详解(超详细 附源码)
1787 0
|
Dart NoSQL JavaScript
Flutter 网络请求王者 Dio 简介
窥一貌而知全部,作为网络请求框架, dio不仅简单易用。而且还具备强大的高级功能。本篇对dio做了基本的介绍以及获取列表数据的示例。
934 0
|
机器学习/深度学习 传感器 编解码
【基于Ubuntu18.04+Melodic的realsense D435i安装】
【基于Ubuntu18.04+Melodic的realsense D435i安装】
2894 0
|
监控 关系型数据库 Linux
CentOS7下Zabbix5.0+PostgreSQL12+TimescaleDB部署实践
CentOS7下Zabbix5.0+PostgreSQL12+TimescaleDB部署实践
1079 0
CentOS7下Zabbix5.0+PostgreSQL12+TimescaleDB部署实践
|
安全 关系型数据库 PHP