LeetCode 2386.找出数组的第 K 大和:逆向思维(小根堆)

【LetMeFly】2386.找出数组的第 K 大和:逆向思维(小根堆)

力扣题目链接:https://leetcode.cn/problems/find-the-k-sum-of-an-array/

给你一个整数数组 nums 和一个 整数 k 。你可以选择数组的任一 子序列 并且对其全部元素求和。

数组的 第 k 大和 定义为:可以获得的第 k最大 子序列和(子序列和允许出现重复)

返回数组的 第 k 大和

子序列是一个可以由其他数组删除某些或不删除元素排生而来的数组,且派生过程不改变剩余元素的顺序。

注意:空子序列的和视作 0

 

示例 1:

输入:nums = [2,4,-2], k = 5
输出:2
解释:所有可能获得的子序列和列出如下,按递减顺序排列:
- 6、4、4、2、2、0、0、-2
数组的第 5 大和是 2 。

示例 2:

输入:nums = [1,-2,3,4,-10,12], k = 16
输出:10
解释:数组的第 16 大和是 10 。

 

提示:

  • n == nums.length
  • 1 <= n <= 105
  • -109 <= nums[i] <= 109
  • 1 <= k <= min(2000, 2n)

方法一:逆向思维(小根堆)

  • 最大和怎么找?数组中正数之和即是。
  • 第二大和怎么找?最大和 的基础上减去一个很小的正数或加上一个很小的负数。
  • 第三大和怎么找?最大和/第二大和 的基础上减去一个很小的正数或加上一个很小的负数。

不难发现除了初始的最大和,负数和其绝对值的正数结果是等价的。因此我们可以:

遍历一遍数组,若为正整数则累加,为负则变为正(取绝对值)。这样最大和就找到了。

又因为求的是“序列”和而不是“子数组”和,也就是说元素可以不连续。因此我们可以:

对处理后的全是非负数的数组从小到大排个序。

接下来的操作就是不断地从“最大和”的基础上,减去非负数组中的一些数了。每次减去地尽可能小,一共减去 k k k次。也就是说:

我们只需要找到这个递增非负数组的前 k k k个最小和即可。

假设这个处理后的数组是[1, 2, 3],那么怎么生成它的 2 3 2^3 23个子序列呢?

  • 初始序列为空:[]
  • 在空序列的基础上添加1得到[1]
  • [1]的基础上添加2得到[1, 2];或将最后的1替换成2得到[2]
  • [2]基础上添加3得到[2, 3];或直接替换最后的2[3]
  • [1, 2]的基础上添加3得到[1, 2, 3];或直接替换最后的2[1, 3]

这不是很适合最小堆吗?

堆中存放(当前和, 添加到了第几个元素),每次选当前和最小的出堆,即为下一个“最小序列和”。

  • 时间复杂度 O ( n log ⁡ n + k log ⁡ k ) O(n\log n + k\log k) O(nlogn+klogk),其中 n = l e n ( n u m s ) n=len(nums) n=len(nums)
  • 空间复杂度 O ( k ) O(k) O(k)

AC代码

C++
/*
1 2 3112  2123   23  3
*/typedef long long ll;
typedef pair<ll, int> pli;
class Solution {
public:ll kSum(vector<int>& nums, int k) {ll sum = 0;for (int& t : nums) {if (t >= 0) {sum += t;}else {t = -t;}}sort(nums.begin(), nums.end());priority_queue<pli, vector<pli>, greater<pli>> pq;pq.push({nums[0], 0});ll toDesc = 0;for (int i = 1; i < k; i++) {auto [nowSum, th] = pq.top();toDesc = nowSum;pq.pop();if (th == nums.size() - 1) {continue;}pq.push({nowSum + nums[th + 1], th + 1});pq.push({nowSum - nums[th] + nums[th + 1], th + 1});}return sum - toDesc;}
};
Python
# from typing import List
# import heapqclass Solution:def kSum(self, nums: List[int], k: int) -> int:sum_ = 0for i in range(len(nums)):if nums[i] >= 0:sum_ += nums[i]else:nums[i] = -nums[i]nums.sort()pq = [(nums[0], 0)]toDesc = 0for _ in range(1, k):nowSum, th = heapq.heappop(pq)toDesc = nowSumif th == len(nums) - 1:continueheapq.heappush(pq, (nowSum + nums[th + 1], th + 1))heapq.heappush(pq, (nowSum - nums[th] + nums[th + 1], th + 1))return sum_ - toDesc

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/136588803

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

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

