HOT 100(七)栈、堆、贪心算法

一、栈

1、每日温度

使用单调递减栈来解决。主要思路是遍历temperatures数组,利用栈来存储还没有找到比当前温度高的天数的索引。当遇到比栈顶索引所对应温度更高的温度时,就可以确定当前这一天的温度比之前那一天高。索引的差值就是等待的天数

求一个元素右边或者左边第一个比它大/小的元素可以用到单调栈。

class Solution:def dailyTemperatures(self, temperatures: List[int]) -> List[int]:n=len(temperatures)stk=[]ans=[0]*nfor i in range(n):tmp=temperatures[i]while stk and tmp>temperatures[stk[-1]]:pre_pos=stk.pop()ans[pre_pos]=i-pre_posstk.append(i)return ans

2、柱状图中最大的矩形 

代码随想录题解icon-default.png?t=O83Ahttp://【单调栈,又一次经典来袭! LeetCode:84.柱状图中最大的矩形】https://www.bilibili.com/video/BV1Ns4y1o7uB?vd_source=b93b9c2a7846dd3e8bd33feb227c4ac5通过使用单调递增栈来解决这个问题。当遇到一个比栈顶元素低的高度时,说明以栈顶高度为矩形的柱子已经结束,它无法再延伸更大的宽度,因此可以计算这个柱子形成的最大矩形面积。

单调栈的核心是维护一个递增序列。具体思路是:

  • 如果当前柱子的高度大于栈顶柱子的高度,则将当前柱子的索引压入栈。
  • 如果当前柱子的高度小于栈顶柱子的高度,说明栈顶柱子的矩形已经找到了右边界,因此我们可以计算以该柱子为高度的最大矩形面积。

我们要找到直方图中能够形成的最大矩形面积。这个问题的关键在于如何快速计算每个柱子作为矩形高度时,能够向左和向右延伸的宽度。为了高效地解决这个问题,我们使用单调栈,它帮助我们在每次遇到更矮的柱子时回溯并计算以之前柱子为高度的最大矩形面积。

class Solution:def largestRectangleArea(self, heights: List[int]) -> int:heights=[0]+heights+[0]res=0stk=[0]for i in range(1,len(heights)):if heights[i]>heights[stk[-1]]:stk.append(i)elif heights[i]==heights[stk[-1]]:stk.pop()stk.append(i)else:while stk and heights[stk[-1]]>heights[i]:mid_height_pos=stk.pop()mid_height=heights[mid_height_pos]left_edge=stk[-1]right_edge=ires=max(res,(right_edge-left_edge-1)*mid_height)stk.append(i)return res

二、堆

1、数组中的第k个最大元素

①快速排序思想

题目要求是找出数组中第k个最大元素,因此可以通过快速排序不断缩小寻找区间来定位第k个最大的元素。(题目要求找的是数组中第k个最大的元素,因此排序后的元素是从大到小逆序排列的,左右指针移动的判断条件不要写错)。

与快速排序不同的是,不需要完全排序整个数组,只需要处理包含第 k 大元素的那一部分。因此每交换过一轮元素以后,都要判定第k大的元素在左边部分(每次的起始left到j)还是右部分(j+1到right)。

class Solution:def findKthLargest(self, nums: List[int], k: int) -> int:def quicksort(nums,left,right,k):if left>=right:return nums[left]mid=(left+right)//2pivot=nums[mid]i,j=left-1,right+1while i<j:while True:i+=1if nums[i]<=pivot:breakwhile True:j-=1if nums[j]>=pivot:breakif i<j:nums[i],nums[j]=nums[j],nums[i]if j-left+1>=k:return quicksort(nums,left,j,k)else:return quicksort(nums,j+1,right,k-(j-left+1))return quicksort(nums,0,len(nums)-1,k)

②堆

维护一个大小为 k 的小根堆。每次当堆的大小超过 k 时,弹出堆顶元素,因为堆顶元素是堆中最小的,这样可以确保堆中始终保留了 k 个最大的元素。最后堆顶的元素就是第 k 大的元素。

class Solution:def findKthLargest(self, nums: List[int], k: int) -> int:min_heap=[]for num in nums:heapq.heappush(min_heap,num)if len(min_heap)>k:heapq.heappop(min_heap)return min_heap[0]

2、前K个高频元素

1-数组中的第k个最大元素中堆处理方法处理思想相同。

首先调用Counter方法获取每个元素与其出现次数,再构建一个小根堆来存放(出现次数,数组元素)堆顶是出现次数最少的数组元素。每当堆的大小超过k,就将堆顶元素弹出,这样最后留在堆中的一定是出现次数最多的那K个数组元素。

