【贪心算法】(第十一篇)

目录

坏了的计算器(medium)

题目解析

讲解算法原理

编写代码

合并区间(medium)

题目解析

讲解算法原理

编写代码


坏了的计算器(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

在显⽰着数字 startValue 的坏计算器上,我们可以执⾏以下两种操作:

◦ 双倍(Double):将显⽰屏上的数字乘2;

◦ 递减(Decrement):将显⽰屏上的数字减 1 。

给定两个整数 startValue 和 target 。返回显⽰数字 target 所需的最⼩操作数。

⽰例1:

输⼊:startValue=2,target=3

输出:2

解释:先进⾏双倍运算,然后再进⾏递减运算{2->4->3}.

⽰例2:

输⼊:startValue=5,target=8

输出:2

解释:先递减,再双倍{5->4->8}.

⽰例3:

输⼊:startValue=3,target=10

输出:3

解释:先双倍,然后递减,再双倍{3->6->5->10}.

提⽰:

◦ 1 <= startValue, target <= 10^9

讲解算法原理

解法(贪⼼):
贪⼼策略:
正难则反:

当「反着」来思考的时候,我们发现:

i. 当 end <= begin 的时候,只能执⾏「加法」操作;ii. 当 end > begin 的时候,对于「奇数」来说,只能执⾏「加法」操作;对于「偶数」来

说,最好的⽅式就是执⾏「除法」操作

这样的话,每次的操作都是「固定唯⼀」的。

编写代码

c++算法代码:

cpp 复制代码
class Solution
{
public:
 int brokenCalc(int startValue, int target) 
 {
 // 正难则反 + 贪⼼
 int ret = 0;
 while(target > startValue)
 {
 if(target % 2 == 0) target /= 2;
 else target += 1;
 ret++;
 }
 return ret + startValue - target;
 }
};

java算法代码:

java 复制代码
class Solution
{
 public int brokenCalc(int startValue, int target) 
 {
 // 正难则反 + 贪⼼
 int ret = 0;
 while(target > startValue)
 {
 if(target % 2 == 0) target /= 2;
 else target += 1;
 ret++;
 }
 return ret + startValue - target;
 }
}

合并区间(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

以数组 intervals 表⽰若⼲个区间的集合,其中单个区间为 intervals[i] = [start(i), end(i)] 。请你合并所有重叠的区间,并返回⼀个不重叠的区间数组,该数组需恰好覆盖输⼊中的所有区间。

⽰例1:

输⼊:intervals=[[1,3],[2,6],[8,10],[15,18]]

输出:[[1,6],[8,10],[15,18]]

解释:区间[1,3]和[2,6]重叠,将它们合并为[1,6].

⽰例2:

输⼊:intervals=[[1,4],[4,5]]

输出:[[1,5]]

解释:区间[1,4]和[4,5]可被视为重叠区间。

提⽰:

◦ 1 <= intervals.length <= 10^4

◦ intervals[i].length == 2

◦ 0 <= start(i) <= end(i) <= 10^4

讲解算法原理

解法(排序+贪⼼):
贪⼼策略:

a. 先按照区间的「左端点」排序:此时我们会发现,能够合并的区间都是连续的;b. 然后从左往后,按照求「并集」的⽅式,合并区间。

如何求并集:

由于区间已经按照「左端点」排过序了,因此当两个区间「合并」的时候,合并后的区间:a. 左端点就是「前⼀个区间」的左端点;

b. 右端点就是两者「右端点的最⼤值」。

编写代码

c++算法代码:

cpp 复制代码
class Solution
{
public:
 vector<vector<int>> merge(vector<vector<int>>& intervals) 
 {
 // 1. 先按照左端点排序
 sort(intervals.begin(), intervals.end());
 // 2. 合并区间
 int left = intervals[0][0], right = intervals[0][1];
 vector<vector<int>> ret;
 for(int i = 1; i < intervals.size(); i++)
 {
 int a = intervals[i][0], b = intervals[i][1];
 if(a <= right) // 有重叠部分
 {
 // 合并 - 求并集
 right = max(right, b);
 }
 else // 没有重叠部分
 {
 ret.push_back({left, right}); // 加⼊到结果中 left = a;
 right = b;
 }
 }
 // 别忘了最后⼀个区间
 ret.push_back({left, right});
 return ret;
 }
};

java算法代码:

java 复制代码
class Solution
{
 public int[][] merge(int[][] intervals) 
 {
 // 1. 按照左端点排序
 Arrays.sort(intervals, (v1, v2) -> 
 {
 return v1[0] - v2[0];
 });
 // 2. 合并区间 - 求并集
 int left = intervals[0][0], right = intervals[0][1];
 List<int[]> ret = new ArrayList<>();
 for(int i = 1; i < intervals.length; i++)
 {
 int a = intervals[i][0], b = intervals[i][1];
 if(a <= right) // 有重叠部分
 {
 // 合并 - 求并集
 right = Math.max(right, b);
 }
 else // 不能合并
 {
 ret.add(new int[]{left, right});
 left = a;
 right = b;
 }
 }
 // 别忘了最后⼀个区间
 ret.add(new int[]{left, right});
 return ret.toArray(new int[0][]);
 }
}
相关推荐
ZTLJQ3 分钟前
基于机器学习的三国时期诸葛亮北伐失败因素量化分析
人工智能·算法·机器学习
橘猫云计算机设计4 分钟前
基于springboot微信小程序的旅游攻略系统(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·微信小程序·毕业设计·旅游
落榜程序员5 分钟前
Java 基础-30-单例设计模式:懒汉式与饿汉式
java·开发语言
顾林海5 分钟前
深度解析ArrayList工作原理
android·java·面试
雷渊7 分钟前
spring-IoC容器启动流程源码分析
java·后端·面试
划水哥~9 分钟前
创建QMainWindow菜单栏
开发语言·c++·qt
用户33154891110712 分钟前
一招搞定Java线程池炸弹,系统吞吐量暴增10倍!
java·后端
努力的搬砖人.16 分钟前
maven如何使用
java·后端·面试·maven
饕餮ing17 分钟前
C++的UDP连接解析域名地址错误
开发语言·c++·udp
风象南20 分钟前
SpringBoot中6种跨域请求解决方案
java·spring boot·后端