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

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

牛客对应题目链接:比那名居的桃子 (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 来存变量。


相关文章
|
2月前
【编程题-错题集】kotori和气球(组合数学)
【编程题-错题集】kotori和气球(组合数学)
|
2月前
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
代码随想录Day29 贪心04 LeetCode T860 柠檬水找零 T406 根据身高重建队列 T452 用最少得箭引爆气球
29 0
|
2月前
|
容器
每日一题——接雨水(单调栈)
每日一题——接雨水(单调栈)
|
2月前
蓝桥备战--分糖果OJ2928 贪心 分类讨论
蓝桥备战--分糖果OJ2928 贪心 分类讨论
44 0
|
9月前
|
算法
【算法挨揍日记】day04——15. 三数之和、18. 四数之和
题目描述: 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
57 0
|
12月前
|
数据采集 算法 数据挖掘
【每周一坑】螺旋矩阵
今天这题,看起来挺简单,实际写出来并不容易。在以前公司我曾把它做过招聘的笔试题,结果惨不忍睹,不得不拿掉。
【每周一坑】螺旋矩阵
|
12月前
【牛客面试必刷TOP101】有效括号序列、滑动窗口的最大值
【牛客面试必刷TOP101】有效括号序列、滑动窗口的最大值
|
算法 索引
从五道leetcode掌握滑动窗口
可以看出,滑动窗口实际就是双指针同向移动的一种。可以想象,左右指针连接形成所谓的窗口,随着左右指针同时在数组中向后移动,就相当于窗口向后滑动,由此称为滑动窗口。值得注意的是,在指针向后的过程中,左右指针移动速度可以不同,所以窗口大小实际是不固定的。
|
机器学习/深度学习 人工智能
【第十五届蓝桥杯备赛(bushi,写文凑个数)】蓝桥OJ---排列序数
文章目录 一、题目 1、原题链接 2、题目描述 二、解题报告 1、思路分析 2、时间复杂度 3、代码详解 三、知识风暴 DFS
80 0
|
存储
【每日一题Day95】LC1815得到新鲜甜甜圈的最多组数 | 状态压缩dp 记忆化搜索
子问题、哪些操作会影响数据:余下的甜甜圈数量left,以及剩余可以选的元素个数 cnt[x]【dfs函数的两个参数->使用状态压缩至一个int类型变量中】
95 0
【每日一题Day95】LC1815得到新鲜甜甜圈的最多组数 | 状态压缩dp 记忆化搜索