using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LowestCommonAncestorWithParent { class Program { static void Main(string[] args) { var node1 = new Node(1); node1.left = new Node(2); node1.left.left = new Node(3); node1.left.right = new Node(4); node1.left.right.right = new Node(5); node1.left.parent = node1; node1.left.left.parent = node1.left; node1.left.right.parent = node1.left; node1.left.right.right.parent = node1.left.right; var test = new Program(); var LCA = test.LowestCommonAncestor(node1.left.left, node1.left.right.right); Debug.Assert(LCA.val == 2); } public class Node { public int val; public Node left; public Node right; public Node parent; public Node(int value) { val = value; } } /// <summary> /// node3->node2->node1->node5->node4->node2 /// node5->node4->node2->node1->node3->node2 /// By observing the above two linked list, two linked list meet at LCA - node2 /// node3 will go up it's parent node, until the root node and continue to travel to node5 /// node5 will go up it's parent node, untilt the root node and continue to travel to node3 /// Space complexity is O(1) /// </summary> /// <param name="p"></param> /// <param name="q"></param> /// <returns></returns> public Node LowestCommonAncestor(Node p, Node q) { if (p == null || q == null) return null; var copyP = p; var copyQ = q; while (copyP != copyQ) { if (copyP.parent == null) { copyP = q; } else { copyP = copyP.parent; } if (copyQ.parent == null) { copyQ = p; } else { copyQ = copyQ.parent; } } return copyP; } } }