1. 前言

由于后面还有很多题型要写,贪心算法目前可能就到此为止了,上一篇博客的地址为

LeetCode解题记录(贪心算法)(一)

下面正式开始我们的刷题之旅

2. 贪心

763. 划分字母区间(中等)

题目链接

思路

想切割,要有首尾两个指针,确定了结尾指针,就能确定下一个切割的开始指针。

遍历字符串,如果已扫描部分的所有字符,都只出现在已扫描的范围内,即可做切割。

注意 : 贪心的思想为,只要是扫描过的字符,都出现在我扫描的范围之类,我就切割,不去考虑其他的条件,这样能保证切割的数量最多

代码实现思路

  • result 用来保存结果
  • start end,片断的首尾指针
  • map 存放每一个字符的最远位置

首先通过一个map,记录了每个字符的最远的位置,接下来遍历字符串,end是用来记录,当前已经扫描的字符串的最远的出现的位置,如果当前的位置,等于扫描的字符串的最远位置,则,可以证明,到达了切割的条件,然后切割,存到result里

class Solution {
public:
vector<int> partitionLabels(string S) {
vector<int> result;
unordered_map<char, int> map; //记录char c 和其最后出现位置的 map
int start = 0, end = 0;
// 初始化map,记录每一个字符的最后位置
for (int i = 0; i < S.size(); i ++) {
map[S[i]] = i;
}
for (int i = 0; i < S.size(); i ++) {
end = max(end, map[S[i]]);//记录已扫描字符的最后一次出现的位置
if (i == end) {//说明后面的片段没有出现重复的字母了
result.push_back(end - start + 1);//记录结果
start = i + 1;
}
}
return result;
}
};

406. 根据身高重建队列(中等)

解题思路

贪心算法:按照身高从高到低进行排序,矮的放后面,因为矮的即使放在了高的前面,也不会对之前高的产生影响;但高的放在前面,对矮的结果就会产生影响了。

重写 compare() 方法:身高相同,按照个数升序排序;身高不同,按照身高降序排序。

public int compare(int[] o1, int[] o2) {

    // 先按身高降序,若身高相同则按 k 值升序。
return o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0];
}

第二个数字作为索引位置,把数组放在目标索引位置上,如果原来有数了,会往后移。(在一个 ListList 中的指定位置插入一个元素,当前指定位置的元素会往后面移动一个位置。)

遍历排序后的数组,根据 K 插入到 K 的位置上。

class Solution {

    public int[][] reconstructQueue(int[][] people) {

        int n = people.length;
int m = people[0].length;
if (n == 0 || m == 0) return new int[0][0]; Arrays.sort(people, new Comparator<int[]>() { @Override
public int compare(int[] o1, int[] o2) { // 先按身高降序,若身高相同则按 k 值升序。
return o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0];
}
}); // 遍历排序后的数组,根据 K 插入到 K 的位置上。
List<int[]> list = new ArrayList<>();
for (int[] i : people) { list.add(i[1], i);
}
return list.toArray(new int[list.size()][2]);
}
}

665. 非递减数列

题目链接

给你一个长度为 n 的整数数组,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。

我们是这样定义一个非递减数列的: 对于数组中任意的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。

示例 1:

输入: nums = [4,2,3]

输出: true

解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。

示例 2:

输入: nums = [4,2,1]

输出: false

解释: 你不能在只改变一个元素的情况下将其变为非递减数列。

提示:

1 <= n <= 10 ^ 4

10 ^ 5 <= nums[i] <= 10 ^ 5

题解:

贪心算法

本题是要维持一个非递减的数列,所以遇到递减的情况时(nums[i] > nums[i + 1]),要么将前面的元素缩小,要么将后面的元素放大。

但是本题唯一的易错点就在这,

如果将nums[i]缩小,可能会导致其无法融入前面已经遍历过的非递减子数列;

如果将nums[i + 1]放大,可能会导致其后续的继续出现递减;

所以要采取贪心的策略,在遍历时,每次需要看连续的三个元素,也就是瞻前顾后,遵循以下两个原则:

需要尽可能不放大nums[i + 1],这样会让后续非递减更困难;

就是能不放大就不放大,尽量与前面持平

