LeetCode 热题 HOT 100题解 (easy级别)(二)

简介: LeetCode 热题 HOT 100题解 (easy级别)

160.相交链表


https://leetcode-cn.com/problems/intersection-of-two-linked-lists


方法 1:暴力法


思路

对于链表 A 的每个节点,都去链表 B 中遍历一遍找看看有没有相同的节点。

复杂度

时间复杂度:O(M * N)O(M∗N), M, N 分别为两个链表的长度。 空间复杂度:O(1)O(1)。

var getIntersectionNode = function (headA, headB) {
  if (!headA || !headB) return null
  let pA = headA
  while (pA) {
    let pB = headB
    while (pB) {
      if (pA === pB) return pA
      pB = pB.next
    }
    pA = pA.next
  }
}


方法 2:哈希表


思路

先遍历一遍链表 A,用哈希表把每个节点都记录下来(注意要存节点引用而不是节点值)。 再去遍历链表 B,找到在哈希表中出现过的节点即为两个链表的交点。

复杂度

时间复杂度:O(M + N), M, N 分别为两个链表的长度。 空间复杂度:O(N),N 为链表 A 的长度。

var getIntersectionNode = function (headA, headB) {
  if (!headA || !headB) return null
  const hashmap = new Map()
  let pA = headA
  while (pA) {
    hashmap.set(pA, 1)
    pA = pA.next
  }
  let pB = headB
  while (pB) {
    if (hashmap.has(pB)) return pB
    pB = pB.next
  }
}


方法 3:双指针


如果链表没有交点

两个链表长度一样,第一次遍历结束后 pA 和 pB 都是 null,结束遍历 两个链表长度不一样,两次遍历结束后 pA 和 pB 都是 null,结束遍历

复杂度

时间复杂度:O(M + N) , M, N 分别为两个链表的长度。 空间复杂度:O(1)。

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} headA
 * @param {ListNode} headB
 * @return {ListNode}
 */
var getIntersectionNode = function (headA, headB) {
  if (!headA || !headB) return null
  let pA = headA,
    pB = headB
  while (pA !== pB) {
    pA = pA === null ? headB : pA.next
    pB = pB === null ? headA : pB.next
  }
  return pA
}


206.反转链表


var reverseList = function (head) {
  let prev = null
  cur = head
  while (cur) {
    const next = cur.next
    cur.next = prev
    prev = cur
    cur = next
  }
  return prev
}


方案 2


var reverseList = function (head) {
  let prev = null
  cur = head
  while (cur) {
    const next = cur.next
    cur.next = prev
    prev = cur
    cur = next
  }
  return prev
}


234.回文链表


https://leetcode-cn.com/problems/palindrome-linked-list

const isPalindrome = (head) => {
  const vals = []
  while (head) {
    // 丢进数组里
    vals.push(head.val)
    head = head.next
  }
  let start = 0,
    end = vals.length - 1 // 双指针
  while (start < end) {
    if (vals[start] != vals[end]) {
      // 理应相同,如果不同,不是回文
      return false
    }
    start++
    end-- // 双指针移动
  }
  return true // 循环结束也没有返回false,说明是回文
}


543.二叉树的直径


https://leetcode-cn.com/problems/diameter-of-binary-tree

