【贪心算法】【中位贪心】LeetCode:100123.执行操作使频率分数最大

涉及知识点

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

题目

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。
你可以对数组执行 至多 k 次操作:
从数组中选择一个下标 i ,将 nums[i] 增加 或者 减少 1 。
最终数组的频率分数定义为数组中众数的 频率 。
请你返回你可以得到的 最大 频率分数。
众数指的是数组中出现次数最多的数。一个元素的频率指的是数组中这个元素的出现次数。
示例 1:
输入:nums = [1,2,6,4], k = 3
输出:3
解释:我们可以对数组执行以下操作:

  • 选择 i = 0 ,将 nums[0] 增加 1 。得到数组 [2,2,6,4] 。
  • 选择 i = 3 ,将 nums[3] 减少 1 ,得到数组 [2,2,6,3] 。
  • 选择 i = 3 ,将 nums[3] 减少 1 ,得到数组 [2,2,6,2] 。
    元素 2 是最终数组中的众数,出现了 3 次,所以频率分数为 3 。
    3 是所有可行方案里的最大频率分数。
    示例 2:
    输入:nums = [1,4,4,2,4], k = 0
    输出:3
    解释:我们无法执行任何操作,所以得到的频率分数是原数组中众数的频率 3 。
    参数范围
    1 <= nums.length <= 105
    1 <= nums[i] <= 109
    0 <= k <= 1014

贪心算法(中位数贪心)

假定众数是x,假定nums的长度为n,将nums按升序排序。

x一定是nums中的数

我们用反证发证明。

x < nums[0]所有数先降到nums[0],再由nums[0]降到x,不如直接降到nums[0]
x > nums[n-1]所有数先升到nums[n-1],再升到x,不如只升到nums[n-1]
x在nums[i]和nums[j]之间,nums中比x小的a个数,比x大的b个数。如果a>=b,x–,可以节省a-b个操作,直到x等于nums[i];否则x++,直到x等于nums[j]。

改变的数一定是一个子数组

假定改变的数是两个子数组[i1,i2]和[i3,i4]。如果x在[i1,i2]之间,则将i4替换成i2+1,直到两个子数组挨着一起合并。如果x在[i3,i4]之间,则i1替换i3-1,直到两个子数组挨着一起合并。

x只需要考虑中位数(中位数贪心算法)

来证明贪心算法的正确性。假定x是nums[i],x前面的数a个,x后面的数b个,i变成i-1操作次数变化:b-(a-1),如果表达式大于等于0,则没必要左移。b -a+1 >= 0,即a <=b+1。同理b <=a+1。即abs(a-b)<=1,则没必要左移和右移。
即:
如果n为偶数,中间任意一个。
如果n为奇数,中间的那个。

代码

核心代码

class Solution {
public:
	int maxFrequencyScore(vector<int>& nums, long long k) {
		m_c = nums.size();
		sort(nums.begin(), nums.end());
		vector<long long> vPreSum = { 0 };
		for (const auto& n : nums)
		{
			vPreSum.emplace_back(n+vPreSum.back());
		}	
		int iRet = 0;
		for (int left = 0, right = 0; left < m_c; left++)
		{
			while (right <= m_c)
			{
				const long long mid = left + (right - left) / 2;
				const long long llLessNeed = (mid - left) * nums[mid] - (vPreSum[mid] - vPreSum[left]);
				const long long llEqualMoreNeed = (vPreSum[right] - vPreSum[mid]) - nums[mid] * (right - mid);
				if (llLessNeed + llEqualMoreNeed <= k)
				{
					iRet = max(iRet, right - left);
					right++;
				}
				else
				{
					break;
				}
			}			
		}
		return iRet;
	}
	int m_c;
};

测试用例

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

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

int main()
{
	Solution slu;
	vector<int> nums;
	int k;
	{
		Solution slu;
		nums = { 1,4,4,2,4 }, k = 0;
		auto res = slu.maxFrequencyScore(nums, k);
		Assert(3, res);
	}
	{
		Solution slu;
		nums = { 16, 2, 6, 20, 2, 18, 16, 8, 15, 19, 22, 29, 24, 2, 26, 19 }, k = 40;
		auto res = slu.maxFrequencyScore(nums, k);
		Assert(11, res);
	}
	
	{
		Solution slu;
		nums = { 1, 2, 6, 4 }, k = 3;
		auto res = slu.maxFrequencyScore(nums, k);
		Assert(3, res);
	}

	
	//CConsole::Out(res);
}

错误解法:二分查找+双指针