如果缩小nums[i],但不破坏前面的子序列的非递减性;

算法步骤:

遍历数组,如果遇到递减:

还能修改:

修改方案1:将nums[i]缩小至nums[i + 1];

这个方案是,用i-1,i,i+1,来表示三个数的位置,其中i是我们发现大于i+1的数,那么当i+1大于i-1的时候,我们应该将i缩小至i+1,为什么呢,你想啊,你右边的数比你小,你左边的数比你小,但是呢,你右边的数比你左边的数高,你是不是只需要和你右边的一样高,就能保持非递减?如果你不这样,你让右边的数增加,这就违反了上面的第一条原则:需要尽可能不放大nums[i + 1],这样会让后续非递减更困难,因为这种情况,我们的选择是缩小i

修改方案2:将nums[i + 1]放大至nums[i];

这种情况是什么呢,与上一种相反,你左边右边的数都比你小,但是你右边的数比你左边的数要小,这个时候我们就应该将右边的数放大,放大至nums[i],也就是你的大小,这种情况下是没有争论的,只能将右边的数放大,不明白的同学可以自己在纸上画一画

如果不能修改了:直接返回false;

这个代码需要修改两个地方,显然不符合题目要求,返回false

代码如下

flag 代表修改机会,因为只有一次,所以用掉了,flag就变成false

class Solution {
public:
bool checkPossibility(vector<int>& nums)
{
if (nums.size() == 1) return true;
bool flag = nums[0] <= nums[1] ? true : false; // 标识是否还能修改
// 遍历时,每次需要看连续的三个元素
for (int i = 1; i < nums.size() - 1; i++)
{
if (nums[i] > nums[i + 1]) // 出现递减
{
if (flag) // 如果还有修改机会,进行修改
{
if (nums[i + 1] >= nums[ i - 1])// 修改方案1
nums[i] = nums[i + 1];
else // 修改方案2
nums[i + 1] = nums[i];
flag = false; // 用掉唯一的修改机会
}
else // 没有修改机会,直接结束
return false;
}
}
return true;
}
};

执行结果

3. 总结

对不起各位,我算法这块更新的实在是太慢了,不过最近真的很忙很忙,当然有时候我也会娱乐一下,没有做到自律,下个星期我还准备开始写计算机网络和操作系统的专栏,所以算法这块,我尽量多写(其实我就是懒,有时候晚上回家真的好累,不想写算法题,,,,)

总之,下个星期,继续努力,与昨天的自己比较!

最新文章

  1. 【转】TCP/IP协议栈及OSI参考模型详解
  2. 区间dp总结篇
  3. Linux下Chrome浏览器不支持WebGL的解决方式。
  4. HighChats报表使用C#mvc导出本地图片
  5. UISwitch(开关控件)、UISegmentedControl(分段控件)
  6. jQuery Validation remote的缓存请求
  7. 【转载】Android设计中的.9.png
  8. jquery完成带单选按钮的表格行高亮显示
  9. HTML5 API&#39;s (Application Programming Interfaces)
  10. js戳和php戳时间换算
  11. NSIS:安装、卸载时检查程序是否正在运行
  12. ZJOI 2019 游记
  13. LOJ #6539 奇妙数论题
  14. golang 中 channel 的非阻塞访问方法
  15. 转:[你必须知道的异步编程]C# 5.0 新特性——Async和Await使异步编程更简单
  16. day31
  17. 【转】Mysql行转换为列
  18. IOS 登录信息类(使用单例)
  19. Mysql中int和varchar类型
  20. 2016级算法第一次练习赛-F.AlvinZH的儿时梦想——机器人篇

热门文章

  1. 06.ElementUI 2.X 源码学习:源码剖析之工程化(一)
  2. Go语言web开发---Beego的cookie
  3. 记录: 解决 pycurl: libcurl link-time ssl backend (openssl) is different from compile-time ssl backend (none/other)
  4. pytest - 测试函数的传参:fixture,参数化。必须传入实参
  5. Python+Selenium学习笔记1 - pip命令
  6. pytest的allure的环境配置
  7. 使用有道云笔记还是github写笔记的优缺点对比
  8. Java双重循环
  9. 解Bug之路-ZooKeeper集群拒绝服务
  10. ST算法模板