相关文章

Android性能优化 - ANR的分析和解决

一、ANR概念 1.定义 “Application Not Responding”的缩写&#xff0c;即“应用程序无响应”。如果你应用程序在UI线程被阻塞太长时间&#xff0c;就会出现ANR。 2.类型 ① KeyDispatchTimeout&#xff08;常见&#xff09; input事件在5S内没有处理完成发生了ANR。logca…

Python和Google Colab进行卫星图像二维小波变化和机器学习

2D 小波分解是图像处理中的一种流行技术,使用不同的滤波器将图像分解为不同的频率分量(“近似”和“细节”系数)。该技术对于各种图像处理任务特别有用,例如压缩、去噪、特征提取和边缘检测。 在本文中,我们将演示如何在 Google Colab 中使用 Python 下载高分辨率样本卫星…

划拳(c++题解)

题目描述 小王和小明在吃饭的时候玩起了划拳游戏。 游戏规则是&#xff0c;每一轮两个人同时说出一个数&#xff08;只能是 中的一个&#xff09;&#xff0c;若两人说出的数一样&#xff0c;则两人均不计分&#xff0c;否则说出数字更大的人获得两人说出的数差值这么多的分…

解决火狐浏览器访问地址受限制问题(This address is restricted)

问题如下图&#xff1a; This address is restrictedThis address uses a network port which is normally used for purposes other than Web browsing. Firefox has canceled the request for your protection. 此地址受到限制 此地址使用通常用于 Web 浏览以外的目的的网…

【Pytorch】进阶学习:基于矩阵乘法torch.matmul()实现全连接层

【Pytorch】进阶学习&#xff1a;基于矩阵乘法torch.matmul()实现全连接层 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448…

深入了解304缓存原理:提升网站性能与加载速度

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

微信小程序开发系列(十八)·wxml语法·声明和绑定数据

目录 1. 双大括号写法用法一&#xff1a;展示内容 步骤一&#xff1a;创建一个data对象 步骤二&#xff1a;双大括号写法的使用 步骤三&#xff1a;拓展 2. 双大括号写法用法二&#xff1a;绑定属性值 步骤一&#xff1a;给对象赋一个属性值 步骤二&#xff1a;双大括…

激光打标机红光与激光不重合:原因及解决方案

激光打标机红光和激光不在一个位置的问题可能由多种原因导致。以下是一些可能的原因和解决方法&#xff1a; 1. 激光器光路调整不当&#xff1a;激光器光路调整不当会导致激光束偏移&#xff0c;从而使红光与激光不重合。解决方法是重新调整激光器的光路&#xff0c;确保激光束…

【文档智能】再谈基于Transformer架构的文档智能理解方法论和相关数据集

前言 文档的智能解析与理解成为为知识管理的关键环节。特别是在处理扫描文档时&#xff0c;如何有效地理解和提取表单信息&#xff0c;成为了一个具有挑战性的问题。扫描文档的复杂性&#xff0c;包括其结构的多样性、非文本元素的融合以及手写与印刷内容的混合&#xff0c;都…

Java本地接口(Java Native Interface,JNI)讲解

Java本地接口&#xff08;Java Native Interface&#xff0c;JNI&#xff09;是一个编程框架&#xff0c;允许Java代码与其他语言写的代码&#xff0c;特别是C和C&#xff0c;进行交互。这个功能使得Java程序能够调用系统级别的库和那些已经用这些语言实现的库。JNI主要用于两个…

