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

目录

坏了的计算器(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][]);
 }
}
相关推荐
何苏三月1 分钟前
设计模式 - 单例模式(懒汉式、饿汉式、静态内部类、枚举)
java·单例模式
Renas_TJOvO4 分钟前
排序算法汇总
java·数据结构·算法
冬天的枫树5 分钟前
人工智能原理实验一:知识的表示与推理实验
c++·人工智能
Stardep6 分钟前
算法2—八大常用排序算法(下)
c语言·数据结构·笔记·算法·排序算法·1024程序员节
秋恬意15 分钟前
Java 反射机制详解
java·开发语言
我就说好玩16 分钟前
使用C语言实现经典贪吃蛇游戏
c语言·vscode·游戏
黑不溜秋的17 分钟前
C++ 模板专题 - 标签分派(Tag Dispatching)
开发语言·c++·算法
爱上语文22 分钟前
LeetCode每日一题
java·算法·leetcode
skywind27 分钟前
为什么 C 语言数组是从 0 开始计数的?
c语言·开发语言·网络·c++