前端算法必刷题系列[61]

199 阅读4分钟

这是我参与更文挑战的第 10 天,活动详情查看 更文挑战

这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。

116. 相交链表 (intersection-of-two-linked-lists)

标签

  • 链表
  • 简单

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null

图示两个链表在节点 c1 开始相交:

image.png

题目数据 保证 整个链式结构中不存在环

注意,函数返回结果后,链表必须 保持其原始结构

示例 1:

image.png

输入:listA = [4,1,8,4,5], listB = [5,0,1,8,4,5]
输出:Intersected at '8'
解释:相交节点的值为 8
从各自的表头开始算起,链表 A[4,1,8,4,5],链表 B[5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

image.png

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4]
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A[0,9,1,2,4],链表 B[3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

基本思路

  1. 用指针 PA 指向 A 链表,指针 PB 指向 B 链表
A 链表 (ABCDEFG)
headA
PA
|
A -> B -> C -> D -> E -> F -> G -> null
                    |               
          X -> Y -> Z
          |
          PB
         headB
         B 链表 (XYZEFG)

交点在 `E` 点
  1. PA, PB 指针依次往后走,
    • PA 假设 A->E(交点) 距离为 l1(4步)
    • PB 假设 X->E(交点) 距离为 l2(3步)
    • 由交点到结尾 距离为 l3(3步)
  // [A -> E l1=4步]      [E -> null l3=3步]   
(A) -> B -> C -> D -> (E) -> F -> (G) -> null
                       ^
                       |               
           (X) -> Y -> Z
         // [X -> E l2=3步]

就本例而言,A 链长,A的路径是 A -> E -> 尾部,然后到 B的头 -> X -> E, 走过的路径就是 l1 -> l3 -> l2,B链是 X -> E -> null -> A -> E ,路径是 l2 -> l3 -> l1,如果有交点的话,那么此时会走到一起。

所以做法就是

  • 如果 PA 到了末尾,则 PA = headB 继续遍历
  • 如果 PB 到了末尾,则 PB = headA 继续遍历
  1. 如果上面两个指针经过遍历能走到一起,说明是有交点,都各自走到最后为 null 则没有交点返回 null, 此时其实就是两个指针交换都会走到最后,走过的路径就都是 (长链 + 短链)的和, 就是他走过的路,你再走一遍,都走到对方的 null, 那么两人走过路径就是两段路的和

写法实现

var getIntersectionNode = function(headA, headB) {
    if (!headA || !headB) {
        return null
    }
    let [PA, PB] = [headA, headB]
    // 要么有交点,要么都是 null
    while (PA !== PB) {
        PA = PA === null ? headB : PA.next;
        PB = PB === null ? headA : PB.next;
    }
    return PA
};

117. 最长回文子串 (longest-palindromic-substring)

标签

  • 字符串
  • 中等

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

给你一个字符串 s,找到 s 中最长的回文子串

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:

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

示例 3:

输入:s = "a"
输出:"a"

基本思路

遍历每一个位置,使其作为『中心』并分奇偶讨论

奇偶讨论

  • 回文子串长度为奇数(如aba,中心是b
  • 回文子串长度为偶数(如cbbd,中心是b,b

写法实现

function longestPalindrome(s) {
    let res = ''

    // 传入中心(左右)坐标,返回以s[l]和s[r]为中心的最长回文串
    const longestPS = (l, r) => {
        // 左右不能超边界, 相同情况向两边扩散
        while (l >= 0 && r < s.length && s[l] === s[r]) {
            l--;
            r++;
        }
        return s.substring(l + 1, r);
    }

    // 遍历每一个位置,使其作为『中心』并分奇偶讨论
    for (let i = 0; i < s.length; i++) {
        // 奇数中心最长串, i 作为坐标,技术中间是一个坐标
        let oddStr = longestPS(i, i)
        // 偶数中心最长串
        let evenStr = longestPS(i, i+1)
        
        // 找出最长回文即可
        if (oddStr.length > evenStr.length) {
            // 奇数的大
            res = res.length > oddStr.length ? res : oddStr
        } else {
            res = res.length > evenStr.length ? res : evenStr
        }
    }
    return res
}

console.log(longestPalindrome('babad')) // aba
console.log(longestPalindrome('cbbd')) // bb

另外向大家着重推荐下这个系列的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列

今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 点击此处交个朋友 Or 搜索我的微信号infinity_9368,可以聊天说地 加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我 presious tower shock the rever monster,我看到就通过,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧

参考