PAT-Apat甲级题1007(python和c++实现)

news2024/12/26 23:43:03

PTA | 1007 Maximum Subsequence Sum

1007 Maximum Subsequence Sum

作者 CHEN, Yue

单位 浙江大学

Given a sequence of K integers { N1​, N2​, ..., NK​ }. A continuous subsequence is defined to be { Ni​, Ni+1​, ..., Nj​ } where 1≤i≤j≤K. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (≤10000). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:

10
-10 1 2 3 4 -5 -23 3 7 -21

Sample Output:

10 1 4

 万事开头难,先读题!

 

给定K个整数{ N1,N2,...,NK }。连续子序列被定义为{ Ni,Ni+1,...,其中1≤i≤j≤K。最大子序列(Maximum Subsequence)是一个连续的子序列,它具有最大的元素和。例如,给定序列{-2,11,-4,13,-5,-2 },其最大子序列为{ 11,-4,13 },最大和为20。

现在你应该找到最大的总和,以及最大子序列的第一个和最后一个数字。
输入规范:

每个输入文件包含一个测试用例。每种情况占两行。第一行包含正整数K(≤10000)。第二行包含K个数字,由空格分隔。
输出规格:

对于每个测试用例,在一行中输出最大和,以及最大子序列的第一个和最后一个数字。数字之间必须用一个空格隔开,但行尾不能有多余的空格。如果最大子序列不是唯一的,则输出具有最小索引i和j的子序列(如示例所示)。如果所有的K数都是负数,那么它的最大和被定义为0,你应该输出整个序列的第一个和最后一个数字。

由题目可以提取到以下关键信息:

        1, 给出指定长度的数组,一行输入长度,一行输入数组,最大长度是10000

        2, 要求的结果是:最大连续子数组的和以及这段子数组的起始位置和末尾位置,考虑是差分和前缀和的应用

        3, 如果是全负数数组,需要按照规定的输出规范进行输出

题目分析完之后,现在是手搓代码时间!!!

本题要求很简洁明了,即求最大的连续子数组和,在这里考虑使用差分与前缀和的思想对本题进行求解,同时又需要输出这段子数组的起始位置和末尾位置,因此首先定义两个变量用于记录这两个位置:head和tail,对输入数据进行处理,定义k用于接收数组的长度,对于C++,可以考虑定义长度为10001的数组用于存储,python的列表没有长度限制,因此只需要定于列表生成式对输入进行处理即可。

由于考虑使用差分和前缀和的思想解决本题,因此这里为了方便后续操作,分别对输入数组的下标0位置和前缀和数组的下标为零位置赋初值:0,使得前缀和数组中自下标位置起为“前 [i] 个子数组的和”,至于输入数组赋初值的原因,则是为了配合前缀和数组方便操作。

初始化代码和对于输入的处理部分如下:

python部分:

k = int(input()) # 接收输入
lst = [int(i) for i in input().split()] # 接收输入数组
lst.insert(0,0) # 输入数组下标为0位置赋初值0
sum_ = [0] * (len(lst)+1) # 生成前缀和数组,为了防止索引越界,一般考虑稍微初始化大一点点
for i in range(1, len(lst)):
    sum_[i] = sum_[i-1] + lst[i] # 计算前缀和数组

C++部分:

    cin >> k;// 接收输入
    sum_[0] = 0; // 前缀和数组初始值赋0
    for(int i=1;i<=k; i++){
        cin>> arr[i]; // 接收输入数组
    }
    for(int i=1; i<= k; i++){
        sum_[i] = sum_[i-1] + arr[i]; // 计算前缀和数组
    }

接下来是本题解题的核心部分,根据前缀和数组计算连续数组的最大和部分。

        由于初始化前缀和数组第一个元素为0,这里则直接从下标为1的位置开始操作,首先定义用于记录最大和的变量result,初始化为-1,这里因为全负数数组有规定的输出格式,且不需要其他额外的操作,因此为了遍历完前缀和数组后可以分辨出该数组是否为全负数数组,此处初始化为-1而不是0,因为全负数数组其子序列的和不可能为正数,但非全负数数组可能存在全零的情况,故此处不初始化为0,避免对后续造成干扰,细节处应该给予充分考虑,避免造成不必要的代码调试时间的浪费。

        此后,我们使用循环,遍历前缀和数组,初始化一个标记变量lowest,用于记录每次最长子数组发生变化后的起始部分,这里初始化为0,因为0下标对应的元素初始化为0,不纳入考虑,循环遍历时,应当使用前缀和数组的元素对下标为lowest的前缀和数组元素进行相减,比如:对于下标为i的前缀和数组sum[i],与标记位置元素sum[lowest] ,其差值为自下标lowest+1到下标为i这段子数组的和,得到这部分子数组的和,我们可以将其与result进行比较,只要发现结果大于result,则更新result,同时head更新为lowest+1,tail更新为i,即【head , tail】部分即为当前所遍历得到的最大连续子数组和,通过循环不断更新i的位置,最终将得到最大的连续子数组和result,以及其初始位置和结束位置下标,同时需要注意的是:标记lowest并不是一成不变的,需要在每次遍历的时候比较sum[i]以及sum[lowest]的大小,只要sum[i]比sum[lowest]小,则更新lowest的位置为i,这里也不难理解,当被减数sum[i]一定时,只有减数sum[lowest]最小,得到的差才能最大,也就是下标为lowest+1到i这部分子数组的和才能最大,这也是解决连续子数组问题的关键点之一。以下是这部分的代码实现:

python:

res = -1 # 最大连续子数组和
lowest = 0 # 标记位置
head = 0
tail = 0
for end in range(len(lst)):
    if sum_[end] - sum_[lowest] > res: # 当前计算结果大于之前计算得到的最大连续子数组和,更新
        res = sum_[end] - sum_[lowest]
        head = lowest + 1
        tail = end
    if sum_[lowest] > sum_[end]: # 保证减数最小
        lowest = end

C++:

// 初始化对应变量
int lowest=0,result=-1;
int head,tail;

    
for(int end=1; end<=k; end ++){
    if(sum_[end] - sum_[lowest] > result){ // 当前计算得到的最大连续子数组和大于以前计算的
        result = sum_[end] - sum_[lowest];
        head = arr[lowest + 1];
        tail = arr[end];
    }
     if(sum_[lowest] > sum_[end]){ // 保证减数最小
        lowest = end;
    }
}

最后是完整的的代码部分:

C++:

#include<bits/stdc++.h>
using namespace std;

int k;
int lowest=0,result=-1;
int head,tail;
int arr[1001],sum_[1001];

int main(){
    cin >> k;// 接收输入
    sum_[0] = 0; // 前缀和数组初始值赋0
    for(int i=1;i<=k; i++){
        cin>> arr[i]; // 接收输入数组
    }
    for(int i=1; i<= k; i++){
        sum_[i] = sum_[i-1] + arr[i]; // 计算前缀和数组
    }
    for(int end=1; end<=k; end ++){
        if(sum_[end] - sum_[lowest] > result){
            result = sum_[end] - sum_[lowest];
            head = arr[lowest + 1];
            tail = arr[end];
        }
        if(sum_[lowest] > sum_[end]){
            lowest = end;
        }
    }
    if(result < 0){
        cout << 0 << " " << arr[1] << " " << arr[k];
    }
    else{
        cout << result << " " << head <<" " << tail;
    }
}

python:

k = int(input()) # 接收输入
lst = [int(i) for i in input().split()] # 接收输入数组
lst.insert(0,0) # 输入数组下标为0位置赋初值0
sum_ = [0] * (len(lst)+1) # 生成前缀和数组,为了防止索引越界,一般考虑稍微初始化大一点点
for i in range(1, len(lst)):
    sum_[i] = sum_[i-1] + lst[i] # 计算前缀和数组
res = -1
lowest = 0
head = 0
tail = 0
for end in range(len(lst)):
    if sum_[end] - sum_[lowest] > res:
        res = sum_[end] - sum_[lowest]
        head = lowest + 1
        tail = end
    if sum_[lowest] > sum_[end]:
        lowest = end

if res < 0:
    print("0" + " " + str(lst[1]) + " " + str(lst[k]))
else:
    print(str(res) + " " + str(head) + " " + str(tail))

最后附上AK截图:

python

C++:

写在后面:

        本题题眼在于“最大连续子数组和”,一般此类题目的解题思路都在于“差分与前缀和”这块,构建前缀和数组,通过“被减数一定,减数最小,差值(最大连续子数组和)最大”思路来进行解题,本题难度适中,核心部分可以当作模板记忆。

        以上就是本题的全部内容,主要在于差分与前缀和思想的应用,对此还不清楚的童鞋可以去详细学习,当然如果您有需要,我可以出一期对于差分与前缀和讲解的文章或视频,您可以评论区留言,如果对于以上内容您有什么意见或建议,欢迎评论区交流!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1431790.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Empowering Multimodal LLMs with Foresight Minds(Merlin)论文精读

paper&#xff1a;https://arxiv.org/pdf/2312.00589.pdfcode&#xff1a;https://ahnsun.github.io/merlin/ 0 Abstract 根据观测预测未知是人类的一个能力&#xff0c;对MLLM进行“future modeling”可以更好地激发其潜能&#xff1b;物体轨迹是一种连续帧间高度结构化的表…

计算机毕业设计 | vue+springboot 教务管理系统(附源码)

1&#xff0c;项目背景 随着我国高等教育的发展&#xff0c;数字化校园将成为一种必然的趋势&#xff0c;国内高校迫切需要提高教育工作的质量与效率&#xff0c;学生成绩管理工作是高校信息管理工作的重要组成部分&#xff0c;与国外高校不同&#xff0c;他们一般具有较大规模…

c#矩阵行列式计算//线程同步

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 实现矩阵行列式计算 {internal class Program{static void Main(string[] args){//定义矩阵Console.WriteLine("矩阵是&#xff1a;&quo…

ICV报告:最新排名!北京下降至第三位

2日&#xff0c;面向前沿科技领域的全球咨询机构ICV发布了《GFII-2023 报告》&#xff0c;其中在“2023年全球产业未来评估:未来20个城市”排名中显示&#xff0c;北京排名居世界第三。进入前十名的其他未来产业城市分别是旧金山-圣何塞、伦敦、慕尼黑、波士顿、纽约、东京横滨…

自然语言开发AI应用,利用云雀大模型打造自己的专属AI机器人

如今&#xff0c;大模型层出不穷&#xff0c;这为自然语言处理、计算机视觉、语音识别和其他领域的人工智能任务带来了重大的突破和进展。大模型通常指那些参数量庞大、层数深、拥有巨大的计算能力和数据训练集的模型。 但不能不承认的是&#xff0c;普通人使用大模型还是有一定…

前端工程化之:webpack2-2(内置插件)

目录 一、内置插件 1.DefinePlugin 2.BannerPlugin 3.ProvidePlugin 一、内置插件 所有的 webpack 内置插件都作为 webpack 的静态属性存在的&#xff0c;使用下面的方式即可创建一个插件对象&#xff1a; const webpack require("webpack")new webpack.插件…

【JVM调优及常见的JVM调优参数以及作用】

JVM调优及常见的JVM调优参数以及作用 JVM调优通常涉及以下几个方面&#xff1a;1. 堆内存调优&#xff1a;2. 垃圾回收调优&#xff1a;3. 线程调优&#xff1a;4. 类加载调优&#xff1a;JVM的优化配置可以通过设置JVM的启动参数来实现。以下是一些常用的JVM优化配置参数及其示…

steam搬砖项目赚钱吗?操作流程看这一篇就够了

很多人应该听说过steam&#xff0c;它是国外一款知名的游戏社交平台&#xff0c;也是目前世界上最大的游戏平台之一。而steam搬砖项目&#xff0c;关键就是靠信息差。我们要做的就是在steam以低价买入道具装备&#xff0c;然后上架到网易buff卖出&#xff0c;赚取差价。 什么人…

新年心愿清单怎么写 用这个软件列心愿清单更方便

新年的钟声在耳畔回荡&#xff0c;我站在窗前&#xff0c;看着外面熙熙攘攘的人群&#xff0c;心中充满了期待。新的一年&#xff0c;新的开始&#xff0c;我有很多心愿想要实现。于是&#xff0c;我决定写下一份心愿清单&#xff0c;给来年定下奋斗的方向。 但是&#xff0c;…

React实例之完善布局菜单(一)

今天我们来用所学的知识来做一个布局菜单的组件, 针对这个组件我之前写过一个教程 React之布局菜单-CSDN博客&#xff0c;那个呢比较基础&#xff0c;这节课算是对那个教程的一个扩展和补充。这个实例讲完&#xff0c;这个系列就算告一段落了。先看效果 这个教程要求对React知识…

uniapp使用u-popup组件弹窗出现页面还可滑动

*1、问题所在&#xff1a; 弹窗遮罩层出现了页面依旧可以上下滑动 2、要求: 为了用户更好交互体验&#xff0c;弹窗出现后应禁止页面往下滑动 3、实现思路&#xff1a; 在弹窗盒子外层添加个阻止触摸冒泡事件&#xff0c;使用touchmove.stop.prevent 4、代码如下&#xff…

Android简单支持项目符号的EditText

一、背景及样式效果 因项目需要&#xff0c;需要文本编辑时&#xff0c;支持项目符号&#xff08;无序列表&#xff09;尝试了BulletSpan&#xff0c;但不是很理想&#xff0c;并且考虑到影响老版本回显等因素&#xff0c;最终决定自定义一个BulletEditText。 先看效果&…

【深度学习】讲透深度学习第3篇:TensorFlow张量操作(代码文档已分享)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论深度学习相关知识。可以让大家熟练掌握机器学习基础,如分类、回归&#xff08;含代码&#xff09;&#xff0c;熟练掌握numpy,pandas,sklearn等框架使用。在算法上&#xff0c;掌握神经网络的数学原理&#xff0c;手动实…

vue + 动态加载图片

首先尝试我们经常用的require动态引入&#xff0c; 发现报错&#xff1a;require is not defind&#xff0c;这是因为 require 属于 Webpack 的方法&#xff0c;我现在的环境是 vue3.0 vite 1、 适用于处理少量链接的资源文件 import img from ./img.png; <img :src"…

Linux挂载本地ISO镜像源

1 创建挂载镜像的目录 mkdir /opt/rpm2 上传iso镜像到root目录 3 挂载镜像 mount -t iso9660 /root/CentOS-7-x86_64-DVD-2207-02.iso /opt/rpm/ 4 若是ftp文件夹挂载本地 mkdir /opt/iso 将ftp上software/caozuoxitong目录挂载到本地/opt/iso/ 目录 mount -t cifs //172.…

字符串左旋

题目&#xff1a;字符串左旋 内容&#xff1a;实现一个函数&#xff0c;可以左旋字符串中的K个字符。 例如&#xff1a; ABCDEF左旋一个字符可以得到BCDEFA ABCDEF左旋两个字符可以得到CDEFAB 方法一&#xff1a;移动字符 #include <stdio.h> #include <string.h>c…

深入分析AOP+自定义注解+RBAC实现操作权限管理设计思想

深入分析AOP自定义注解RBAC实现操作权限管理设计思想&#xff01;经过三个小节的部署&#xff0c;我们已经把这个思想走了一遍。下面内容是对于此次设计思想的一个详细介绍。帮助大家完善透彻的了解&#xff0c;到底自定义注解是如何实现的。以及&#xff0c;权限管理的核心思想…

程序报错无法打开源文件stdafx.h

在运行代码时&#xff0c;代码中头文件突然报错程序无法打开源文件stdafx.h include “stdafx.h”,编译器就说无法打开源文件&#xff0c;直接上干货解决方法是&#xff1a; 1.打开项目 ->项目属性&#xff08;最后一个&#xff09;-> C/C ->常规&#xff0c; 2在附…

音频几个相关概念及心理声学模型

系列文章目录 音频格式的介绍文章系列&#xff1a; 音频编解码格式介绍&#xff1a;音频几个相关概念及心理声学模型 https://blog.csdn.net/littlezls/article/details/135499627 音频编解码格式介绍&#xff1a;音频编码格式介绍 https://blog.csdn.net/littlezls/article/d…

nohost本地部署

1、安装node Node.js 官方网站下载&#xff1a;https://nodejs.org/en/download/ 2、安装whistle 安装命令为 npm install -g whistle 或 npm install -g cnpm --registryhttps://registry.npm.taobao.org 后&#xff0c;使用 cnpm install -g whistle 来安装 3、插件修改 官方…