错误原因: 随着left增加targge可能减少
class Solution {
public:
int maxFrequencyScore(vector& nums, long long k) {
m_c = nums.size();
sort(nums.begin(), nums.end());
vector vPreSum = { 0 };
for (const auto& n : nums)
{
vPreSum.emplace_back(n+vPreSum.back());
}
long long llLeftSum = 0;//nums[left,target)的和,nums升序
int iRet = 0;
for (int left = 0, target = 0; left < m_c; left++)
{
while ((target < m_c) && (nums[target]*(target-left)- llLeftSum <= k))
{
const int right = BF(vPreSum,nums, target, k - (nums[target] * (target - left) - llLeftSum));
iRet = max(iRet, right - left);
llLeftSum += nums[target];
target++;
}
llLeftSum -= nums[left];
}
return iRet;
}
int BF(const vector& vPreSum,const vector& nums, int index,long long canUse)
{
int left = index, right = vPreSum.size();
while (right - left > 1)
{
const int mid = left + (right- left)/2 ;
if ((vPreSum[mid] - vPreSum[index]- nums[index] * (mid - index)) <= canUse)
{
left = mid;
}
else
{
right = mid;
}
}
return left;
}
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
如无特殊说明,本算法用**C++**实现。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分享!!!(一)小编总结的base64、blob、图片文件二进制相互转换的方式以及源码

目录 第一章 了解 1.1 大概结构 1.2 准备阶段 1.2.1 了解canvas 1.2.2 了解imageData 1.2.3 了解imgUrl 1.2.4 了解base64 1.2.5 了解blob/文件二进制流 1.2.6 了解arraybuffer 1.2.7 文件、图片 第二章 掌握图中的相互转换 2.1 cavas 与 imageData的互相转换 2.1…

【Java】基于fabric8io库操作k8s集群实战(pod、deployment、service、volume)

目录 前言一、基于fabric8io操作pod1.1 yaml创建pod1.2 fabric8io创建pod案例 二、基于fabric8io创建Service&#xff08;含Deployment&#xff09;2.1 yaml创建Service和Deployment2.2 fabric8io创建service案例 三、基于fabric8io操作Volume3.1 yaml配置挂载存储卷3.2 基于fa…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)控件的部分公共属性和事件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;控件的部分公共属性和事件 一、操作环境 操作系统: Windows 10 专业版 IDE:DevEco Studio 3.1 SDK:HarmonyOS 3.1 二、公共属性 常用的公共属性有&#xff1a; 宽(with)、高(height)、…

Python Pandas 如何增加/插入一列数据(第5讲)

Python Pandas 如何增加/插入一列数据(第5讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹…

17.Oracle中instr()函数查询字符位置

1、instr()函数的格式 &#xff08;俗称&#xff1a;字符查找函数&#xff09; 格式一&#xff1a;instr( string1, string2 ) // instr(源字符串, 目标字符串) 格式二&#xff1a;instr( string1, string2 [, start_position [, nth_appearance ] ] ) // instr(源字符…

docker-harbor 私有仓库

docker三大组件&#xff1a;镜像、容器、仓库 仓库&#xff1a;保存镜像 私有&#xff0c;自定义用户的形式登陆仓库&#xff0c;拉取或者上传镜像&#xff08;内部管理的用户&#xff09; harbor是VMware公司开发的开源的企业级的docker registry项目 帮助用户快速的搭建一…

mov格式怎么转换成mp4

在现代数字化时代&#xff0c;视频成为人们交流、娱乐和记录生活的重要工具。然而&#xff0c;不同的视频格式可能会给我们的使用带来一些不便。其中&#xff0c;MOV格式是一种常见的视频格式&#xff0c;而MP4格式则更加广泛兼容于不同的设备和平台。 一般来说&#xff0c;MP…

22款奔驰GLE450升级小柏林音响 提升音质效果

开车是一种很枯燥的事&#xff0c;特别是在拥堵路段很容易让人变得很烦躁&#xff0c;在我们平常生活中汽车陪伴我们的时间是非常久的&#xff0c;在网上经常看到很多人把车比作老婆&#xff0c;为了让自己的“老婆”内在更加美&#xff0c;很多车友对音乐尤为热衷&#xff0c;…

CesiumLab地理信息基础数据处理平台 各类数据类型介绍、发布数据介绍

目录 0 引言1 CesiumLab2 数据处理模块2.1 输出格式&#xff1a;切片文件格式2.2 输入格式2.2.1 传统GIS数据2.2.2 人工模型2.2.3 BIM模型2.2.4 倾斜实景数据2.2.5 点云数据 3 发布服务功能3.1 拓展&#xff1a;其他平台发布服务功能 &#x1f64b;‍♂️ 作者&#xff1a;海码…

2022最新云存储网盘系统,文件分享系统与文件存储系统。

资源入口 2022 最新云存储网盘系统, 文件分享系统与文件存储系统。 测试环境&#xff1a;Apache MySQL5.6 PHP7.0 安装 PHP 扩展 exif、fileinfo 从 PHP 禁用函数中 删除 shell_exec、proc_open、putenv 这三个 PHP 函数 PS&#xff1a;整体还不错的系统&#xff0c;注意的…

nodejs配置express服务器,运行自动打开浏览器

查看专栏目录 Network 灰鸽宝典专栏主要关注服务器的配置&#xff0c;前后端开发环境的配置&#xff0c;编辑器的配置&#xff0c;网络服务的配置&#xff0c;网络命令的应用与配置&#xff0c;windows常见问题的解决等。 文章目录 设置方法&#xff1a;1&#xff0c;安装nodej…

跟随山海鲸开发者,深入了解智慧城市解决方案的核心技术

随着科技的飞速发展&#xff0c;数字孪生技术逐渐成为智慧城市建设的重要手段。作为山海鲸开发者&#xff0c;我们深知数字孪生技术在智慧城市中的应用价值&#xff0c;因此致力于开发出高效、便捷的数字孪生智慧城市解决方案。因此本文将带大家了解山海鲸智慧城市解决方案。 …

Django 构建动态前端页面详解

概要 Django 是一个强大的 Python Web 框架&#xff0c;广泛用于后端开发。然而&#xff0c;它也支持直接使用 HTML, CSS, 和 JavaScript 来构建动态的前端界面。本文将详细介绍如何在 Django 项目中使用这些技术&#xff0c;包括设置静态文件、编写 HTML 模板以及集成 JavaSc…

YOLOv5改进 | SPPF | 将RT-DETR模型AIFI模块和Conv模块结合替换SPPF(全网独家改进)

一、本文介绍 本文给大家带来是用最新的RT-DETR模型中的AIFI模块来替换YOLOv5中的SPPF。RT-DETR号称是打败YOLO的检测模型&#xff0c;其作为一种基于Transformer的检测方法&#xff0c;相较于传统的基于卷积的检测方法&#xff0c;提供了更为全面和深入的特征理解&#xff0c…

Linux性能优化常做的一些事情

Linux性能优化是一个广泛的主题&#xff0c;涉及多个方面。以下是一些常见的Linux性能优化建议&#xff1a; 硬件和系统配置&#xff1a; 使用SSD替代HDD。确保系统有足够的RAM。使用多核CPU。配置合适的网络硬件和带宽。 磁盘I/O性能&#xff1a; 使用RAID来提高I/O性能。使用…

人工智能在金融与商业领域的智能化变革

导言 随着人工智能技术的不断发展&#xff0c;金融和商业领域正迎来一场智能化的变革。随着人工智能的不断发展&#xff0c;其在金融和商业领域的应用正成为业界瞩目的焦点。本文将深入探讨人工智能在金融和商业应用中的关键技术、应用场景以及对未来的影响。 1. 关键技术与算…

08-工厂方法

意图 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类 类图 适用性 在下列情况可以使用工厂方法模式&#xff1a; 当一个类不知道它所必须创建的对象的类的时候。当一个类希望由它的子类来指定它所创建的对象的时候。当类将创建对象的职责委托给多个帮助子…

Axure的元件库的使用以及详细案例

目录 元件库的使用 元件介绍 元件的基本使用 矩形、按钮、标题的使用​编辑 图片的使用 图片以及热区的使用 表单元件的使用 表格元件的使用 登录界面 个人简介界面 元件库的使用 元件介绍 Axure提供了一套丰富的元件库&#xff0c;用于快速创建原型中常见的UI界面元素…

虚拟机性能监控、故障处理工具

虚拟机性能监控、故障处理工具 二、基础故障处理工具4.2.1 jps&#xff1a;虚拟机进程状况工具4.2.2 jstat:虚拟机统计信息监视工具4.2.3 jinfo:Java配置信息工具4.2.4 jmap:java内存映像工具4.2.5 jhat:虚拟机堆转储快照分析工具4.2.6 jstack&#xff1a;Java堆栈跟踪工具4.2.…

neo4j安装报错:neo4j.bat : 无法将“neo4j.bat”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。

neo4j安装报错&#xff1a; neo4j.bat : 无法将“neo4j.bat”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确 保路径正确&#xff0c;然后再试一次。 解决办法&#xff1a; 在环境变量中的&#xff0c;用户…