C++前缀和算法的应用:摘水果 原理源码测试用例

news2024/9/23 5:21:07

本文涉及的基础知识点

C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频

题目

在一个无限的 x 坐标轴上,有许多水果分布在其中某些位置。给你一个二维整数数组 fruits ,其中 fruits[i] = [positioni, amounti] 表示共有 amounti 个水果放置在 positioni 上。fruits 已经按 positioni 升序排列 ,每个 positioni 互不相同 。
另给你两个整数 startPos 和 k 。最初,你位于 startPos 。从任何位置,你可以选择 向左或者向右 走。在 x 轴上每移动 一个单位 ,就记作 一步 。你总共可以走 最多 k 步。你每达到一个位置,都会摘掉全部的水果,水果也将从该位置消失(不会再生)。
返回你可以摘到水果的 最大总数 。
示例 1:
输入:fruits = [[2,8],[6,3],[8,6]], startPos = 5, k = 4
输出:9
解释:
最佳路线为:

  • 向右移动到位置 6 ,摘到 3 个水果
  • 向右移动到位置 8 ,摘到 6 个水果
    移动 3 步,共摘到 3 + 6 = 9 个水果
    示例 2:
    输入:fruits = [[0,9],[4,1],[5,7],[6,2],[7,4],[10,9]], startPos = 5, k = 4
    输出:14
    解释:
    可以移动最多 k = 4 步,所以无法到达位置 0 和位置 10 。
    最佳路线为:
  • 在初始位置 5 ,摘到 7 个水果
  • 向左移动到位置 4 ,摘到 1 个水果
  • 向右移动到位置 6 ,摘到 2 个水果
  • 向右移动到位置 7 ,摘到 4 个水果
    移动 1 + 3 = 4 步,共摘到 7 + 1 + 2 + 4 = 14 个水果
    示例 3:
    输入:fruits = [[0,3],[6,4],[8,5]], startPos = 3, k = 2
    输出:0
    解释:
    最多可以移动 k = 2 步,无法到达任一有水果的地方

参数范围
1 <= fruits.length <= 105
fruits[i].length == 2
0 <= startPos, positioni <= 2 * 105
对于任意 i > 0 ,positioni-1 < positioni 均成立(下标从 0 开始计数)
1 <= amounti <= 104
0 <= k <= 2 * 105

分析

原理

只需要左移(右移)一次。假定左移了两次,分别移动了x1,x2,假定x1<x2。则不移动x1,水果不会少。
分四种情况:
一,左移到底。
二,先左移,后右移。
三,右移到底。
四,先右移,再左移。
一是四的特殊请,三是二的特殊情况。

步骤

一,先获取前缀和。
二,枚举左移。右移为0或负数,忽视,因为劣于左移到底。k为0是,此条不符合。
三,枚举右移。

注意

坐标无限,但前缀和有限[0,iMaxPos]。

左移后的坐标可能小于0
左移后的坐标** 可能大于iMax**
右移后的坐标可能大于iMax
k为0时要左特殊处理。

变量解释

vNum各坐标水果数量
vSum/vSum[i]记录[0,i)草莓的总数量
iMoveLeft左移距离
iMoveRight右移距离
left移动到的最左坐标
right移动到最右坐标

代码

核心代码

class Solution {
public:
int maxTotalFruits(vector<vector>& fruits, int startPos, int k) {
const int iMaxPos = fruits.back()[0];
vector vNum(iMaxPos + 1);
for (const auto&v : fruits)
{
vNum[v[0]] = v[1];
}
vector vSum = { 0 };//vSum[i]记录[0,i)草莓的总数量
for (int i =0; i <= iMaxPos; i++)
{
vSum.emplace_back(vSum.back() + vNum[i]);
}

	int iRet = 0;
	for (int iMoveLeft = 0; iMoveLeft <= k / 2; iMoveLeft++)
	{//先左后右
		const int iMoveRight = k - iMoveLeft * 2;
		if (iMoveRight < 0)
		{
			continue;
		}
		const int left = max(0, startPos - iMoveLeft);
		if (left > iMaxPos)
		{
			continue;
		}
		const int right = min(iMaxPos, startPos + iMoveRight);
		//可收集[left,right+1)的草莓
		const int cur = vSum[right + 1] - vSum[left];
		iRet = max(iRet, cur);
	}

	for (int iMoveRight = 0; iMoveRight <= k / 2; iMoveRight++)
	{//先左后右
		const int iMoveLeft = k - iMoveRight * 2;
		if (iMoveLeft < 0)
		{
			continue;
		}
		const int left = max(0, startPos - iMoveLeft);
		if (left > iMaxPos)
		{
			continue;
		}
		const int right = min(iMaxPos, startPos + iMoveRight);
		//可收集[left,right+1)的草莓
		const int cur = vSum[right + 1] - vSum[left];
		iRet = max(iRet, cur);
	}
	return iRet;
}

};

