当前位置: 首页 > news >正文

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

相关文章:

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

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

速盾:高防服务器租用需要注意什么事项

在当今互联网时代&#xff0c;网络安全问题日益严峻。各种网络攻击手段层出不穷&#xff0c;给企业和个人的网站带来了巨大的安全威胁。为了保障网站的安全稳定运行&#xff0c;高防服务器成为了许多人的选择。而在租用高防服务器时&#xff0c;需要注意以下几个事项。 一、选择…...

【数据库】MySQL内置函数

本篇分享一些在MySQL中常见的一些内置函数&#xff0c;如日期函数&#xff0c;字符串函数和数学函数&#xff0c;以方便于操作数据库中的数据。 1.日期函数 我们先整体观察一下这些函数再讲解案例 日期函数使用起来都非常就简单 获得年月日&#xff1a; select current_dat…...

Promise查漏及回调地狱结构优化

目录 前言一、执行器函数的执行顺序二、如何在then()中抛出错误三、期约的"非重入"特性四、串行化期约五、应对回调地狱结语 前言 依据《JavaScript高级程序设计》对Promise期约相关进行查缺补漏. 一、执行器函数的执行顺序 执行器函数虽作为期约的参数, 却是期约的…...

SpringCloud-05 Resilience4J 服务降级和熔断

服务雪崩&#xff1a;指在多个服务之间存在依赖关系时&#xff0c;当一个服务发生故障或不可用时&#xff0c;导致其他服务也无法正常工作的情况。这种现象通常是因为服务之间的依赖关系过于紧密&#xff0c;当一个服务发生故障时&#xff0c;其他服务无法正确处理该服务的请求…...

哈希表、算法

哈希表 hash&#xff1a; 在编程和数据结构中&#xff0c;"hash" 通常指的是哈希函数&#xff0c;它是一种算法&#xff0c;用于将数据&#xff08;通常是字符 串&#xff09;映射到一个固定大小的数字&#xff08;哈希值&#xff09;。哈希函数在哈希表中尤为重要…...

变更AWS EC2 实例配置或实例类型

在本文中&#xff0c;九河云将带您了解如何更改由 Amazon Elastic Block Store (EBS) 支持的 Amazon Elastic Compute Cloud (EC2) 实例的类型。更改实例类型可以优化成本和性能&#xff0c;使其更符合您的应用程序需求。 准备工作 在开始之前&#xff0c;请确保您已完成以下…...

【前端】ref引用的作用

首先&#xff0c;我们要明确一点&#xff0c;使用vue的好处是&#xff1a; 想要减少开发者直接操作dom元素。使用组件模版&#xff0c;实现代码的服用。 ref的属性的实现是为了取代原生js中使用id、class等标识来获取dom元素。 helloworld组件 <template><div clas…...

运用Java实现倒计时功能

这个功能其实是比较好实现的&#xff0c;一般来说java中实现倒计时有两种方法&#xff1a; 1、使用 scheduledexecutorservice创建一个可重复执行的任务&#xff0c;直到时间到&#xff1a; ScheduledExecutorService 是 Java 中一种用于安排延迟或定期任务的工具。我们可以使…...

Vue 第三方调用若依系统实现系统单点登录

应用场景 甲方现有平台系统拟集成我方新开发系统&#xff0c;实现单点登录功能&#xff0c;即用户登录主平台后&#xff0c;无需重复登录即可无缝访问新系统&#xff0c;提升用户体验与操作效率。 解决方案 实现代码 前端 Step:1 新建ssoLogin.vue页面 <template><d…...

IP纯净度对跨境电商有哪些影响

在全球化贸易的浪潮中&#xff0c;跨境电商凭借其打破地理界限的能力&#xff0c;成为推动国际贸易的重要力量。然而&#xff0c;跨境电商的运营并非没有挑战&#xff0c;其中IP纯净度是影响其成功的关键因素之一。本文将探讨IP纯净度对跨境电商运营的多方面影响&#xff0c;并…...

