2020.09.28-2020.10.03 leetcode刷题总结(贪心&堆)

贪心算法
一.题目列表
1.判断子序列
题目描述:
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

示例:
s = “abc”, t = “ahbgdc”
返回 true.

题解:
两个循环遍历,增加一个标志变量,判断是否为最后一个元素。

2.K 次取反后最大化的数组和
题目描述:
给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)
以这种方式修改数组后,返回数组可能的最大和。

示例:
输入:A = [4,2,3], K = 1
输出:5
解释:选择索引 (1,) ,然后 A 变为 [4,-2,3]。

题解:
先将数组排序,将A[0]反转,若反转A[1]>=反转后的A[0],则仍将A[0]反转,否则反转A[1],并且依次向前。

3.无重叠区间
题目描述:
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

示例:
输入: [ [1,2], [2,3], [3,4], [1,3] ]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。

题解:
将数组按结束点排序,如果当前节点的开始时间下大于等于前一个结点的结束时间,则保留。返回二维数组长度-保留数目

4.买卖股票的最佳时机 II
题目描述:
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。

题解:
等价于每天都买卖,若当前价格-前一天价格大于零则买入,否则不买。

5.移掉K位数字
题目描述:
给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。

示例:
输入: num = “1432219”, k = 3
输出: “1219”
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。

题解:
只要当前的数组比左边的数字小,就应该删除左面的数字,如果删除的数学小于k个,则应该从后向前删除剩下的k个数组。最后输出,注意删除前导零。

6.最长快乐字符串
题目描述:
如果字符串中不含有任何 ‘aaa’,‘bbb’ 或 ‘ccc’ 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。
给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 s:
s 是一个尽可能长的快乐字符串。
s 中 最多 有a 个字母 ‘a’、b 个字母 ‘b’、c 个字母 ‘c’ 。
s 中只含有 ‘a’、‘b’ 、‘c’ 三种字母。
如果不存在这样的字符串 s ,请返回一个空字符串 “”。

示例:
输入:a = 1, b = 1, c = 7
输出:“ccaccbcc”
解释:“ccbccacc” 也是一种正确答案。

题解:
先定义一个类,存放字符和其数目,然后将其按字符数目由高到低排序,先放最多的, 如果上个放的2个字符串和剩余个数最多的字符相同,则放置次多的字符,最后将剩余的放置

7.删列造序
题目描述:
给定由 N 个小写字母字符串组成的数组 A,其中每个字符串长度相等。
你需要选出一组要删掉的列 D,对 A 执行删除操作,使 A 中剩余的每一列都是 非降序 排列的,然后请你返回 D.length 的最小可能值。
删除 操作的定义是:选出一组要删掉的列,删去 A 中对应列中的所有字符,形式上,第 n 列为 [A[0][n], A[1][n], …, A[A.length-1][n]])。(可以参见 删除操作范例)

示例:
输入:[“cba”, “daf”, “ghi”]
输出:1
解释:
当选择 D = {1},删除后 A 的列为:[“c”,“d”,“g”] 和 [“a”,“f”,“i”],均为非降序排列。若选择 D = {},那么 A 的列 [“b”,“a”,“h”] 就不是非降序排列了。

题解:

8.重构字符串
题目描述:
给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。若可行,输出任意可行的结果。若不可行,返回空字符串

示例:
输入: S = “aab”
输出: “aba”

题解:
定义一个字符和其数目的类,将字符数目从高到底排序,将字符和数目放到优先队列中,弹出最多的两个,将他们放入stringbuilder,将该字符和其数目-1再放入优先队列中,最后放入优先队列中剩余的

9.两地调度
题目描述:
公司计划面试 2N 人。第 i 人飞往 A 市的费用为 costs[i][0],飞往 B 市的费用为 costs[i][1]。
返回将每个人都飞到某座城市的最低费用,要求每个城市都有 N 人抵达。

示例:
输入:[[10,20],[30,200],[400,50],[30,20]]
输出:110
解释:
第一个人去 A 市,费用为 10。
第二个人去 A 市,费用为 30。
第三个人去 B 市,费用为 50。
第四个人去 B 市,费用为 20。
最低总费用为 10 + 30 + 50 + 20 = 110,每个城市都有一半的人在面试。

题解:
先全部飞到A地,在计算从A飞到B的花费,可能为负数,挑选花费最低的N个飞到B地。

