ARTS_22

什么是 ARTS?

  1. 算法(Algorithm): 每周至少一道 LeetCode 算法题,加强编程训练和算法学习
  2. 阅读(Review): 阅读并点评至少一篇英文技术文章,提高英文水平
  3. 技巧 (Tip):学习至少一个技术技巧,总结、归纳日常工作中遇到的知识点
  4. 分享(Share):分析一篇有观点和思考的技术文章,建立影响力,输出价值观

时间周期
11月21日止11月28日

一:算法

leetCode题目地址:https://leetcode.cn/problems/intersection-of-two-linked-lists/

编写一个程序,找到两个单链表相交的起始节点。

前置知识

  • 链表
  • 双指针

解法一:哈希法
有A,B这两条链表,先遍历其中一个,比如A链表,并将A中的所有节点存入哈希表。
遍历B链表,检查节点是否在哈希表中,第一个存在的就是相交节点

  • 伪代码
// 存放A链表的所有节点的地址
date = new Set()

while A 不为空 {
    哈希表中添加A链表当前节点
    A指针向后移动
}

while B不为空 {
    if 如果哈希表中含有B链表当前节点
        return B
    B指针向后移动
}

// 两条链表没有相交点
return null

JavaScript代码

/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */

let getIntersectionNode = function (headA, headB) {
  let data = new Set()

  while (headA !== null) {
    data.add(headA)
    headA = headA.next
  }

  while (headB !== null) {
    if (data.has(headB)) {
      return headB
    }
    headB = headB.next
  }

  return null
};

复杂度分析

  • 空间复杂度: O(N)
  • 时间复杂度: O(N)

解法二:双指针

  • 例如使用a,b两个指针分别指向A,B这两条链表,两个指针相同的速度向后移动
  • 当a到达链表的尾部时,重定位到链表B的头节点
  • 当b到达链表的尾部时,重定位到链表A的头节点
  • a,b指针相遇的点为相交的起始节点,否则没有相交点
007S8ZIlly1gfig7vsvwhj30bs05z3yl.jpg

为什么a,b指针相遇的点一定是相交的起始节点?我们证明一下:

  • 将两条链表按相交的起始节点继续截断,链表1为:A + C,链表2为:B + C
  • 当a指针将链表1遍历完后,重定位到链表B的头节点,然后继续遍历直至相交点(a指针遍历的距离为A+C+B)
  • 同理b指针遍历的距离为B+C+A

伪代码

a = headA
b = headB

while a,b指针不相等时 {
    if a指针为空时:
        a指针重定位到链表的B的头节点
  else:
        a指针向后移动一位
    
    if b指针为空时:
        b指针重定位到链表A的头节点
    else:
        b指针后移动一位
}

return a

JavaScript Code

let getIntersectionNode = function (headA, headB) {
  let a = headA
  let b = headB
  while (a != b) {
    if (a === null) {
      a = headB
    } else {
      a = a.next
    }

    if (b === null) {
      b = headA
    } else {
      b = b.next
    }
  }
  return a
};

Python Code:

class Solution:
   def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
    a, b = headA, headB
    while a != b:
      a = a.next if a else headB
      b = b.next if b else headA
    return a

Go Code:

func getIntersectionNode(headA, headB *ListNode) *ListNode {
  // a=A(a单独部分)+C(a相交部分); b=B(b单独部分)+C(b相交部分)
  // a+b=b+a=A+C+B+C=B+C+A+C
  a := headA
  b := headB

  for a !=b {
    if a == nil {
      a = headB
    } else {
      a = a.Next
    }

    if b == nil {
      b = headA
    } else {
      b = b.Next
    }
  }

  return a
}

算法思考:

  1. JavaScript无论是从时间复杂度,还是空间复杂度上来说,都不是最优解,真要追求极致性能,javaScript是真的不够用
  2. Python运行时间上最慢,但是空间上还是可以的
  3. 表扬一下Go,无论是空间,还是时间上,都是极其强悍的
444FDB79-A1B0-4878-8765-BB256B67EA82.png

二:阅读

Web 开发的未来是边缘网络

三:技巧

小黄鸭调试法
日记的作用

四:分享

《什么是高级工程师?》

分享理由:

  1. 有人带,有代码规范,1个足够聪明的小朋友在1年内就能写出很好的代码了,这时候,他和高级工程师的区别在哪里?文中给出了一个思路
  2. 高级工程师,这个title进入公司的人,写代码只是他的一部分工作,更多的工作是那些工程实践知识,那些经验比让他写具体的一个业务,对公司产生的价值更大

下面是我的翻译文章链接:https://www.jianshu.com/p/3bd94b5e10cb

你可能感兴趣的:(ARTS_22)