算法与数据结构面试题(7)-链表“香蕉”问题

题目


微软亚院之编程判断俩个链表是否相交 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交。 为了简化问题,我们假设俩个链表均不带环。
问题扩展:
1.如果链表可能有环列?
2.如果需要求出俩个链表相交的第一个节点?

解题思路


1.先了解一下什么是有环链表

2.查找判断是否相交的方法

3.求出列表相交的第一个节点。


解题步骤


1.有环链表


有环的链表指的是链表有环路,例如下面:A->B->C->D->B,这样遍历的时候B->C->D->B就形成一个环路一直循环。


环链表


上面的知识中讲解了如何判断单向链表是否含有环。有三种方式:


1.第一种方式很好理解,就是用散列表数据结构中来保存已遍历的节点,如果当前遍历的节点存在于上面的数据结构中,那说明存在环。 时间复杂度O(n)

2.指针反转:指能通过表尾部节点找到表头的链表。在有环的情况下,表指针会通过反转找到表头,那么遍历完成后,只需要判断最后一个节点是否是标头就行。时间复杂度为O(n),但是该方法破坏了表的结构,遍历结束后,需要还原。

3.快慢指针:fast指针移动2个位置,slow指针每次移动一个指针,如果在某一个位置中,快慢指针如果能相遇,说明有环。


2.是否相交


链表相交


1.直接法:循环遍历链表1种所有节点,然后再判断该节点是否存在于链表2种。时间复杂度O(n2).

2.利用计数。有点复杂,需要消化。

以节点地址遍历第一个链表,保存所有地址到一个hash表中

遍历第二个链表,判断当前节点的地址是否存在于上面的hash表中

如果存在,则有相交

时间复杂度O(n).

3.利用最后一个节点:如果相交的话,那么最后一个节点肯定是相同的。那么每个链表只需要遍历到最后一个节点,然后比较2个最后节点的地址是否相同就ok啊。时间复杂度O(n).


总结:判断是否有环用方法3,是否相交用方法2。求第一个相交节点也就方便许多。


代码


public class Banana {
	//保存相交节点
	LinkedListNode bananaNode = null;
	
	/**
	 * 判断链表是否有环
	 */
	public boolean isLoop(LinkedListNode node) {
		LinkedListNode fastNode;
		LinkedListNode slowNode;
		// 初始化快慢指针
		fastNode = node;
		slowNode = node;
		while (fastNode != null && fastNode.getNextNode() != null) {
			// fast指针每次前进2步
			fastNode = fastNode.getNextNode().getNextNode();
			// slow指针每次前进1步
			slowNode = slowNode.getNextNode();

			if (fastNode == slowNode) {
				return true;
			}

		}
		return false;
	}

	/**
	 * 判断链表是否相交
	 */
	public boolean isBanana(LinkedListNode node1, LinkedListNode node2) {
		// 首先判断链表是否存在环
		boolean isLoop1 = isLoop(node1);
		boolean isLoop2 = isLoop(node2);
		if (isLoop1) {
			System.out.println("链表1存在环");
		}
		if (isLoop2) {
			System.out.println("链表2存在环");
		}
		// 只有当两者都不存在环或者都存在环才有相交的可能性。
		List<Integer> hashList = new ArrayList<Integer>();
		
		if (isLoop1 == isLoop2) {
			// 遍历第一个链表
			while (node1 != null) {
				hashList.add(node1.hashCode());
				node1 = node1.getNextNode();
			}
			while (node2 != null) {
				if (hashList.contains(node2.hashCode())) {
					System.out.println("链表相交");
					bananaNode = node2;
					return true;
				}
				node2 = node2.getNextNode();
			}
		}

		return false;
	}

	public static void main(String[] args) {

	}

}


你可能感兴趣的:(数据结构,算法)