从头遍历到末尾,再次从头遍历到中间处。O(L+L/2) =O(3L/2)
利用快慢指针原理:设置两个指针fast 和mid,都指向单链表的头节点。其中fast的移动速度是mid的2倍。当fast指向末尾节点的时候,mid正好就在中间了。O(L/2)
public static int void getMidNode(MyList L){ MyList fast,mid; fast = L.head; mid = L.head; while(fast.next != null){ if(fast.next.next!=null){ fast = fast.next.next; mid = mid.next; } else fast = fast.next; } return mid.data;}利用快慢指针原理,最后快慢指针相撞。
1. 有环时求环的长度 记录碰撞点P,slow、fast指针从该点出发,再次碰撞所走过的操作数就是环的长度s。 2. 找出环的连接点 有定理:碰撞点p到连接点的距离=头指针到连接点的距离,因此,分别从头结点,碰撞点开始走(相同的速度),相遇的地方就是连接点。 证明:
假设单链表的总长度为L,头结点到环入口的距离为a,环入口到快慢指针相遇的结点距离为x,环的长度为r,慢指针总共走了s步,则快指针走了2s步。另外,快指针要追上慢指针的话快指针至少要在环里面转了一圈多(假设转了n圈加x的距离),得到以下关系:s = a + x;2s = a + nr + x;=>a + x = nr;=>a = nr - x;由上式可知:若在头结点和相遇结点分别设一指针,同步(单步)前进,则最后一定相遇在环入口结点,搞定!附图:3. 求带环链表的长度 问题2中已经求出连接点距离头指针的长度,加上问题1中求出的环的长度,二者之和就是带环单链表的长度
法1:假设第一条和第二条链表的长度为len1,len2,然后找出较长的链表,并让其从|len1- len2|,开始遍历,逐个比较两个链表的值。 法2:将两个链表压栈,并比较两个栈出来的数据,直到两个数据不同时,就可以判断相交点。
问题的延伸: 如果原来的两个链表中有环怎么处理? a.创建第一个链表的地址hash,直到所有节点都存入(终结条件就是添加新的hash时,hash表中已经存在了)。遍历第二个链表,并hash,判断是否在表中。 b.分三种情况:两条head都不在环上,都在环上,有一个在环上,这三种方式都可以用快慢指针进行判断。
新闻热点
疑难解答