题解 | #最长上升子序列(一)#

最长上升子序列(一)

http://www.nowcoder.com/practice/5f65ccbb025240bd8458eb6479c2612e

1.错误思路

看到示例

7
6 3 1 5 2 3 7

首先想到了用单调栈,因为单调栈可以得到递增子序列,那么以数组每个元素ii为结尾,向前查找最长的单调递减子序列

function main(arr, n) {
    let max = 1
    let stack = null
    for(let i = 1 ; i < n ; i++) {
        stack = [arr[i]] 
        for(let k = i - 1 ; k >= 0 ; k--) {
            let peek = stack[stack.length - 1]
            if(arr[k] < peek) stack.push(arr[k])
        }
        max = Math.max(max, stack.length)
    }
    return max
}

该方法将得到错误的结果,例如

6
1 2 3 4 3 5

该示例结果应该为5,但实际输出为4,因为从5向前递减,元素3已经决定了再之前的元素不能大等于3,而实际5之前的元素应该是4。考虑到这个问题,那或许就会联想到动态规划了,因为动态规划可以通过状态转移来避免上述单调栈所出现的问题,即我可以同时考虑元素4到元素5的状态转移,以及元素3到元素5的状态转移,两者取大值。

2.动态规划

动态规划的思路其实就是修改单调栈的缺陷,以元素arr[i]arr[i]为子序列结尾元素,查找最长递增子序列。状态转移方程则是当arr[i]>arr[k]arr[i] > arr[k]的时候,dp[i]=dp[k]+1dp[i] = dp[k] + 1,当然由于kk有多个值,我们要找最大值,则状态转移方程改为dp[i]=max(dp[i],dp[k]+1)dp[i] = max(dp[i], dp[k] + 1)

3.JavaScript实现

const n = ~~readline()
const arr = readline().split(' ').map(x => parseInt(x))

function main(arr, n) {
    let max = 1
    const dp = new Array(n).fill(1)
    for (let i = 1; i < n; i++) {
        for (let k = 0; k < i; k++) {
            if (arr[i] > arr[k]) {
                dp[i] = Math.max(dp[i], dp[k] + 1)
            }
        }
        max = Math.max(max, dp[i])
    }
    return max
}

console.log(main(arr, n))
全部评论

相关推荐

码农索隆:有点耳熟,你们是我教过最差的一届
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-08 10:39
一个证都没&nbsp;我能填什么
程序员小白条:别人有,你为什么没有,还是这个道理,社会就是比较,竞争,淘汰,你要安逸,那么就要做好淘汰的准备
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-07 12:04
毕业生招你惹你了,问一个发薪日来一句别看网上乱七八糟的你看哪个工作没有固定发薪日扭头就取消了面试就问了一句公司都是这个态度吗还搞上人身攻击了...
程序员小白条:呃呃呃,都还没面试,我都不会问这么细,何况通不通过,去不去都另说,你没实力和学历的话,在外面就这样,说实话没直接已读不回就不错了,浪费时间基本上
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务