测试用例

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
assert(v1[i] == v2[i]);
}
}

template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}

int main()
{
Solution slu;
vector<vector> fruits;
int startPos = 0;
int k = 0;
int res;

fruits = {{2, 8}, {6, 3}, {8, 6}};
startPos =5 ;
k =4 ;
res = slu.maxTotalFruits(fruits, startPos, k);
Assert(9, res);

fruits = {{0, 9}, {4, 1}, {5, 7}, {6, 2}, {7, 4}, {10, 9}};
startPos = 5;
k = 4;
res = slu.maxTotalFruits(fruits, startPos, k);
Assert(14, res);

fruits = { {0,10000} };
startPos = 20000;
k = 20000;
res = slu.maxTotalFruits(fruits, startPos, k);
Assert(10000, res);

fruits = { {20000,10000} };
startPos = 20000;
k = 0;
res = slu.maxTotalFruits(fruits, startPos, k);
Assert(10000, res);


//CConsole::Out(res);

}

2023年3月旧代码

class Solution {
public:
int maxTotalFruits(vector<vector>& fruits, int startPos, int k) {
m_c = fruits.size();
int iMaxLeftIndex = std::lower_bound(fruits.begin(), fruits.end(),startPos, [](const vector& v, int i)
{
return v[0] < i;
}) - fruits.begin() - 1;
std::map<int, int> mLeftMoveNum;
for (int i = iMaxLeftIndex ; (i >= 0) && (startPos - fruits[i][0] <= k); i–)
{
const int iLeftMove = startPos - fruits[i][0];
mLeftMoveNum[iLeftMove] = fruits[i][1] + (mLeftMoveNum.empty() ? 0 : mLeftMoveNum.rbegin()->second);
}
int iMinRightIndex = iMaxLeftIndex + 1;
int iRet = 0;
if ((iMinRightIndex < m_c) && (fruits[iMinRightIndex][0] == startPos))
{
iRet += fruits[iMinRightIndex][1];
iMinRightIndex++;
}
std::map<int, int> mRightMoveNum;
for (int i = iMinRightIndex; (i < m_c) && (fruits[i][0] - startPos <= k); i++)
{
const int iRightMove = fruits[i][0] - startPos;
mRightMoveNum[iRightMove] = fruits[i][1] + (mRightMoveNum.empty() ? 0 : mRightMoveNum.rbegin()->second);
}

	 int iMaxExcludeStart = 0;
	 for (int left = 0; left <= k / 2; left++)
	 {
		 const int right = k - left * 2;
		 int iCur = 0;
		 {
			 auto itLeft = mLeftMoveNum.upper_bound(left);
			 if (mLeftMoveNum.begin() != itLeft)
			 {
				 iCur += (--itLeft)->second;
			 }
		 }
		 {
			 auto itRight = mRightMoveNum.upper_bound(right);
			 if (mRightMoveNum.begin() != itRight)
			 {
				 iCur += (--itRight)->second;
			 }
		 }
		 iMaxExcludeStart = max(iMaxExcludeStart, iCur);
	 }
	 for (int right = 0; right <= k / 2; right++)
	 {
		 const int left = k - right * 2;
		 int iCur = 0;
		 {
			 auto itLeft = mLeftMoveNum.upper_bound(left);
			 if (mLeftMoveNum.begin() != itLeft)
			 {
				 iCur += (--itLeft)->second;
			 }
		 }
		 {
			 auto itRight = mRightMoveNum.upper_bound(right);
			 if (mRightMoveNum.begin() != itRight)
			 {
				 iCur += (--itRight)->second;
			 }
		 }
		 iMaxExcludeStart = max(iMaxExcludeStart, iCur);
	 }
	 iRet += iMaxExcludeStart;
	 return iRet;
 }
 int m_c;

};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《闻缺陷则喜算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