docker-01 创建一个自己的镜像并运行容器

docker-01 创建一个自己的镜像并运行容器 前言 我们都知道使用Docker的镜像可以快速创建和部署应用&#xff0c;大大的节约了部署的时间。并且Docker 的镜像提供了除内核外完整的运行时环境&#xff0c;确保代码的环境一致性&#xff0c;从而不会在出现这段代码在我机器上没问…...

国产视频转换HDMI1.4转单/双MIPI DSI/CSI LT6911C芯片方案,带音频输出,QFN64封装 Lontium

LT6911C:HDMI 1.4 TO MIPI DSI/CSI 芯片简介&#xff1a; LT6911C是一款高性能的HDMI1.4转换器MIPI DSI/CSI芯片用于VR/智能手机/显示应用。对于MIPI DSI/CSI输出&#xff0c;LT6911C功能可配置单端口或双端口MIPIDSI/CSI 1高速时钟通道和1~4个高速数据通道最大1.5Gb/s/lane&am…...

亚马逊、沃尔玛、敦煌网、Target塔吉特、Temu环境搭建测评技术!

海外跨境电商各大主要平台正不断力推半托管模式&#xff0c;不断对商家开出众多吸引和扶持政策。全托管是指电商平台全面负责店铺的运营&#xff0c;包括仓储、配送、售后等&#xff0c;而商家主要负责提供货品。半托管模式则基本由商家自主经营&#xff0c;平台只负责仓配物流…...

yjs05——matplotlib画其他图像

不管是折线图还是散点图&#xff0c;饼状图&#xff0c;柱状图等&#xff0c;其流程都是 1.创建幕布 ❤2.画图画坐标补充信息 3.保存图像 4.展示图像 不同就是在画图时候的代码不太相同 折线&#xff1a;plt.plot(x,y) 散点&#xff1a;plt.scatter() 柱状图&#xff1a;plt.hi…...

【C#】添加临时环境变量

在C#中&#xff0c;可以通过System.Environment类来添加临时环境变量。临时环境变量只在当前进程中有效&#xff0c;进程结束后变量即失效&#xff0c;不会写入系统的Path中。 using System;class Program {static void Main(){// 设置临时环境变量Environment.SetEnvironment…...

物联网之ESP32与微信小程序实现指示灯、转向灯

MENU ESP32微信小程序 ESP32 代码 #include <WiFi.h> #include <WebServer.h> #include <ArduinoJson.h>const char* ssid "jifu"; const char* pass "2022xinchan!#"; const int dateTime 500; const int ledPin4 4; const int le…...

ICPC网络赛 以及ACM训练总结

一、训练反思 关于我自己暑假期间训练的反思&#xff0c;我承认无论是因为什么原因&#xff0c;我自己浪费我整整一个暑假的时间&#xff0c;暑假期间正是我们集训的关键时期&#xff0c;这期间没有任何的事情来打扰我们学习&#xff0c;而我却熬夜&#xff0c;白天训练懈怠&a…...

优化深度学习模型训练过程:提升PASCAL VOC 2012数据集上Deeplabv3+模型训练效率的策略

创作不易&#xff0c;您的打赏、关注、点赞、收藏和转发是我坚持下去的动力&#xff01; 优化说明&#xff1a; 避免重复下载和解压数据集&#xff1a;将downloadTrue改为downloadFalse&#xff0c;防止每次运行代码都重新下载和解压数据集&#xff0c;从而节省时间。 使用pin…...

【乐吾乐大屏可视化组态编辑器】使用手册

1 总览 开始设计&#xff1a;大屏可视化设计器 - 乐吾乐Le5le 1.1 画布 画布即绘画区域&#xff0c;将图形拖拽到画布进行编辑&#xff0c;绘制大屏。 1.2 菜单栏 顶部菜单导航&#xff0c;一级菜单可设置Logo、公司名称、文件编辑、常用编辑、查看、帮助&#xff0c;设置大…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...