class Solution:def topKFrequent(self, nums: List[int], k: int) -> List[int]:counter=Counter(nums)heap=[]for num,count in counter.items():heapq.heappush(heap,(count,num))if len(heap)>k:heapq.heappop(heap)list_k=[heap[i][1] for i in range(k)]return list_k

3、数据流的中位数

整体思路:

  • 使用一个最大堆(通过存负值模拟)来保存数据流中较小的一半元素。
  • 使用一个最小堆来保存数据流中较大的一半元素。
  • 保持最大堆的大小总是等于最小堆的大小或者比最小堆大一个元素,这样中位数可以轻松获取:
    • 如果两个堆的大小相同,则中位数是两个堆顶元素的平均值。
    • 如果最大堆比最小堆大一个元素,则中位数是最大堆的顶部元素。

详细步骤:

  • 添加元素:

    • 首先添加到最大堆: 元素以其负值形式添加到最大堆中。
    • 调整元素到最小堆: 如果添加后最大堆的堆顶元素(负值的最小值,即绝对值最大)大于最小堆的堆顶元素,则将最大堆的顶部元素弹出(转换为正值),并加入到最小堆中。这样做是为了保证最小堆中的所有元素始终大于最大堆中的所有元素。
    • 平衡两个堆的大小:
      • 如果最大堆的大小比最小堆大超过1个元素,从最大堆中移除顶部元素(最大值),转换为正值后加入到最小堆中。
      • 如果最小堆比最大堆大(虽然按照逻辑不应该发生,但为了保证健壮性也可以检查和处理),则将最小堆的顶部元素弹出并加入到最大堆中。
  • 计算中位数:

    • 如果最大堆的元素数量比最小堆多,中位数是最大堆的堆顶元素(转换为正值)。
    • 如果最大堆和最小堆的大小相同,中位数是两个堆顶元素值的平均数。
class MedianFinder:def __init__(self):self.min_heap=[]self.max_heap=[]def addNum(self, num: int) -> None:heapq.heappush(self.max_heap,-num)if self.max_heap and self.min_heap and -self.max_heap[0]>self.min_heap[0]:heapq.heappush(self.min_heap,-heapq.heappop(self.max_heap))if len(self.max_heap)>len(self.min_heap)+1:heapq.heappush(self.min_heap,-heapq.heappop(self.max_heap))if len(self.min_heap)>len(self.max_heap):heapq.heappush(self.max_heap,-heapq.heappop(self.min_heap))def findMedian(self) -> float:if len(self.max_heap)==len(self.min_heap):return (-self.max_heap[0]+self.min_heap[0])/2.0else:return -self.max_heap[0]# Your MedianFinder object will be instantiated and called as such:
# obj = MedianFinder()
# obj.addNum(num)
# param_2 = obj.findMedian()

 三、贪心算法

1、买卖股票的最佳时机

①题意限制

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。

并且卖出股票的价格需要比买入股票的价格高

②解题思路

维护两个变量max_profit和min_price,分别记录当前最大利润当前最小价格

最大利润一定是由较高的价格减去它之前最低的价格获得的。

遍历每个prices数组中的每个price,根据price更新max_profit和min_price:

  • max_profit=max(max_profit,price-min_price)
  • min_price=min(price,min_price)
class Solution:def maxProfit(self, prices: List[int]) -> int:max_profit=0min_price=float('inf')for price in prices:max_profit=max(price-min_price,max_profit)min_price=min(min_price,price)return max_profit

2、跳跃游戏

①题意解读

给你一个非负整数数组 nums ,你最初位于数组的第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。

题目忽略的部分:

在当前跳跃游戏和下一个跳跃游戏II中,在 nums[i] 处,你可以跳转到任意 nums[i + j] 处,其中0 <= j <= nums[i] 。

举个例子,在【2,3,1,4,2】中,从起点nums[0]=2开始跳跃,当前最远可达索引位置是nums[0]+0=2,nums[0]可以选择跳跃到3,也可以选择跳到当前最远1。

②思路解析

能否到达最后一个下标,取决于从数组第一个下标开始跳跃能到达的最远位置

因此我们可以维护一个记录当前可达最远位置的变量right,遍历数组中每一个元素,若当前遍历到的数组索引 i 大于right,就说明当前位置 i 是跳跃到达不了的。

若right的值大于等于数组中最后一个下标索引,则说明能够到达终点。

class Solution:def canJump(self, nums: List[int]) -> bool:n=len(nums)right=0for i in range(n):if i<=right:right=max(right,nums[i]+i)if right>=n-1:return Truereturn False

3、跳跃游戏II

①题意说明

给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]

每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

  • 0 <= j <= nums[i] 
  • i + j < n

返回到达 nums[n - 1] 的最小跳跃次数。

②思路解析

