您的位置:首页 > 其它

Cracking the coding interview--Q4.6

2014-11-17 20:26 344 查看
原文:

Design an algorithm and write code to find the first common ancestor of two nodes in a binary tree. Avoid storing additional nodes in a data structure. NOTE: This is not necessarily a binary search tree.

译文:

写程序在一棵二叉树中找到两个结点的第一个共同祖先。不允许存储额外的结点。注意: 这里不特指二叉查找树。

若使用额外的存储空间,最简单的方式就是对于一个结点向父节点进行遍历,直至根结点。可以考虑存储为hash,然后对另一个结点向父节点进行遍历,同时和第一个结点的父节点,所组成的hash集合进行比较,第一个相同的结点即为二者的共同祖先;

若不能使用额外的存储空间,则只能是不断的取一个节点的父节点,然后同另外一个节点的所有父节点进行比较,直到根节点;

另外如果节点没有父指针,那么则需要从根节点开始遍历,依次判断每个节点,是否可以到达问题中的两个节点。找到最后一个这样的节点即可

代码如下:

1、如果结点可以记录父亲结点信息,并可以借助外部存储空间

/**
* @param p
* @param q
* @return
*
* 如果结点可以记录父亲结点信息,并可以借助外部存储空间,
* 则可以使p的所有父亲结点记录在hashset中,然后一次遍历q的父亲结点,每个父节点一次与hashset中的结点比较,
* 相同即为最近的相同父亲结点
*
*/
public static Node_4_6 findCommonParent(Node_4_6 p, Node_4_6 q) {
if(p ==null || q ==null) {
return null;
}
HashSet<Node_4_6> set = new HashSet<Node_4_6>();
while(p.parent != null) {
set.add(p.parent);
p = p.parent;
}
while(q.parent != null) {
q = q.parent;
if(set.contains(q)) {
break;
}
}
if(q != null) {
return q;
} else {
return null;
}
}

2、如果结点可以记录父亲结点信息,不可以借助外部存储空间

/**
* @param p
* @param q
* @return
*
* 如果结点可以记录父亲结点信息,不可以借助外部存储空间,
* 则可以遍历p的所有父亲结点,然后每次遍历一个p的父亲结点则依次遍历q的父亲结点,直到找到相同结点存在,
* 相同即为最近的相同父亲结点
*
*/
public static Node_4_6 findCommonParent2(Node_4_6 p, Node_4_6 q) {
if(p ==null || q ==null) {
return null;
}
while(p.parent != null) {
p = p.parent;
while(q.parent != null) {
q = q.parent;
if( p == q) {
return p;
}
}
}
return null;
}

3、如果结点没有引用父亲结点,并且同时不能使用额外的存储空间

/**
* @param head
* @param p
* @param q
* @return
*
* 如果结点没有引用父亲结点,并且同时不能使用额外的存储空间,
* 则只能从head结点一次遍历结点信息,并且每次遍历结点判断当前结点是否同时为p,q的父结点
* 并且还需要判断是否最近
*
*/
public static void findCommonParent3(Node_4_6 head, Node_4_6 p, Node_4_6 q) {
if(p ==null || q ==null || head == null) {
return;
}
if(head != null && head!=p && head!=q && father(head, p) && father(head, q)) {
ancestor = head;
findCommonParent3(head.lchild, p, q);
findCommonParent3(head.rchild, p, q);
}
}

/**
* @param head
* @param node
* @return
*
* 判断当前结点node是否是head结点的子节点
* 即head是否为node的祖先结点
*
*/
public static boolean father(Node_4_6 head, Node_4_6 node) {
if(head == null) {
return false;
} else if(node == head) {
return true;
} else {
return father(head.lchild, node) || father(head.rchild, node);
}
}

总代码如下:

package chapter_4_TreesandGraphs;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Stack;

class Node_4_6 {
public int data;
public Node_4_6 lchild;
public Node_4_6 rchild;
public Node_4_6 parent;
}

