两维影响条件排序问题(排序+求最大递增子序列)js实现

题目:有个人打怪赢得了很多宝物,他要将宝物卖给一个收藏家,这个收藏家有一个习惯,就是他每次都不会收购比上一件宝物价值低的宝物,评价宝物的价值有两个因子x和h,只有一件宝物的x和h都比另一件高才能说这件宝物比另一件价值高。给出一个宝物的序列,求可以卖出去的宝物最大件数。

例如:
输入[{x:3,h:2},{x:1,h:3},{x:1,h:1},{x:2,h:2}],
输出3

解题思路:我们首先肯定想到要对宝物的价值进行排序,找到最大递增子序列,但是影响宝物价值的因素有两个,因此我们可以先确定一个影响因素,再去考虑另一个,首先我们先根据x对数组进行由小到大排序,得到:[ { x: 1, h: 3 }, { x: 1, h: 1 }, { x: 2, h: 2 }, { x: 3, h: 2 } ],确定了一个影响因素后,后面我们无需再考虑x,只需求得数组根据y的最长递增子序列(注意这里是非严格递增)了。
{3,1,2,2}的最长非严格递增子序列为{1,2,2},因此结果为3.
但是这样还不够,举个例子[{x:1,h:2},{x:1,h:1},{x:2,h:1},{x:2,h:3},{x:3,h:4},{x:3,h:3},{x:4,h:5},{x:4,h:1}],根据x排序后为:
[ { x: 1, h: 2 },
{ x: 1, h: 1 },
{ x: 2, h: 1 },
{ x: 2, h: 3 },
{ x: 3, h: 4 },
{ x: 3, h: 3 },
{ x: 4, h: 5 },
{ x: 4, h: 1 } ]
{2,1,1,3,4,3,5,1}的最长非严格递增子序列为{1,1,3,3,5},因此求得结果为5,求得卖出去的宝物为[
{ x: 1, h: 1 },
{ x: 2, h: 1 },
{ x: 2, h: 3 },
{ x: 3, h: 3 },
{ x: 4, h: 5 },]
但是实际结果应该为6,可以卖出去的宝物应该为
[ { x: 1, h: 1 },
{ x: 1, h: 1 },
{ x: 1, h: 2 },
{ x: 2, h: 3 },
{ x: 3, h: 3 },
{ x: 4, h: 5 }]
这是因为除了将数组排序为x递增,对于x相同的情况,h小的应该排在h值大的前面,对
{1,1,2,3,4,3,5,1}求最长非严格递增子序列与对{2,1,1,3,4,3,5,1}求最长非严格递增子序列的结果是不一样的。
因此代码为:

function maxNum(arr){
    var max = 0;
    //将数组排序为x递增,x相同情况下y递增的数组
    arr.sort(function(pre,after){
       return pre.x > after.x || (pre.x == after.x && pre.h > after.h);
    });
    //利用动态规划求最长递增子序列大小
    var dp = [];
    for(var i=0;i<arr.length;i++){
        dp[i] = 1;
        for(var j=0;j<i;j++){
            if(arr[j].h <= arr[i].h){
                dp[i] = Math.max(dp[i],dp[j]+1);
            }
        }
        max = Math.max(max,dp[i]);
    }
    return max;
   }
   console.log(maxNum([{x:3,h:2},{x:1,h:3},{x:1,h:1},{x:2,h:2}]));
   console.log(maxNum([{x:1,h:2},{x:1,h:1},{x:2,h:1},{x:2,h:3},{x:3,h:4},{x:3,h:3},{x:4,h:5},{x:4,h:1}]));

另外再将将如何求最长递增子序列长度,例如:
数组A=[4,1,3,7,4,2,0,9]的最长递增子序列为[1,3,4,9]或者[1,3,7,9],最长递增子序列长度为4
假设dp[i]表示在数组A的下标0到i这个子序列中,并且以A[i]为结尾的最长递增子序列长度。例如dp[2]表示[4,1,3]的以3为结尾的递增子序列的长度的最大值,[4,1,3]的以3为结尾的递增子序列为【1,3】,因此dp[2] == 2;同理可得dp[0] == 1,dp[1] == 1,dp[3]==3,
接下来我们求dp[4]: A[4]=4,要求[4,1,3,7,4]中以4为结尾的递增子序列的长度的最大值,我们可以扫描A[4]的前面比A[4]小的有A[1]==1和A[2]==3,以4为结尾的递增子序列,4的前面一个可以是3也可以是1因此dp[4] = Math.max(dp[1]+1,dp[2]+1,1).
求得dp[0~A的长度-1]后,dp中的最大值就是数组的最长递增子序列长度

var max = 0;
var dp = [];
for(var i=0;i<A.length;i++){
    dp[i] = 1;
    for(var j=0;j<i;j++){
        if(A[j] <= A[i]){
            dp[i] = Math.max(dp[i],dp[j]+1);
        }
    }
    max = Math.max(max,dp[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值