动态规划 - 最长对数链 - 中等难度

*************

C++
topic: 646. 最长数对链 - 力扣(LeetCode)

*************

Inspect the topic 

短暂的回归一下中文,因为退了之前的一把键盘,现在是用的新买的键盘,还是用中文更顺手一点,不知道为什么,用中文的打字速度就是比用英文的快很多,可能大脑用更多的资源来联想单词而使用中文的话不需要那么多的资源来思考单词和语法。不是很清楚呢。但是现在用的这个新到的键盘打字肉肉的,虽然是矮轴,但是现在有点习惯后后感觉还不错,就是有点不太想退了,先把这篇文章写完吧。

还是使用我之前的方法,想一下我有没有做过类似的题。仔细想一下的话,关于数组的题目我做过一点,因为一直在练习数组的题目。这个可能跟最长递增子序列的个数 - 中等难度_给定一个长度为 n 的数列,求数值严格单调递增的子序列的长度最长是多少。输入格式-CSDN博客

这个有点关系, 但是呢仔细想一下的话,关系也不是很大。

Back to EN, used to the keyboard and have to output EN to inspect my interlagence. And hash-table cannot be used here, either. 

Have a slight glance at the lables,   贪心算法, 我不会,因为我不贪心。      

还有就是暴力美学,简单粗暴的遍历所有的数组,然后对数组进行从小到大的排列。如果是每组置于一个数字的话,就是非常简单的题目,就是把数组从小到大进行排列。但是时过境迁了,现在的每组有两个数组,这个就比较的难以解决了,只能现在先学习一下贪心算法是怎么贪心的。

所谓贪心算法,就是指在每一步过程中都选择最优解,这样的话会希望全局是最优解。算法步骤就是每一步采取当前状态下的最优解。

算法只是算法,具体的实现没有什么特别的语法结构。我觉得贪心算法相当于一个成语,就好像说到 屎上雕花 就知道这写的就是一坨,说到 彭于晏 就联想到 我, 说到 闭月羞花 就想到貂蝉,我如果没记错的话,沉鱼落雁说的是西施,闭月羞花说的是貂蝉闭月,杨玉环羞花。

OK,贪心算法的本质就是,每一步都选当前状态下的最优解,具体怎么实现的,无所谓。举个例子,给你一个小目标的任务,我当前的最优状态就是每个月存个100块钱,然后存上100000000/100/12 = 83333 年。每个月的最优解就是存100, 全局最优解是存到1个亿,一个月存100块,得存 83333 年,恐怖。

突然想到排序,我之前做过一个排序题,就是动态规划 - 堆箱子 - 困难 - 再尝试_boxes = [details['left'][i], details['top'][i], de-CSDN博客,这个题给的是3维的,用的是 sort 函数排序,sort 也是一个标准库,主要的工作就是对数组中的元素进行排序。这个一想的话就很简单了。

复习一下 sort 的用法:

基本用法:

sort(ForwardIterator first, ForwardIterator last);
// first:指向要排序的序列的开始位置的迭代器。
// last:指向要排序的序列的结束位置的迭代器(不包含此位置)。
// 这个函数会将 [first, last) 范围内的元素进行排序。

自定义排序:

sort(ForwardIterator first, ForwardIterator last, Compare comp);

// comp:一个比较函数或函数对象,它接受两个参数并返回一个布尔值,指示第一个参数是否应该排在第二个参数之前。

举个栗子:如果我,in the other word, 也就是 彭于晏,想对一个 vector<int> 进行排序,可以这样使用 sort

#include <algorithm>
#include <vector>

int main() {
    std::vector<int> vec = {5, 3, 8, 6, 2};
    std::sort(vec.begin(), vec.end());

    // 使用自定义比较函数
    std::sort(vec.begin(), vec.end(), [](int a, int b) {
        return a > b; // 降序排序
    });

    return 0;
}

所以这个怎么用贪心算法呢?我的直觉就是按照数组里面的第二个数进行排列,按照第二个数递增的顺序,然后遍历数组,然后选择符合条件的数对。

假设,

pairs = [[1,2], [2,3], [3,4], [1,3], [1,4]]

排序后: [[1,2],[2,3],[1,3],[3,4],[1,4]]、

然后对排序后的数组进行贪心选择:初始化一个变量 current_end 来记录当前链的最后一个数对的第二个数,初始值设为负无穷大。然后遍历排序后的数对数组,如果当前数对的第一个数大于 current_end,则选择该数对,并更新 current_end 为该数对的第二个数,同时计数器加一。

首先来写的是就是最重要的排序代码,按照 sort 的语法,起始就是 paris.begin(), 终止就是 paris.end(), 然后 对数组进行引用。

class Solution {
public:
    int findLongestChain(vector<vector<int>>& pairs) {
        // 按数对的第二个数进行排序
        sort(pairs.begin(), pairs.end(), [](const vector<int>& a, const vector<int>& b) {
            return a[1] < b[1];
        });
        
    }
};

 复习一下代码中的语法,先从判断条件开始:

  1. a[1]b[1]:这两个表达式分别访问数对ab的第二个元素。在C++中,vector<int>类型的数对可以像数组一样通过下标访问元素,其中0是第一个元素的下标,1是第二个元素的下标。

  2. const vector<int>& a:这是lambda表达式的参数,表示一个对vector<int>的常量引用,即数对a
  3. pairs.begin(), pairs.end():这两个函数调用返回向量pairs的开始和结束迭代器。begin()返回指向向量第一个元素的迭代器,end()返回一个指向向量末尾的迭代器。

对数对进行排序完成之后,就是下一步,贪心算法了。

已知,排序后的数组是按照从小到大的排列顺序;

那么,让程序遍历数组,

如果 b[0] > a[1],

那么就更新数组,并且计数 + 1;

直到最后:

class Solution {
public:
    int findLongestChain(vector<vector<int>>& pairs) {
        // 按数对的第二个数进行排序
        sort(pairs.begin(), pairs.end(), [](const vector<int>& a, const vector<int>& b) {
            return a[1] < b[1];
        });
        
        int current_end = INT_MIN; // 当前链的最后一个数对的第二个数
        int count = 0; // 计数器,记录链的长度
        
        for (const auto& pair : pairs) {
            if (pair[0] > current_end) {
                count++;
                current_end = pair[1];
            }
        }
        
        return count;
    }
};

最后,提交。

写到这里的话,我决定留下了这个键盘,因为逐渐习惯了以后,是个还不错的手感,声音闷闷的,不像之前的那个键盘一样是麻将音,也没有RGB灯,就是简单的白灯,还是喜欢简单的事情,简单的关系,简单的设计。

明天周五了,希望有个愉快的周末。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值