(动态规划)leetcode354:俄罗斯套娃的信封问题

25 篇文章 0 订阅

题目

给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。

请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。

说明:
不允许旋转信封。

示例:

输入: envelopes = [[5,4],[6,4],[6,7],[2,3]]
输出: 3
解释: 最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/russian-doll-envelopes

分析

此题首先应该考虑应该考虑到排序的问题,按照数组的第一个元素升序排列,如果第一个元素相等,按照第二个元素的降序排列(这样在计算的时候不会把第一个元素相等的数组考虑进去,减少后面去重的工作量);
其次要找到递归方程:dp[i]=max(dp[i],dp[j]+1), 即第i个数组时一套套娃的最大信封数,为了去掉相同长度的信封数,还要加个判断条件 envelopes[j][1]<envelopes[i][1];
最后找到一组套娃最多的信封数。

错误代码

错误提示

Line 9: Char 48: fatal error: reference to non-static member function must be called
        sort(envelopes.begin(),envelopes.end(),func);
                                               ^~~~
1 error generated.
class Solution {
public:
    bool func(vector<int> &a,vector<int> &b)
    //按照数组的第一个元素升序排列,如果第一个元素相等,按照第二个元素的降序排列
    {
        return a[0]<b[0]||(a[0]==b[0]&&a[1]>b[1]);
    }
    int maxEnvelopes(vector<vector<int>>& envelopes) {
        sort(envelopes.begin(),envelopes.end(),func);//问题出在此行
        int n=envelopes.size();
        vector<int> dp(n,1);
        int res=0;
        
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(envelopes[j][1]<envelopes[i][1])
                {
                    dp[i]=max(dp[i],dp[j]+1);
                }
            }
            res=max(res,dp[i]);
        }
        return res;
    }
};

错误分析

1.问题的大概意思是:你调用了非静态成员函数,但你不是通过类对象来调用的
2.问题的原因其实就是函数参数不匹配的问题。因为我们普通的成员函数都有一个隐含的this指针,表面上看我们的函数func()只有两个参数,但实际上它有三个参数,

bool func(Solution *this,vector<int> &a,vector<int> &b)

而我们调用sort()排序函数的时候只需要用到两个参数进行比较,所以就出现了形参与实参不匹配的情况(函数有三个形参,但是只输入了两个实参)。
3.静态函数成员与非静态函数成员都为类所有,对象并不存在函数的拷贝。静态成员函数和非静态成员函数的根本区别在于非静态函数由对象名.或者对象指针->调用,调用时编译器会向函数传递this指针;静态成员函数则有类名::或者对象名.调用,编译器不向函数传递this指针,不识别对象个体,经常用来操作类的静态数据成员,要访问类的非静态成员可以通过对象来实现。
4.所以解决办法就是把函数func()变成静态成员函数即可。

正确代码

class Solution {
public:
    static bool func(vector<int> &a,vector<int> &b)
    //按照数组的第一个元素升序排列,如果第一个元素相等,按照第二个元素的降序排列
    {
        return a[0]<b[0]||(a[0]==b[0]&&a[1]>b[1]);
    }
    int maxEnvelopes(vector<vector<int>>& envelopes) {
        sort(envelopes.begin(),envelopes.end(),func);//按照规则排序
        int n=envelopes.size();
        vector<int> dp(n,1);//初始化的值为1
        int res=0;
        
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(envelopes[j][1]<envelopes[i][1])

                //套娃的规则是,后一个信封的长度和宽度必须比前一个大
                {
                    dp[i]=max(dp[i],dp[j]+1);//相同的长度的信封只能选一个
                }
            }
            res=max(res,dp[i]);//计算一组套娃最多的信封数
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值