public class Question_4_6 {
private static Node_4_6 p, q;
private static Node_4_6 ancestor;

public static void insertTreeNode(Node_4_6 curNode, Node_4_6 node) {
if(node.data < curNode.data) {
if(curNode.lchild != null) {
insertTreeNode(curNode.lchild, node);
} else{
curNode.lchild = node;
node.parent = curNode;
}
} else {
if(curNode.rchild != null) {
insertTreeNode(curNode.rchild, node);
} else {
curNode.rchild = node;
node.parent = curNode;
}
}
}

public static void createTree(Node_4_6 head, int array[]) {
int len = array.length;
int curIndex = 1;
while(curIndex < len) {
Node_4_6 node = new Node_4_6();
node.data = array[curIndex];
if(node.data == 1) {
p = node;
System.out.println("set p.data = " + node.data);
}
if(node.data == 5) {
q = node;
System.out.println("set q.data = " + node.data);
}
node.lchild = null;
node.rchild = null;
insertTreeNode(head, node);
curIndex ++;
}
}

public static void postOrderTraverce(Node_4_6 head) {
Stack<Node_4_6> stack = new Stack<Node_4_6>();
stack.push(head);
Node_4_6 node;
Node_4_6 preNode = null;
while(!stack.empty()) {
node = stack.peek();
if(node.lchild==null && node.rchild==null ||
(preNode!=null && (node.lchild == preNode || node.rchild == preNode))) {
System.out.print(" " + node.data + " ");
stack.pop();
preNode = node;
} else {
if(node.rchild != null) {

4000
stack.push(node.rchild);
}
if(node.lchild != null) {
stack.push(node.lchild);
}
}
}
}

/**
* @param p
* @param q
* @return
*
* 如果结点可以记录父亲结点信息,并可以借助外部存储空间,
* 则可以使p的所有父亲结点记录在hashset中,然后一次遍历q的父亲结点,每个父节点一次与hashset中的结点比较,
* 相同即为最近的相同父亲结点
*
*/
public static Node_4_6 findCommonParent(Node_4_6 p, Node_4_6 q) {
if(p ==null || q ==null) {
return null;
}
HashSet<Node_4_6> set = new HashSet<Node_4_6>();
while(p.parent != null) {
set.add(p.parent);
p = p.parent;
}
while(q.parent != null) {
q = q.parent;
if(set.contains(q)) {
break;
}
}
if(q != null) {
return q;
} else {
return null;
}
}

/**
* @param p
* @param q
* @return
*
* 如果结点可以记录父亲结点信息,不可以借助外部存储空间,
* 则可以遍历p的所有父亲结点,然后每次遍历一个p的父亲结点则依次遍历q的父亲结点,直到找到相同结点存在,
* 相同即为最近的相同父亲结点
*
*/
public static Node_4_6 findCommonParent2(Node_4_6 p, Node_4_6 q) {
if(p ==null || q ==null) {
return null;
}
while(p.parent != null) {
p = p.parent;
while(q.parent != null) {
q = q.parent;
if( p == q) {
return p;
}
}
}
return null;
}

/**
* @param head
* @param p
* @param q
* @return
*
* 如果结点没有引用父亲结点,并且同时不能使用额外的存储空间,
* 则只能从head结点一次遍历结点信息,并且每次遍历结点判断当前结点是否同时为p,q的父结点
* 并且还需要判断是否最近
*
*/
public static void findCommonParent3(Node_4_6 head, Node_4_6 p, Node_4_6 q) {
if(p ==null || q ==null || head == null) {
return;
}
if(head != null && head!=p && head!=q && father(head, p) && father(head, q)) {
ancestor = head;
findCommonParent3(head.lchild, p, q);
findCommonParent3(head.rchild, p, q);
}
}

/**
* @param head
* @param node
* @return
*
* 判断当前结点node是否是head结点的子节点
* 即head是否为node的祖先结点
*
*/
public static boolean father(Node_4_6 head, Node_4_6 node) {
if(head == null) {
return false;
} else if(node == head) {
return true;
} else {
return father(head.lchild, node) || father(head.rchild, node);
}
}

public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
String string = scanner.nextLine();
// 7 10 1 3 6 5 4 2 8
String strs[] = string.split(" ");
int array[] = new int[strs.length];
for(int i=0; i<array.length; i++) {
array[i] = Integer.parseInt(strs[i]);
}

Node_4_6 head = new Node_4_6();
head.data = array[0];
head.lchild = null;
head.rchild = null;

createTree(head, array);

postOrderTraverce(head);
System.out.println("");

Node_4_6 commonParent = findCommonParent(p, q);
if(commonParent == null) {
System.out.println("error!不存在");
} else {
System.out.println("common least parent is : " + commonParent.data);
}

Node_4_6 commonParent2 = findCommonParent2(p, q);
if(commonParent2 == null) {
System.out.println("error!不存在");
} else {
System.out.println("common least parent is : " + commonParent.data);
}

findCommonParent3(head, p, q);
if(ancestor == null) {
System.out.println("error!不存在");
} else {
System.out.println("common least parent is : " + ancestor.data);
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法