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

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

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


相关文章
|
7月前
【错题集-编程题】最长上升子序列(二)(贪心 + 二分)
【错题集-编程题】最长上升子序列(二)(贪心 + 二分)
|
7月前
|
人工智能 JavaScript
【错题集-编程题】最大子矩阵(二维前缀和)
【错题集-编程题】最大子矩阵(二维前缀和)
|
7月前
|
算法
leetcode代码记录(摆动序列
leetcode代码记录(摆动序列
34 0
|
机器学习/深度学习
【N皇后】
【N皇后】
|
算法
代码随想录算法训练营第三十一天 | LeetCode 455. 分发饼干、376. 摆动序列、53. 最大子数组和
代码随想录算法训练营第三十一天 | LeetCode 455. 分发饼干、376. 摆动序列、53. 最大子数组和
70 0
|
C++
【LeetCode343】剪绳子(动态规划)
(1)确定状态 dp[i]是将正整数i拆成2个及其以上的正整数后,求所有数的乘积值。
145 0
【LeetCode343】剪绳子(动态规划)
|
算法 安全
代码随想录算法训练营第六天| 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和
代码随想录算法训练营第六天| 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和
|
算法 索引
代码随想录算法训练营第八天 | 344.反转字符串541. 反转字符串II 剑指Offer 05.替换空格151.翻转字符串里的单词剑指Offer58-II.左旋转字符串
代码随想录算法训练营第八天 | 344.反转字符串541. 反转字符串II 剑指Offer 05.替换空格151.翻转字符串里的单词剑指Offer58-II.左旋转字符串
|
机器学习/深度学习 算法 JavaScript
代码随想录训练营day31| 455.分发饼干 376. 摆动序列 53. 最大子序和
代码随想录训练营day31| 455.分发饼干 376. 摆动序列 53. 最大子序和
|
机器学习/深度学习 算法
代码随想录训练营day53| 1143.最长公共子序列 1035.不相交的线 53. 最大子序和...
代码随想录训练营day53| 1143.最长公共子序列 1035.不相交的线 53. 最大子序和...