二.相关语法及用法
1.优先队列 PriorityQueue pq = new PriorityQueue((a,b)->
a.count == b.count? a.letter-b.letter : b.count-a.count);
pq.add pq.poll();
2.StringBuilder ans = new StringBuilder();
pq.poll(); ans.append(mc2.letter);

一.题目列表
1.最小的k个数
题目描述:
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

示例:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]

题解:
定义一个从小到大的优先队列,输出k个值

2.数据流中的第K大元素
题目描述:
设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。
你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用 KthLargest.add,返回当前数据流中第K大的元素。

示例:
int k = 3;
int[] arr = [4,5,8,2];
KthLargest kthLargest = new KthLargest(3, arr);
kthLargest.add(3); // returns 4
kthLargest.add(5); // returns 5
kthLargest.add(10); // returns 5
kthLargest.add(9); // returns 8
kthLargest.add(4); // returns 8

题解:

3.分割数组为连续子序列
题目描述:
给你一个按升序排序的整数数组 num(可能包含重复数字),请你将它们分割成一个或多个子序列,其中每个子序列都由连续整数组成且长度至少为 3 。
如果可以完成上述分割,则返回 true ;否则,返回 false 。

示例:
输入: [1,2,3,3,4,5]
输出: True
解释:
你可以分割出这样两个连续子序列 :
1, 2, 3
3, 4, 5

题解:
定义一个hashmap类型的count存放数组的数目,tail存放该数字之前的子序列的个数。如果能存放完则返回ture 否则false.

4.最后一块石头的重量
题目描述:
有一堆石头,每块石头的重量都是正整数。
每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。

示例:
输入:[2,7,4,1,8,1]
输出:1
解释:
先选出 7 和 8,得到 1,所以数组转换为 [2,4,1,1,1],
再选出 2 和 4,得到 2,所以数组转换为 [2,1,1,1],
接着是 2 和 1,得到 1,所以数组转换为 [1,1,1],
最后选出 1 和 1,得到 0,最终数组转换为 [1],这就是最后剩下那块石头的重量。

题解:

5.数组中的第K个最大元素
题目描述:
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

题解:

6…根据字符出现频率排序
题目描述:
给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

示例:
输入:
“tree”
输出:
“eert”
解释:
'e’出现两次,'r’和’t’都只出现一次。
因此’e’必须出现在’r’和’t’之前。此外,"eetr"也是一个有效的答案。

题解:
定义一个数组存放元素数目,定义一个大顶堆返回将元素数目从高到低排序,然后弹出堆顶,stringbuilder增加该数目的元素个数。

7.有序矩阵中第K小的元素
题目描述:
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素。

示例:
输入:
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
返回 13。

题解:
定义一个大顶堆,存放k个数,先遍历行,若小则放入否则遍历下一行,最终返回堆顶元素

8.最接近原点的 K 个点
题目描述:
我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。
(这里,平面上两点之间的距离是欧几里德距离。)
你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。

示例:
输入:points = [[1,3],[-2,2]], K = 1
输出:[[-2,2]]
解释:
(1, 3) 和原点之间的距离为 sqrt(10),
(-2, 2) 和原点之间的距离为 sqrt(8),
由于 sqrt(8) < sqrt(10),(-2, 2) 离原点更近。
我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]。

题解:

9.~IPO
题目描述:
假设 力扣(LeetCode)即将开始其 IPO。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k 个不同的项目。帮助 力扣 设计完成最多 k 个不同项目后得到最大总资本的方式。
给定若干个项目。对于每个项目 i,它都有一个纯利润 Pi,并且需要最小的资本 Ci 来启动相应的项目。最初,你有 W 资本。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。
总而言之,从给定项目中选择最多 k 个不同项目的列表,以最大化最终资本,并输出最终可获得的最多资本。

示例:
输入: k=2, W=0, Profits=[1,2,3], Capital=[0,1,1].
输出: 4
解释:
由于你的初始资本为 0,你尽可以从 0 号项目开始。
在完成后,你将获得 1 的利润,你的总资本将变为 1。
此时你可以选择开始 1 号或 2 号项目。
由于你最多可以选择两个项目,所以你需要完成 2 号项目以获得最大的资本。
因此,输出最后最大化的资本,为 0 + 1 + 3 = 4。

题解:
将启动资金从低到高排序,将可获得的利润从高到底排序。然后依次加入利润值

二.相关语法及用法
1.堆中元素是一个数组 PriorityQueue<int []> pq = new PriorityQueue<>(K, (o1, o2) -> o1[0] * o1[0] + o1[1] * o1[1] - o2[0] * o2[0] - o2[1] * o2[1]);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值