LeetCode#646 Add Maximum Length of Pair Chain题解(C++版)

题干

这里写图片描述

原题网址:
https://leetcode.com/problems/maximum-length-of-pair-chain/description/

题干解析

给你n个数对,每个数对中第一个数永远小于第二个数。给数对定义一个规则,假定我们有(c, d)和(a, b)两个数对,当且仅当b

知识点

动态规划

难度

中等

解题思路

这道题是一道比较常见的动态规划题。思路大致上是:先给这些数对排序,按照每个数对中第一个数的大小,从小到大排好序。然后从头开始往后遍历,对于每一个数对只有两种情况,要么被选中,要么不被选中。被选中的话,链的长度就要加一,但是下一个开始的数对就会被本数对的第二个数据限制,因为要满足下一个数对的第一个数据大于上一个数对的第二个数据;不被选中的话,直接从下一个数对看起。只要比较被选中与不被选中哪个能得到最长的链就可以了。具体代码如下。

代码

int *long_num;  // 用来保存已经计算过的从下标为j开始往后的最长子序列的值,防止重复计算
class Solution {
public:
    int findlong(vector<vector<int> >& pairs, int j) {  // 寻找pairs中从下标为j开始往后的最长子序列
        if (j >= pairs.size()) {  // 如果已经越界了,返回0
            return 0;
        } else if(*(long_num + j) != -1) {  // 如果已经这个序列计算过了,直接返回之前得到的值
            return *(long_num + j);
        } else {
            int yes, no;  // yes表示要把第j个pair加入序列,no表示不加入
            no = findlong(pairs, j + 1);  // 如果不加入,直接求从下一个下标开始的最长子序列
            int k = j + 1;  // 如果要加入,下一个下标的pair的第一个元素应该大于当前pair的第二个元素
            while (k < pairs.size() && pairs[k][0] <= pairs[j][1]) {
                k++;
            }
            if (k >= pairs.size()) {  // 如果没有找到合适的下个pair,已经越界
                yes = 1;
            } else {
                yes = 1 + findlong(pairs, k);
            }
            if (yes > no) {  // 如果加入后最长子序列大于不加
                *(long_num + j) = yes;
                return yes;
            } else {   // 反之
                *(long_num + j) = no;
                return no;
            }
        }
    }
    int findLongestChain(vector<vector<int> >& pairs) {
        for (int i = pairs.size() - 1; i > 0; i--) {  // 按照每个pair的第一个元素给他们排个序 
            for (int j = 0; j < i; j++) {
                if (pairs[j][0] > pairs[j + 1][0]) {
                    vector<int> temp = pairs[j];
                    pairs[j] = pairs[j + 1];
                    pairs[j + 1] = temp;
                }
            }
        }
        long_num = new int[pairs.size()];
        for (int i = 0; i < pairs.size(); i++) {  // long_num全部初始化为-1
            *(long_num + i) = -1;
        }
        return findlong(pairs, 0);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值