【LeetCode与《代码随想录》】贪心算法篇:做题笔记与总结-JavaScript版

代码随想录

贪心的本质是选择每一阶段的局部最优,从而达到全局最优。

文章目录

    • 455. 分发饼干
    • 376. 摆动序列
    • 53. 最大子数组和
    • 122. 买卖股票的最佳时机 II
    • 55. 跳跃游戏
    • 45. 跳跃游戏 II
    • 1005. K 次取反后最大化的数组和
    • 134. 加油站
    • 135. 分发糖果(困难)
    • 860. 柠檬水找零
    • 406.根据身高重建队列
    • 452. 用最少数量的箭引爆气球
    • 435. 无重叠区间
    • 763.划分字母区间
    • 56. 合并区间
    • 738.单调递增的数字
    • 968.监控二叉树

455. 分发饼干

https://leetcode.cn/problems/assign-cookies/description/

大饼干可以满足大孩子也可以满足小孩子,在这里显然是满足大孩子最划算。因此饼干从大到小,如果饼干可以满足该孩子,ans++,否则,尝试是否可以满足小孩子。

注意跳出循环的条件,当i<0||j<0

var findContentChildren = function (g, s) {g.sort((a, b) => (a - b))s.sort((a, b) => (a - b))let ans = 0;for (let i = g.length - 1, j = s.length - 1; i >= 0, j >= 0;) {// g[i] 人 s[j]饼干if (s[j] >= g[i]) {ans++;i--, j--;} else {i--;}if (i < 0 || j < 0) break;}return ans;
};

376. 摆动序列

376. 摆动序列

想要得到最长的摆动数组,需要保留一个上/下坡的头和尾,如:

1257521

这里1,2,5,7都是上坡,但1,7的上坡比其他的好,因为7可以与后面组成更好的下坡——若是1,7,则后面想要下坡<7即可;若1,2,后面想要下坡则需要<2,条件比<7要小。反之亦然。

但是,选择1,7还是1,2本质都是上坡,且长度都为2。因此,我们可以把问题简化为数组有多少个上下坡的变化

上面的样例就是一上一下,不管怎么选摆动数组都是3.

我们用一个flag来记录前面是上坡还是下坡:前面是上坡且当前数组是下坡则ans++,反之亦然。

注意要判断平坡,且从第一个上/下坡之后开始(flag值就记录第一个上/下坡)。

var wiggleMaxLength = function(nums) {// flag表示是上行1还是下行0,-1表示一直平坡let ans=1,flag=-1;// 要找到第一次上行或下行let index=1;for(;index<nums.length;index++){if(nums[index]===nums[index-1]) continue;if(nums[index]>nums[index-1]) {flag=1;ans=2;break;}else{flag=0;ans=2;break;}}for(let i=index+1;i<nums.length;i++){// 上行if(nums[i]>nums[i-1]){if(!flag){ans++;flag=1;}}// 下行else if(nums[i]<nums[i-1]){if(flag){ans++;flag=0;}}}return ans;
};

53. 最大子数组和

53. 最大子数组和

分为两种情况:数组全负和数组非全负。

数组全负则选元素最大的那一个。
数组非全负则一直累加并存最大值,若出现cnt<0则令cnt=0,相当于前面部分都不选。

var maxSubArray = function (nums) {let ans = -10001;// 数组全为负数let flag = 0;nums.forEach(item => {if (item > 0) {flag = 1; return;}})if (!flag) {nums.forEach(item => {ans = Math.max(ans, item);})return ans;}let cnt = 0;// 贪心:如果一块连续部分是负数则舍去nums.forEach(item => {cnt += item;if (item >= 0) ans = Math.max(ans, cnt);else {if (cnt < 0) cnt = 0;}})return ans;
};

122. 买卖股票的最佳时机 II

122. 买卖股票的最佳时机 II

有prices数组:1,2,3,5,8

最低买入最高卖出肯定是答案,即8-1=7

注意,8-1=(2-1)+(3-2)+(5-3)+(8-5)。即前缀差中正值的和。

若数组为:2,0,1,4,前缀差为-2,1,3,说明要在0时买入,在4时卖出。

var maxProfit = function (prices) {// 前缀差 差值为正表示利润let ans = 0;for (let i = 1; i < prices.length; i++) {let temp = prices[i] - prices[i - 1]if (temp > 0) ans += temp;}return ans;
};

55. 跳跃游戏

55. 跳跃游戏

var canJump = function (nums) {// cover表示可以覆盖的范围,也就是下标let cover = 0;if (nums.length === 1) return true;for (let i = 0; i <= cover; i++) {cover = Math.max(cover, i + nums[i]);if (cover >= nums.length - 1) return true;}return false;
};

45. 跳跃游戏 II

45. 跳跃游戏 II

var jump = function (nums) {if (nums.length === 1) return 0;// ans步数,next本次可以到达的最大范围,max下一次可以到达的最大范围let ans = 0, next = 0, max = 0;for (let i = 0; i < nums.length; i++) {max = Math.max(max, i + nums[i]);// 当前已经达到本次可以达到的最大范围,到下一范围需要一步if (i === next) {ans++;next = max;if (max >= nums.length - 1) break;}}return ans;
};

1005. K 次取反后最大化的数组和

1005. K 次取反后最大化的数组和

var largestSumAfterKNegations = function (nums, k) {// k是偶数可以相当于不变let f = [], z = []nums.forEach(item => {if (item < 0) f.push(item);else z.push(item);})f.sort((a, b) => (a - b));z.sort((a, b) => (a - b));if (k >= f.length) {k -= f.length;f = f.map(item => {return -item;})z.push(...f);f = []} else {for (let i = 0; i < k; i++) {let temp = -f[i];z.push(temp);}f = f.slice(k);k = 0;}f.sort((a, b) => (a - b));z.sort((a, b) => (a - b));if (k && k % 2) {// k是奇数z[0] = -z[0];}let ans = 0;if (f.length) {ans += f.reduce((pre, val) => {return pre + val;})}if (z.length) {ans += z.reduce((pre, val) => {return pre + val;})}return ans;
};

134. 加油站

134. 加油站

n是1e5,暴力双层循环会超出时间限制。

获得数组arr=gas-cost,arr[i]表示离开i地点剩余的油。
遍历arr,计算区间和,但凡出现区间和<0,说明不能从这个区间的开头开始走(没油了),可能从此区间的下一个地方j开始走。于是从j开始计算区间和。维护这个j值:是可能的答案。

计算arr的和,若arr的和>0,说明存在一个地方开始走能顺时针跑完。由题知,这个答案是唯一的。因此就是上面维护的j值。

若arr<0,说明不存在答案。

var canCompleteCircuit = function (gas, cost) {// 遍历 找gas-cost的区间和<0 答案就是此区间的下一个let curSum = 0, allSum = 0, ans = 0;for (let i = 0; i < gas.length; i++) {let temp = gas[i] - cost[i];curSum += tempallSum += temp// 此区间和为负,不能从这个区间和的头开始if (curSum < 0) {curSum = 0;ans = i + 1;//从此区间的下一个下标开始尝试}}if (allSum < 0) return -1;return ans;
};

135. 分发糖果(困难)

135. 分发糖果

思路:这个讲得好

省流:从左到右遍历一次,从右到左遍历一次。

var candy = function (ratings) {let arr = new Array(ratings.length).fill(1)// 右边大于左边,即从左到右:右边大的糖果+1for (let i = 1; i < ratings.length; i++) {if (ratings[i] > ratings[i - 1]) {arr[i] = arr[i - 1] + 1;}}// 左边大于右边,即从右到左(右边最小)for (let i = ratings.length - 1; i >= 0; i--) {if (ratings[i - 1] > ratings[i]) {arr[i - 1] = Math.max(arr[i - 1], arr[i] + 1);}}let ans = arr.reduce((pre, val) => {return pre + val;})return ans;
};

860. 柠檬水找零

860. 柠檬水找零

forEach中的return是跳出循环而不是函数的return

var lemonadeChange = function (bills) {let cnt5 = 0, cnt10 = 0;let flag = true;bills.forEach(item => {console.log(item, cnt5, cnt10)if (item === 5) {cnt5++;} else if (item === 10) {cnt10++;if (cnt5 > 0) cnt5--;else {flag = false; return;//这里的return是跳出bills的循环 而不是函数的return}} else if (item === 20) {if (cnt5 > 0 && cnt10 > 0) {cnt5--; cnt10--;} else if (cnt5 >= 3) {cnt5 -= 3;} else {flag = false; return;}}})return flag;
};

406.根据身高重建队列

406.根据身高重建队列

想要队列queue中的内容满足:第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人,只需要构造

  • 前面的人都比第i个人高
  • 前面的人的个数是k[i]

因此,需要先对身高从大到小排列,若身高相同,则对k从小到大排列。(如,[5,0]一定在[5,1]前)

[[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]为例,排序后为:

[ [ 7, 0 ], [ 7, 1 ], [ 6, 1 ], [ 5, 0 ], [ 5, 2 ], [ 4, 4 ] ]

开始构造:

  1. [ 7, 0 ],前面有0个比它高的,因此他在第0个,这里的0即people[0][0]
  2. [ 7, 1 ],前面有1个比它高的,因此他在第1个,这里的0即people[1][1]
  3. [ 6, 1 ],前面有1个比它高的,因此他在第1个,这里的1即people[2][1]
  4. [ 5, 0 ],前面有0个比它高的,因此他在第0个,这里的0即people[3][1]

以此类推。

每次的queue为:

i为 0 , [ [ 7, 0 ] ]
i为 1 , [ [ 7, 0 ], [ 7, 1 ] ]
i为 2 , [ [ 7, 0 ], [ 6, 1 ], [ 7, 1 ] ]
i为 3 , [ [ 5, 0 ], [ 7, 0 ], [ 6, 1 ], [ 7, 1 ] ]
i为 4 , [ [ 5, 0 ], [ 7, 0 ], [ 5, 2 ], [ 6, 1 ], [ 7, 1 ] ]
i为 5 , [ [ 5, 0 ], [ 7, 0 ], [ 5, 2 ], [ 6, 1 ], [ 4, 4 ], [ 7, 1 ] ]

总体代码:

var reconstructQueue = function (people) {// 先看h,h从大到小,若h一样看k,从小到大people.sort((a, b) => {if (a[0] != b[0]) return b[0] - a[0];else return a[1] - b[1];})let queue = []for (let i = 0; i < people.length; i++) {queue.splice(people[i][1], 0, people[i]);}return queue;
};

452. 用最少数量的箭引爆气球

452. 用最少数量的箭引爆气球

var findMinArrowShots = function (points) {let ans = 1;// 都从小到大排points.sort((a, b) => {if (a[0] != b[0]) return a[0] - b[0];else return a[1] - b[1];})let min = points[0][0], max = points[0][1];for (let i = 1; i < points.length; i++) {let a = points[i][0], b = points[i][1];if (a >= min && b <= max) {min = amax = b} else {if (a >= min && a <= max) min = aelse if (b >= min && b <= max) max = belse {ans++;min = a, max = b;}}}return ans;
};

435. 无重叠区间

435. 无重叠区间

var eraseOverlapIntervals = function (intervals) {intervals.sort((a, b) => {if (a[0] != b[0]) return a[0] - b[0]else return a[1] - b[1]})let ans = 0let min = intervals[0][0], max = intervals[0][1]for (let i = 1; i < intervals.length; i++) {let a = intervals[i][0], b = intervals[i][1]if (a >= max) {min = a, max = b} else {ans++;if (a >= min && b <= max) {min = a, max = b;}}}return ans;
};

763.划分字母区间

763.划分字母区间

var partitionLabels = function (s) {let start = new Map(), end = new Map()for (let i = 0; i < s.length; i++) {// 注意:只有一个的情况end.set(s[i], i);if (!start.has(s[i])) start.set(s[i], i);}let arr = [...start.keys()], nums = []arr.forEach(item => {nums.push([start.get(item), end.get(item)])})// 从小到大nums.sort((a, b) => {if (a[0] != b[0]) return a[0] - b[0]else return a[1] - b[1]})let min = nums[0][0], max = nums[0][1], ans = []for (let i = 1; i < nums.length; i++) {let a = nums[i][0], b = nums[i][1]if (a > max) {ans.push(max - min + 1)min = a, max = b} else max = Math.max(max, b);}ans.push(max - min + 1)return ans;
};

56. 合并区间

56. 合并区间

var merge = function (intervals) {// 从小到大intervals.sort((a, b) => {if (a[0] != b[0]) return a[0] - b[0]else return a[1] - b[1]})let min = intervals[0][0], max = intervals[0][1], ans = []for (let i = 1; i < intervals.length; i++) {let a = intervals[i][0], b = intervals[i][1];if (a >= min && b <= max) continue;if (a > max) {ans.push([min, max])min = a, max = b;} else max = b;}ans.push([min, max])return ans;
};

738.单调递增的数字

738.单调递增的数字

var monotoneIncreasingDigits = function (n) {let str = n.toString()str = str.split('').map(item => {return Number(item)});// 找到第一个不是递增的位置let flag;for (let i = str.length - 1; i >= 0; i--) {if (str[i - 1] > str[i]) {flag = istr[i - 1]--;str[i] = 9}}for (let i = flag; i < str.length; i++) str[i] = 9return Number(str.join(''))
};

968.监控二叉树

968. 监控二叉树

困难先跳了。

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

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

相关文章

string的使用和模拟实现

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; C&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大…

iisfastchi漏洞复现

1.查看版本 2.在路径中写入 php脚本 发现使用不了 3.环境搭建 结局打开 把限制打开

SideBar 侧边导航与内容区域交互重写【Ant Design Mobile】

需求&#xff1a;SideBar 侧边导航与内容区域交互 点击侧边栏某一项时&#xff0c;相对应内容区域滚动到视口顶部滚动视口区域&#xff0c;到某一项内容区域&#xff0c;侧边栏选中状态也会跟着变化 const SideBarAgain: React.FC<PopupProps> (props) > {// 父组件…

可扩展性表设计方案

文章目录 1 使用预留字段2 使用JSON字段3 使用单表继承4 构建属性表5 直接构建新表6 适当冗余 1 使用预留字段 在表设计初期&#xff0c;可以预留一些命名通用的备用字段&#xff0c;例如field1、field2、field3。当业务需要增加新字段时&#xff0c;就直接使用这些预留字段,无…

Xilinx FPGA 7系列 GTX/GTH Transceivers (1)

初识Xlilix GTX 1概述 Xilinx 7系列FPGA全系所支持的GT,GT资源是Xilinx系列FPGA的重要卖点,也是做高速接口的基础,GT的意思是Gigabyte Transceiver,G比特收发器。不管是PCIE、SATA、MAC等,都需要用到GT资源来做数据高速串化和解串处理,Xilinx不同的FPGA系列拥有不同的G…

Kafka中Consumer源码解读

Consumer源码解读 本课程的核心技术点如下&#xff1a; 1、consumer初始化 2、如何选举Consumer Leader 3、Consumer Leader是如何制定分区方案 4、Consumer如何拉取数据 5、Consumer的自动偏移量提交 Consumer初始化 从KafkaConsumer的构造方法出发&#xff0c;我们跟踪到…

前端JavaScript中异步的终极解决方案:async/await

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 1. 背景 在深入讨论 async/await 之前&#xff0c;我们需要了解一下 JavaScript 的单线程和非阻塞的特性。JavaScript 是…

AD22使用笔记+积累库

一、前言 使用AD9习惯了&#xff0c;但是需求逐渐上来了就不够用了&#xff0c;好多快捷的新功能要新版本软件才能用&#xff0c;所以升级使用AD22 目录 1.添加层之后中间层无法布线 2.新增快捷方式CtrlW布线&#xff0c;不用点图标了 二、环境 AD22 三、正文 1.添加层之…

SpringBoot-RabbitMQ

RabbitMQ 是一个开源的消息中间件&#xff0c;它实现了 AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;协议&#xff0c;并提供了可靠的消息传递机制。 Spring Boot 中使用 RabbitMQ 实现异步消息的发送和接收。 使用 Spring Boot 提供的 AmqpTemplate 和 Rab…

Redis Part1

单体架构&#xff1a;一台Web服务器、一台数据库服务器。 1.了解NoSql 什么是Nosql&#xff1f; NoSQL&#xff0c;即Not-Only-SQL&#xff0c;意思就是我们干事情不能只用SQL&#xff0c;泛指非关系型的数据库&#xff01;NoSQL定位&#xff1a;作为关系型数据库的补充&am…

小米OPPO三星一加红魔全机型解锁BL详细教程合集-ROOT刷机必要操作

解锁BL一个熟悉又陌生的词汇&#xff0c;只要你刷机root过&#xff0c;你肯定都解锁BL成功过。我们简单的描述下BL是什么&#xff1f;BL全名bootloader&#xff0c;目前市面上全部机型&#xff0c;基本出厂全部BL处于锁定的状态锁定的BL机型&#xff0c;不支持刷入非官方固件或…

性能测试 —— Jmeter事务控制器

事务&#xff1a; 性能测试中&#xff0c;事务指的是从端到端&#xff0c;一个完整的操作过程&#xff0c;比如一次登录、一次 筛选条件查询&#xff0c;一次支付等&#xff1b;技术上讲&#xff1a;事务就是由1个或多个请求组成的 事务控制器 事务控制器类似简单控制器&…

广州口腔医院种植牙-广东省爱牙工程公益种牙,获湾区群众点赞

广州种植牙价格表-自2017年成立以来,广东省爱牙工程一直坚持以公益惠民为宗旨、公益种牙为服务方向,针对群众普遍存在的口腔健康问题,开展形式多样的公益性口腔医疗惠民活动。 广州种植牙费用表-日前,广东省爱牙工程“种植牙惠民行动”第二十季已正式启动。据广东省爱牙工程官方…

韩信点兵:求韩信一共有多少兵

任务描述 本关任务&#xff1a;求韩信一共有多少兵。 韩信有一队兵&#xff0c;他想知道有多少人&#xff0c;便让士兵排队报数。 按从 1 至5报数&#xff0c;最末一个士兵报的数为 1&#xff1b; 按从 1 至 6 报数&#xff0c;最末一个士兵报的数为 5&#xff1b; 按从 1 …

栈与队列--删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 示例&#xff1a; 输入&#x…

C/C++指针函数与函数指针

一、指针函数 指针函数&#xff1a;本质为一个函数&#xff0c;返回值为指针指针函数&#xff1a;如果一个函数的返回值是指针类型&#xff0c;则称为指针函数用指针作为函数的返回值的好处&#xff1a;可以从被调函数向主函数返回大量的数据&#xff0c;常用于返回结构体指针。…

基于ntchat的微信群聊同步机器人

微信群有500人上限的限制&#xff0c;建立多个群的话又有信息无法互通的不便&#xff0c;此机器人通过自动将消息转发到同一个同步组内的所有群&#xff0c;消除这一不便性&#xff0c;间接达成扩大群成员数的目的。 效果演示&#xff1a; 项目地址&#xff1a; https://gith…

为何红黑树在B/B+树之上仍然占据重要地位?

为何红黑树在B/B树之上仍然占据重要地位&#xff1f; 引言二、红黑树和B/B树的基本原理2.1、红黑树的特点和性质2.2、B/B树的特点和性质2.3、红黑树和B/B树的比较 三、B/B树相对于红黑树的优势四、红黑树仍然占据重要地位的原因总结 博主简介 &#x1f4a1;一个热爱分享高性能服…

Vue echarts 饼图 引导线加小圆点,文字分行展示

需求 重点代码 完整代码 initChart() {// 创建 echarts 实例。var myChartOne this.$echarts.init(this.$refs.Echart);myChartOne.setOption({tooltip: {trigger: "item",},title: {top: center,text: [{name| this.chartTitle.name },{value| this.chartTitle.…