维护两个变量right和end,分别记录能够到达的最远位置目前所在跳跃区间的终点

right和上一个跳跃游戏表示的意思是一样的。

end是目前所在跳跃区间的终点。举个例子【231,5,6】紫色标识的部分便是从起点nums[0]开始的跳跃区间,end此时指向索引2。遍历到end的时候,就不得不做一次跳跃了,而跳跃的根据取决于right,确保每次跳跃都能到达更远的位置

利用【231,5,6】辅助说明:i=0时,right=2;i=1时,right=4;i=end=2时,right=3(在这个跳跃区间内更新了right的情况)。到达end=2时需要从起点执行一次跳跃操作,可以跳到索引位置1(nums[1]=3),也可以跳到索引位置2(nums[2]=1),而根据right的信息我们可以知道这一跳跳到索引位置1的收益最大,因此当前这一跳跳到索引位置1,跳跃区间发生变化,区间终点end的值更新为当前right。

class Solution:def jump(self, nums: List[int]) -> int:if len(nums)<=1:return 0n=len(nums)jump=0right=0end=0for i in range(n):right=max(right,i+nums[i])if i==end:jump+=1end=rightif end>=n-1:breakreturn jump

4、划分字母区间

首先,数组last来记录每个字母最后一次出现的位置。

维护两个变量start和end,分别记录当前区间开始的位置和当前区间结束的位置。

遍历字符串,比较当前字母的最后一次出现位置与当前子区间终点end的大小,若前者更大则更新end。若当前索引与end相等,表示该子区间遍历结束,另起起点划分区间。

class Solution:def partitionLabels(self, s: str) -> List[int]:last=[0]*26for i,ch in enumerate(s):pos=ord(ch)-ord('a')last[pos]=istart=0end=0partition=[]for i,ch in enumerate(s):pos=ord(ch)-ord('a')end=max(end,last[pos])if i==end:partition.append(end-start+1)start=end+1return partition

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

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

相关文章

使用c#制作一个小型桌面程序

封装dll 首先使用visual stdio 创建Dll新项目,然后属性管理器导入自己的工程属性表&#xff08;如果没有可以参考visual stdio 如何配置opencv等其他环境&#xff09; 创建完成后 系统会自动生成一些文件&#xff0c;其中 pch.cpp 先不要修改&#xff0c;pch.h中先导入自己需…

Unet改进31:添加Star_Block(2024最新改进方法)|紧凑的网络结构和高效的运算

本文内容:在不同位置添加Star_Block 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 最近的研究引起了人们对网络设计中尚未开发的“星型操作”(元素智能乘法)潜力的关注。虽然有很多直观的解释,但其应用背后的基本原理在很大程度上仍未被探索。我们的研…

旅游网站设计与实现:SpringBoot技术手册

第三章 系统分析 开发一个系统首先要对系统进行分析&#xff0c;是开发者针对系统实际客户对软件应用的一个调查访问和研究&#xff0c;弄清用户对软件需求的具体要求&#xff0c;同时开发者还要对系统开发的经济和可技术上是否可行进行分析&#xff0c;并确定系统开发的成本和…

OZON电子产品大幅增长,OZON跨境PS5销量激增

Top1 存储卡 Карта памяти Canvas Select Plus 128 ГБ 商品id&#xff1a;1548303593 月销量&#xff1a;2131 欢迎各位卖家朋友点击这里&#xff1a; &#x1f449; D。DDqbt。COm/74rD 免费体验 随着智能手机和平板电脑的普及&#xff0c;用户对于存储空…

C++笔记---继承(上)

1. 继承的简单介绍 1.1 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许我们在保持原有类特性的基础上进行扩展&#xff0c;增加方法(成员函数)和属性(成员变量)&#xff0c;这样产生新的类&#xff0c;称派生类。 继承呈…

使用LDAP登录GitLab

使用LDAP登录GitLab gitlab.rb 配置如下 gitlab_rails[ldap_enabled] true #gitlab_rails[prevent_ldap_sign_in] false###! **remember to close this block with EOS below** gitlab_rails[ldap_servers] YAML.load <<-EOSmain:label: LDAPhost: 172.16.10.180port:…

python环境安装

一、下载开发IDE https://www.jetbrains.com/pycharm/download/?sectionwindows 下载:conda Download Now | Anaconda 重新打开PyCharm Community Edition 2024.2.1 新建项目&#xff1a;pythonProject1 编写python 文件时没有提示&#xff1a;错误:未选择 Python 解释器。请…

云轴科技ZStack 获鲲鹏应用创新大赛2024上海赛区决赛一等奖