方法 1
var diameterOfBinaryTree = function (root) {
  // 默认为1是因为默认了根节点自身的路径长度
  let ans = 1
  function depth(rootNode) {
    if (!rootNode) {
      // 如果不存在根节点,则深度为0
      return 0
    }
    // 递归,获取左子树的深度
    let left = depth(rootNode.left)
    // 递归,获取右子树的深度
    let right = depth(rootNode.right)
    /* 关键点1
        L+R+1的公式是如何而来?
        等同于:左子树深度(节点个数) + 右子树深度(节点个数) + 1个根节点
        便是这株二叉树从最左侧叶子节点到最右侧叶子节点的最长路径
        类似于平衡二叉树的最小值节点到最大值节点的最长路径
        之所以+1是因为需要经过根节点
         */
    // 获取该树的最长路径和现有最长路径中最大的那个
    ans = Math.max(ans, left + right + 1)
    /* 关键点2
        已知根节点的左右子树的深度,
        则,左右子树深度的最大值 + 1,
        便是以根节点为数的最大深度*/
    return Math.max(left, right) + 1
  }
  depth(root)
  // 由于depth函数中已经默认加上数节点的自身根节点路径了,故此处需减1
  return ans - 1
}
方法 2
function height(node) {
  //求树高
  if (!node) return 0
  return 1 + Math.max(height(node.left), height(node.right))
}
var diameterOfBinaryTree = function (root) {
  if (!root) return 0
  let tempH = height(root.left) + height(root.right)
  return Math.max(
    tempH,
    diameterOfBinaryTree(root.left),
    diameterOfBinaryTree(root.right)
  )
}


617.合并二叉树


https://leetcode-cn.com/problems/merge-two-binary-trees/

var mergeTrees = function (root1, root2) {
  if (root1 == null && root2) {
    return root2
  } else if (root2 == null && root1) {
    return root1
  } else if (root1 && root2) {
    root1.val = root1.val + root2.val
    //递归合并每一个节点
    root1.left = mergeTrees(root1.left, root2.left)
    root1.right = mergeTrees(root1.right, root2.right)
  }
  return root1
}

注:部分题解参考LeetCode最佳题解,有需要的同学可以自行去LeetCode官网查看。


目录
相关文章
|
6月前
|
算法 Java Go
【经典算法】LeetCode 67. 二进制求和(Java/C/Python3/Golang实现含注释说明,Easy)
【经典算法】LeetCode 67. 二进制求和(Java/C/Python3/Golang实现含注释说明,Easy)
86 2
|
6月前
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
65 2
|
6月前
|
存储 算法 Java
【经典算法】LeetCode 26. 删除有序数组中的重复项:(Java/C/Python3实现含注释说明,Easy)
【经典算法】LeetCode 26. 删除有序数组中的重复项:(Java/C/Python3实现含注释说明,Easy)
47 2
|
6月前
|
算法 Java Go
【经典算法】LeetCode 69. x 的平方根(Java/C/Python3/Golang实现含注释说明,Easy)
【经典算法】LeetCode 69. x 的平方根(Java/C/Python3/Golang实现含注释说明,Easy)
50 1
|
6月前
|
算法 Java Go
【经典算法】LeetCode 64. 最小路径和(Java/C/Python3/Golang实现含注释说明,Easy)
【经典算法】LeetCode 64. 最小路径和(Java/C/Python3/Golang实现含注释说明,Easy)
41 1
|
6月前
|
存储 算法 Java
【经典算法】LeetCode 136:只出现一次的数字(Java/C/Python3实现含注释说明,Easy)
【经典算法】LeetCode 136:只出现一次的数字(Java/C/Python3实现含注释说明,Easy)
42 1
|
6月前
|
算法 Java C语言
【经典算法】LeetCode 20:有效的括号(Java/C/Python3实现含注释说明,Easy)
【经典算法】LeetCode 20:有效的括号(Java/C/Python3实现含注释说明,Easy)
49 1
|
6月前
|
算法 安全 Java
【经典算法】LeetCode 21:合并两个有序链表Java/C/Python3实现含注释说明,Easy)
【经典算法】LeetCode 21:合并两个有序链表Java/C/Python3实现含注释说明,Easy)
41 1
|
6月前
|
算法 Java Go
【经典算法】LeetCode 392 判断子序列(Java/C/Python3/Go实现含注释说明,Easy)
【经典算法】LeetCode 392 判断子序列(Java/C/Python3/Go实现含注释说明,Easy)
74 0
|
6月前
|
算法 Java Go
【经典算法】LeetCode 1103 分糖果 II(Java/C/Python3实现含注释说明,Easy)
【经典算法】LeetCode 1103 分糖果 II(Java/C/Python3实现含注释说明,Easy)
91 0