| 鄙人想对大家说的话
|
|-|
|闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。|
| 墨家名称的来源:有所得以墨记之。 |
|如果程序是一条龙,那算法就是他的是睛|

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境:

VS2022 C++17

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

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

相关文章

读高性能MySQL(第4版)笔记20_Performance Schema和其他

1. 线程 1.1. MySQL服务端是多线程软件。它的每个组件都使用线程 1.2. 每个线程至少有两个唯一标识符 1.2.1. 操作系统线程ID 1.2.2. MySQL内部线程ID 2. 对象类型 2.1. OBJECT_TYPE列 2.2. EVENT 2.3. FUNCTION 2.4. PROCEDURE 2.5. TABLE 2.6. TRIGGER 3. Perfor…

RunnerGo UI自动化使用流程

可以直接进入官网下载开源版或点击右上角体验企业版体验 RunnerGo UI自动化平台 RunnerGo提供从API管理到API性能再到可视化的API自动化、UI自动化测试功能模块&#xff0c;覆盖了整个产品测试周期。 RunnerGo UI自动化基于Selenium浏览器自动化方案构建&#xff0c;内嵌高度…

Java并发线程池原理源码深入分析与调优实战

一&#xff0c;开篇&#xff1a; java中提供了多线程设计的Api&#xff0c;为什么还要用线程池呢&#xff1f; 下来看两个例子&#xff1a; 1. 使用多线程跑十万次 2. 使用线程池跑十万次 使用多线程跑十万次 package com.laoyang.ThreadPool.公开课;import java.util.ArrayL…

让图片完美适应:掌握 CSS 的object-fit与object-position

在CSS中&#xff0c;我们可以使用 background-size 和background-position属性为背景图像设置大小和位置。而 object-fit 和 object-position 属性则允许我们对嵌入的图像&#xff08;以及其他替代元素&#xff0c;如视频&#xff09;做类似的操作。在本文中&#xff0c;我们将…

Photoshop(PS)安装教程(图文教程超详细)

目录 一.简介 二.安装步骤 软件&#xff1a;PS版本&#xff1a;2023语言&#xff1a;简体中文大小&#xff1a;3.20G系统要求&#xff1a;Win10&#xff08;1903&#xff09;及以上版本&#xff0c;64位操作系统硬件要求&#xff1a;CPU2.0GHz 内存8G(或更高&#xff0c;不支…

蓝桥算法赛(铺地板)

问题描述 小蓝家要装修了&#xff0c;小蓝爸爸买来了很多块&#xff08;你可以理解为数量无限&#xff09; 23 规格的地砖&#xff0c;小蓝家的地板是 nm 规格的&#xff0c;小蓝想问你&#xff0c;能否用这些 23 的地砖铺满地板。 铺满地板&#xff1a;对于地板的每个区域&…

Apipost现已支持连接数据库!

Apipost提供了数据库连接功能&#xff0c;在接口调试时可以使用数据库获取入参或进行断言校验。目前的Apipost支持&#xff1a;Mysql、SQL Sever、Oracle、Clickhouse、达梦数据库、PostgreSQL、Redis、MongoDB 8种数据库的连接操作 新建数据库连接&#xff1a; 在「项目设置…

Openssl数据安全传输平台010:jasoncpp 0.10.7的编译 - Windows-vs2022 / Ubuntu/ Centos8 -含测试代码

文章目录 0. 代码仓库1 安装1.1 windows 下的安装1.2 Linux 下的安装1.2.1 相关环境配置问题1.2.2 准备安装1.2.2.1 安装scons1.2.2.2 安装jsoncppUbuntu系统下Centos8系统下 2 编译 c 测试文件&#xff1a; json-test.cpp2.1 配置库文件2.2 配置VS2.3 Winsows系统下cpp文件测试…

java集成海康预览抓图出现内存一直上涨问题

求助&#xff1a;在java 中集成海康sdk后批量抓图出现内存上涨问题&#xff0c;不论是预览后不关闭继续预览&#xff0c;还是预览后关闭预览&#xff0c;然后重新预览都没有解决这个问题&#xff08;抓图正常&#xff09;&#xff0c;尝试使用第三方解码器ffmpeg来进行解码&…

聊聊今年的秋招

