题解 | #最长公共子序列(二)#

最长公共子序列(二)

https://www.nowcoder.com/practice/6d29638c85bb4ffd80c020fe244baf11

kotlin
动态规划基础版
object Solution {
    /**
    * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
    * longest common subsequence
        * @param s1 string字符串 the string
        * @param s2 string字符串 the string
        * @return string字符串
    */
    fun LCS(s1: String,s2: String): String  {
        val dp = Array<Array<StringBuilder>>(s1.length + 1) {
            Array<StringBuilder>(s2.length + 1) {
                StringBuilder()
            }
        }
        for(i in 1..s1.length) {
            for(j in 1..s2.length) {
                if(s1[i - 1] == s2[j - 1]) {
                    dp[i][j].append(dp[i - 1][j - 1].toString()).append(s2[j - 1])
                }
                else  {
                    if (dp[i - 1][j].length > dp[i][j - 1].length) dp[i][j].append(dp[i - 1][j].toString())  else dp[i][j].append(dp[i][j - 1].toString())
                }
            }
        }
        if(dp[s1.length][s2.length].length == 0) return "-1"
        return dp[s1.length][s2.length].toString()
    }
}
动态规划进阶版-滚动数组
object Solution {
    /**
    * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
    * longest common subsequence
        * @param s1 string字符串 the string
        * @param s2 string字符串 the string
        * @return string字符串
    */
    fun LCS(s1: String,s2: String): String  {
        //注意到其实我们的状态转移只与前一个数组有关(dp[i - 1][j - 1] 其中i - 1 表示使用前一个数组记录的值),因为我们维护两个数组,然后内部循环完之后交换数组的值就行了,这样可以节省空间
        val dp1 = Array<StringBuilder>(s2.length + 1) {
                StringBuilder()
            }
        val dp2 = Array<StringBuilder>(s2.length + 1) {
                StringBuilder()
            }
        for(i in 1..s1.length) {
            for(j in 1..s2.length) {
                if(s1[i - 1] == s2[j - 1]) {
                    dp2[j].append(dp1[j - 1].toString()).append(s2[j - 1])
                }
                else  {
                    if (dp1[j].length > dp2[j - 1].length) dp2[j].append(dp1[j].toString())  else dp2[j].append(dp2[j - 1].toString())
                }
            }
            //交换数组的值
            swap(dp2, dp1)
        }
        if(dp1[s2.length].length == 0) return "-1"
        return dp1[s2.length].toString()
    }
    
    private inline fun swap(src: Array<StringBuilder>, des: Array<StringBuilder>) {
        for(i in src.indices) {
            //清楚之前的数据然后添加新数据
            des[i].clear()
            des[i].append(src[i].toString())
            //清楚数据,等一下会添加新的数据
            src[i].clear()
        }
    }
}
动态规划进阶版-维护两个临时变量
object Solution {
    /**
    * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
    * longest common subsequence
        * @param s1 string字符串 the string
        * @param s2 string字符串 the string
        * @return string字符串
    */
    fun LCS(s1: String,s2: String): String  {
        val dp = Array<StringBuilder>(s2.length + 1) {
                StringBuilder()
            }
        /之前使用滚动数组来减少空间,但实际上这任然是浪费空间的,我们注意到我们实际上只使用了上一个数组的相同下标或前一个下标的值(dp[i - 1][j - 1] 表示前一个数组的当前下标的前一个值,dp[i - 1][j] 表示前一个数组相同下标的值)
        //因此我们可以用两个变量来记住这两个值即可
        var prev = ""
        var temp = ""
        for(i in 1..s1.length) {
            //开始前为初始状态
            prev = ""
            for(j in 1..s2.length) {
                //此时temp相当于dp[i - 1][j]
                temp = dp[j].toString()
                dp[j].clear()
                if(s1[i - 1] == s2[j - 1]) {
                    dp[j].append(prev).append(s2[j - 1])
                }
                else  {
                    if (temp.length > dp[j - 1].length) dp[j].append(temp)  else dp[j].append(dp[j - 1].toString())
                }
                //此时赋值给prev下一轮使用的时候相当于dp[i - 1][j - 1]
                prev = temp
            }
        }
        if(dp[s2.length].length == 0) return "-1"
        return dp[s2.length].toString()
    }
}
其实还有一个逆序遍历,连临时变量都不用维护的方法,但在这里不合适用,等遇到合适使用的题再补充另外一种解法



全部评论

相关推荐

点赞 1 评论
分享
正在热议
# 牛客帮帮团来啦!有问必答 #
1151650次浏览 17149人参与
# 通信和硬件还有转码的必要吗 #
11203次浏览 101人参与
# OPPO开奖 #
19201次浏览 267人参与
# 和牛牛一起刷题打卡 #
18978次浏览 1635人参与
# 实习与准备秋招该如何平衡 #
203386次浏览 3627人参与
# 大厂无回复,继续等待还是奔赴小厂 #
4972次浏览 30人参与
# 不去互联网可以去金融科技 #
20385次浏览 255人参与
# 通信硬件薪资爆料 #
265913次浏览 2484人参与
# 国企是理工四大天坑的最好选择吗 #
2223次浏览 34人参与
# 互联网公司评价 #
97687次浏览 1280人参与
# 简历无回复,你会继续海投还是优化再投? #
25037次浏览 354人参与
# 0offer是寒冬太冷还是我太菜 #
454868次浏览 5124人参与
# 国企和大厂硬件兄弟怎么选? #
53903次浏览 1012人参与
# 参加过提前批的机械人,你们还参加秋招么 #
14644次浏览 349人参与
# 硬件人的简历怎么写 #
82286次浏览 852人参与
# 面试被问第一学历差时该怎么回答 #
19398次浏览 213人参与
# 你见过最离谱的招聘要求是什么? #
28097次浏览 248人参与
# 学历对求职的影响 #
161239次浏览 1804人参与
# 你收到了团子的OC了吗 #
538722次浏览 6386人参与
# 你已经投递多少份简历了 #
344226次浏览 4963人参与
# 实习生应该准时下班吗 #
96977次浏览 722人参与
# 听劝,我这个简历该怎么改? #
63524次浏览 622人参与
牛客网
牛客企业服务