0
点赞
收藏
分享

微信扫一扫

Leecode 刷题记录

老王420 2022-04-01 阅读 52
算法

剑指 Offer 35. 复杂链表的复制

Object.assign //Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }

console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(target===returnedTarget)
// true

回溯+哈希表
本题要求我们对一个特殊的链表进行深拷贝。如果是普通链表,我们可以直接按照遍历的顺序创建链表节点。而本题中因为随机指针的存在,当我们拷贝节点时,「当前节点的随机指针指向的节点」可能还没创建,因此我们需要变换思路。一个可行方案是,我们利用回溯的方式,让每个节点的拷贝操作相互独立。对于当前节点,我们首先要进行拷贝,然后我们进行「当前节点的后继节点」和「当前节点的随机指针指向的节点」拷贝,拷贝完成后将创建的新节点的指针返回,即可完成当前节点的两指针的赋值。

具体地,我们用哈希表记录每一个节点对应新节点的创建情况。遍历该链表的过程中,我们检查「当前节点的后继节点」和「当前节点的随机指针指向的节点」的创建情况。如果这两个节点中的任何一个节点的新节点没有被创建,我们都立刻递归地进行创建。当我们拷贝完成,回溯到当前层时,我们即可完成当前节点的指针赋值。注意一个节点可能被多个其他节点指向,因此我们可能递归地多次尝试拷贝某个节点,为了防止重复拷贝,我们需要首先检查当前节点是否被拷贝过,如果已经拷贝过,我们可以直接从哈希表中取出拷贝后的节点的指针并返回即可。

在实际代码中,我们需要特别判断给定节点为空节点的情况。

var copyRandomList = function(head, cachedNode = new Map()) {
    if (head === null) {
        return null;
    }
    if (!cachedNode.has(head)) {
        cachedNode.set(head, {val: head.val}), Object.assign(cachedNode.get(head), {next: copyRandomList(head.next, cachedNode), random: copyRandomList(head.random, cachedNode)})
    }
    return cachedNode.get(head);
}
//这里是这样的 首先通过对next的赋值 使得先递归一遍 建立完整的哈希表 这时整个链表已经建立完成 这样后续的random就可以正常的执行了

5. 最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:

输入:s = "babad"
输出:"bab"

解释:“aba” 同样是符合题意的答案。
示例 2:

输入:s = "cbbd"
输出:"bb"

这道题使用动态规划来处理,其基本思想为如果abba为回文串,那么bb就一定是回文串 反过来说 当s[i,j] 表示字符串中i到j的片段 其中如果s[i+1,j-1]是回文字符串的话,如果s[i] == s[j]
则 s[i,j] 为回文字符串
因此我门可以定义公式
p [ i , j ] = { t r u e 如 果 s [ i , j ] 是 回 文 串 f a l s e 如 果 s [ i , j ] 不 是 回 文 串 p[i,j]= \left\{ \begin{aligned} true 如果s[i,j]是回文串 \\ false 如果s[i,j]不是回文串 \\ \end{aligned} \right. p[i,j]={trues[i,j]falses[i,j]
这里的「其它情况」包含两种可能性:

  • s[i, j] 本身不是一个回文串;

  • i > j 此时s[i, j]s[i,j] 本身不合法。

那么我们就可以写出动态规划的状态转移方程:

dp[i,j] = dp[i+1,j-1]&&s[i] == s[j]

优化:
我们可以使用一维数组来进行处理 利用滚动原理 因为我们只需要最长的序列 所以我们可以使用dp[i+1] 来代替dp[i+1, j-1]的值

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function(s) {
    let list = []
    let Max_len = 0
    let start = 0
    for(j=0;j<s.length;++j) {
        for(i=0;i<=j;++i) {
            list[i] = (s[i] == s[j]&&(j-i < 2||list[i+1]))
            if(list[i]&&(j-i+1)>Max_len)
            {
                Max_len = (j-i+1)
                start = i
            }
        }
    }
    return s.slice(start,start+Max_len)

};
举报

相关推荐

0 条评论