大家好啊&#xff0c;我是董董灿。 又是一年秋招季&#xff0c;身边不少小伙伴反馈&#xff0c;今年的秋招很卷&#xff0c;很多人在刚到9月份的时候就开始投简历到处面试了。 不少同学甚至坐火车去外地参加笔试和面试&#xff0c;来回折腾的同时&#xff0c;也让周围的同学都…

[ACTF2020 新生赛]Include 1

题目环境&#xff1a;超链接&#xff0c;点进去看看你能找到flag吗&#xff1f;除了这些网页什么都没有&#xff0c;但是不当紧&#xff0c;因为我们有一双善于发现的眼睛&#x1f440;F12瞅瞅无&#xff0c;并无其他等等URL看了吗&#xff1f;发现存在一个参数file&#xff0c…

18 行为型模式-观察者模式

行为模式共有11种&#xff1a; 观察者模式 模板方法模式 策略模式 职责链模式 状态模式 命令模式 中介者模式 迭代器模式 访问者模式 备忘录模式 解释器模式 以上 11 种行为型模式&#xff0c;除了模板方法模式和解释器模式是类行为型模式&#xff0c;其他的全部属于对象行为型…

ShardingSphere-JDBC分库分表快速入门实战

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;啥技术都喜欢捣鼓捣鼓&#xff0c;喜欢分享技术、经验、生活。 &#x1f60e;人生感悟&#xff1a;尝尽人生百味&#xff0c;方知世间冷暖。 &#x1f4d6;所属专栏&#xff1a;My…

xhadmin多应用Saas框架如何安装情侣飞行棋?

xhadmin是什么&#xff1f; xhadmin 是一套基于最新技术的研发的多应用 Saas 框架&#xff0c;支持在线升级和安装模块及模板&#xff0c;拥有良好的开发框架、成熟稳定的技术解决方案、提供丰富的扩展功能。为开发者赋能&#xff0c;助力企业发展、国家富强&#xff0c;致力于…

设置爱奇艺代理教程

设置爱奇艺代理教程 活泼与直观&#xff1a;设置爱奇艺代理&#xff0c;让你的网络更加自由&#xff01; 轻松口语化&#xff1a;首先&#xff0c;打开爱奇艺APP&#xff0c;进入设置页面。 设置->网络->代理设置 活泼与直观&#xff1a;在代理设置页面&#xff0c;我…

Vue3富文本编辑器组件封装

近期后台项目有使用富文本编辑器的需求&#xff0c;本文记录一下封装细节 1.富文本组件库参考 TinyMCE - 富文本编辑器里的 Word &#xff0c;功能想不到的丰富tiptap - 多人在线实时协同编辑CKEditor 5 - 开源免费可商用&#xff0c;行内编辑Quill - 易扩展、轻量级二开、代码…

sql第二次上机作业

1查找借阅了ISBN为“4-6045-1023-4”的借书证号&#xff0c;读者姓名&#xff0c;专业名和借书时间 use tsgl go select Reader.Lno,Rname,Spec,Lend.Bordate FROM Reader,Lend WHERE Reader.LnoLend.Lno AND ISBN 4-6045-1023-42查找借阅了《数据库原理》一书的借阅信息&…

Kubernetes(K8S)快速搭建typecho个人博客

Kubernetes&#xff08;K8S&#xff09;快速搭建typecho个人博客 1、准备工作 K8S集群环境&#xff0c;搭建教程参考腾讯云Lighthouse组建跨地域Kubernetes集群 K8S集群面板&#xff0c;搭建教程参考Kubernetes集群管理面板的安装及使用 - 青阳のblog-一个计算机爱好者的个人…

[moeCTF 2023] pwn

总体上来说并不难&#xff0c;不过对于新生来说还是相当好的。循序渐进&#xff0c;很适合PWN入门到放弃。 baby_calculator 就是要算对100个10以内加法&#xff08;幼儿园的题&#xff09;练习pwntools和python from pwn import * from hashlib import md5 import string …

android button 按钮,设置左/右小图标,与文字居中距离

参考博客地址 功能点 支持自定义图标与文字的距离支持小图标宽高自定义支持左右自定义小图标 maven { url https://jitpack.io } implementation com.github.CMzhizhe:AppCompatButtonProject:1.0.0<com.gxx.buttonlibrary.DrawableCenterButtonandroid:layout_marginTop&…