9月13日&#xff0c;鲲鹏应用创新大赛2024上海赛区决赛成功举办。经评委专家从方案创新性、技术领先性、商业前景以及社会价值四个维度严格评审&#xff0c;云轴科技ZStack参赛作品《ZStack鲲鹏原生开发方案》荣获上海赛区企业赛——原生开发赛道&#xff08;互联网&#xff09…

线程 - 线程的由来、进程和线程的关系、进程创建_等待_退出详解

文章目录 一、线程概念1. 线程的出现2. linux 对线程的设计3. 线程二、进程和线程1. 进程和线程的关系2. 进程的调度3. 轻量级进程三、pthread库1. pthread 库的作用2. 手动链接 pthread库四、创建线程1. pthread_create()2. 函数的使用3. 线程和函数五、线程等待1. 新线程的运…

ROADM(可重构光分插复用器)-介绍

1. 引用 https://zhuanlan.zhihu.com/p/163369296 https://zhuanlan.zhihu.com/p/521352954 https://zhuanlan.zhihu.com/p/91103069 https://zhuanlan.zhihu.com/p/50610236 术语&#xff1a; 英文缩写描述灰光模块彩光模块CWDM&#xff1a;Coarse Wave-Length Division …

WireShark分析localhost包

文章目录 需要npcap。 java 需要配置Npcap&#xff0c;如果没有需要卸载重新安装 Npcap 是专为 Windows 开发的一款网络抓包 SDK&#xff0c;该 SDK 提供了被应用程序调用的库文件和系统驱动程序。通过 Npcap&#xff0c;我们可以得到原始&#xff08;raw&#xff09;网络数据&…

Java手写RPC框架-01-开篇

项目背景 随着业务不断升级&#xff0c;系统规模不断扩大&#xff0c; 单体架构会产生越来越多的问题&#xff0c;需要引入微服务将原先架构解耦为一个个模块。每个服务模块放在不同的服务器上&#xff0c;能够保证系统在高并发环境下的正常运转。 各个服务模块之间如何相互调…

OpenHarmony(鸿蒙南向开发)——轻量系统STM32F407芯片移植案例

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——轻量和小型系统三方库移植指南…

【getshell】phpmyadmin后台getshell(4.8.5)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【getshell】phpmyadmin后台getshell&#xff08;4.8.5&#xff09; 一、进入sql命令输入界面二、上传代码三、getshell 一、进入…

Kubernetes (k8s)v1.27.1版本安装步骤

这 一、k8s 安装步骤1.1 安装docker及containerd容器1.2、设置每台服务器的参数1.3、安装kubelet、kubeadm、kubectl1.4、修改 kubelet 的 cgroup 和 docker 的 cgroup-driver 保持一致1.5、使用containerd 默认容器的配置1.6、使用kubeadm进行初始化1.7、初始化成功1.8、集群部…

海外云手机有哪些推荐?

随着云手机的发展&#xff0c;越来越多的企业和个人开始使用云手机来满足他们的海外业务需求。用户可以通过云手机实现方便、快捷的海外访问&#xff0c;一般用来进行tiktok运营、亚马逊电商运营、海外社媒运营等操作。海外云手机平台有很多&#xff0c;以下是一些比较好的云手…

✨机器学习笔记(四)—— 逻辑回归、决策边界、过拟合、正则化

Course1-Week3: https://github.com/kaieye/2022-Machine-Learning-Specialization/tree/main/Supervised%20Machine%20Learning%20Regression%20and%20Classification/week3机器学习笔记&#xff08;四&#xff09; 1️⃣逻辑回归&#xff08;logistic regression&#xff09;…

Java的衍生生态有哪些?恐怖如斯的JAVA

Java的衍生生态极其丰富&#xff0c;涵盖了多个层面和领域。以下是Java衍生生态的一些主要方面&#xff1a; 1. 开源工具 开发工具&#xff1a;如Eclipse&#xff0c;这是一款非常优秀的Java IDE工具&#xff0c;支持Java以及其他语言的代码编写。Spring官方还基于Eclipse开发…

Excel单元格操作:读写单元格数据、格式设置与条件格式详解

目录 一、Excel单元格的基本操作 1.1 单元格的选取与编辑 案例一&#xff1a;基本数据录入 1.2 单元格的读取与写入 案例二&#xff1a;使用公式计算销售额 二、单元格格式设置 2.1 字体与颜色设置 案例三&#xff1a;设置标题格式 2.2 数字格式设置 案例四&#xff…

树形弹窗选择框/vue2/Element/弹框选择

前言 此类选择器根据vueelementUI实现&#xff0c;使用vue3的可以根据此案例稍作改动即可实现&#xff0c;主要功能有弹出选择、搜索过滤、搜索结果高亮等&#xff0c;此选择器只支持单选&#xff0c;如需多选可在此基础进行改造。 效果图 代码实现 使用时&#xff0c;props-…