链表(List)
定义
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
实现
1 2 3 4
| function ListNode(value) { this.value = value; this.nextNode = null; }
|
应用
236.二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
1 2 3 4 5 6 7
| 3 / \ 5 1 / \ / \ 6 2 0 8 / \ 7 4
|
示例 1:
1 2 3
| 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出: 3 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
|
示例 2:
1 2 3
| 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出: 5 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
|
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
var lowestCommonAncestor = function (root, p, q) { function setNodeList(node) { let list = [node]; while (node && node.father) { list.unshift(node.father); node = node.father; } return list }
let nodeStack = [root]; let nodeListP = undefined; let nodeListQ = undefined;
while (nodeStack.length) { let node = nodeStack.pop(); if (node.right) { nodeStack.push(node.right); node.right.father = node; } if (node.left) { nodeStack.push(node.left); node.left.father = node; } if (node.val === q.val) { nodeListQ = setNodeList(node); } if (node.val === p.val) { nodeListP = setNodeList(node); } if (nodeListP && nodeListQ) { break; } } for (let i = 0; i < Math.min(nodeListP.length, nodeListQ.length); i++) { if (!nodeListP[i + 1] || !nodeListQ[i + 1] || nodeListP[i + 1].val !== nodeListQ[i + 1].val) { return nodeListP[i]; } } return null; };
|