C# winform 重启电脑

一、重启电脑指令 windows7系统的启动文件夹为“开始菜单”——“所有程序”里面就有“启动”文件夹&#xff0c;其位置是 “C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup” 如果没有&#xff0c;则需要将其中的"administrator…

【正点原子STM32探索者】CubeMX+Keil开发环境搭建

文章目录 一、简单开箱二、资料下载三、环境搭建3.1 安装Keil MDK3.2 激活Keil MDK3.3 安装STM32CubeMX3.4 安装STM32F4系列MCU的Keil支持包 四、GPIO点灯4.1 查阅开发板原理图4.2 创建STM32CubeMX项目4.3 配置系统时钟和引脚功能4.4 生成Keil项目4.5 打开Keil项目4.6 编译Keil…

Java学习笔记NO.18

T1.理工超市 &#xff08;1&#xff09;题目描述 编写一个程序&#xff0c;设计理工超市功能菜单并完成注册和登录功能的实现。显示完菜单后&#xff0c;提示用户输入菜单项序号。当用户输入<注册>和<登录>菜单序号时模拟完成注册和登录功能&#xff0c;最后提示…

使用Python快速提取PPT中的文本内容

直接提取PPT中的文本内容可以方便我们进行进一步处理或分析&#xff0c;也可以直接用于其他文档的编撰。通过使用Python程序&#xff0c;我们可以快速批量提取PPT中的文本内容&#xff0c;从而实现高效的信息收集或对其中的数据进行分析。本文将介绍如何使用Python程序提取Powe…

模拟实现C语言库函数(strlen,strcpy,strcat)

模拟实现strlen 三种方法 size_t my_strlen(char* s)//计数器 {size_t count 0;while (*(s))count;return count; }size_t my_strlen(char* s)//递归 {if (*s \0)return 0;elsereturn my_strlen(s) 1; }size_t my_strlen(char* s)//指针-指针 {char* tmp s;while (*(s));…

设计模式-代理模式使用教程

在 Java 中实现代理模式通常包括两种方式&#xff1a;静态代理和动态代理。静态代理是在编译时就已经确定代理类和真实对象的关系&#xff0c;而动态代理则是在运行时动态生成代理类。下面&#xff0c;我会分别解释如何在项目中实践这两种代理模式。 静态代理 定义接口&#…

HTML5基础2

drag 可以把拖放事件拆分成4个步骤 设置元素为可拖放。为了使元素可拖动&#xff0c;把 draggable 属性设置为 true 。 <img draggable"true"> 拖动什么。ondragstart 和 setData() const dragestart (ev)>{ev.dataTransfer.setData(play,ev.target.id)} …

Pytorch线性回归实现(原理)

设置梯度 直接在tensor中设置 requires_gradTrue&#xff0c;每次操作这个数的时候&#xff0c;就会保存每一步的数据。也就是保存了梯度相关的数据。 import torch x torch.ones(2, 2, requires_gradTrue) #初始化参数x并设置requires_gradTrue用来追踪其计算历史 print(x…

软考笔记--系统架构评估

系统架构评估是在对架构分析、评估的基础上&#xff0c;对架构策略的选取进行决策。它利用数据或逻辑分析技术&#xff0c;针对系统的一致性&#xff0c;正确性&#xff0c;质量属性&#xff0c;规划结果等不同方面&#xff0c;提供描述性&#xff0c;预测性和指令性的分析结果…

C#协变与逆变:解锁高级编程技巧,轻松提升代码性能

文章目录 协变协变接口的实现逆变里氏替换原则 协变 协变概念令人费解&#xff0c;多半是取名或者翻译的锅&#xff0c;其实是很容易理解的。 比如大街上有一只狗&#xff0c;我说大家快看&#xff0c;这有一只动物&#xff01;这个非常自然&#xff0c;虽然动物并不严格等于…