一道算法题目的思考
2015-04-10 00:00
330 查看
摘要: 最近看到关于环的算法题觉得很有意思,于是思考了一会,现在分几步把解法展示出来.
问题1:如何检测一个单链表有环.
问题2:一个有环的单链表找出环的入口.
问题3:两个无环单链表有一个结点相交,找出这个交点.
最近看到关于环的算法题觉得很有意思,于是思考了一会,现在分几步把解法展示出来.
问题1:如何检测一个单链表有环.
设两个指针,p=head,q=head,从头结点开始,每次p = p.next , q= q.next.next ,如果能找到一点p==q就说明这个有环.
问题2:一个有环的单链表找出环的入口.
如图所示,设置3个变量,根据第一次相遇时,q走的距离是p的两倍,可以列出一个方程等式, 2*(a+b) =a+2b+c,最后可以简化成 a = c.那么从第一次相遇的焦点到圆环的起始点和从head到圆环的起始点实际上结点数一样多,这样就可可以通过循环判断来完成.p=head , q=第一次相遇点. while(p!= q) {p=p.next ; q=q.next} 最终找到圆环的起点.
附上代码:
问题3:两个无环单链表有一个结点相交,找出这个交点.
最烂的解法:
循环H1的结点,H1的每个结点与H2的所有结点对比,时间复杂度是O(n*m)
最简单的解法:
找到H1的长度m,找到H2的长度n.较长的结点先移动m-n的长度,然后遍历循环两个链表,结束的条件是p.next=q.next 时间复杂度是O().
最方便的解法:
把H1链表结点依次放到HashSet中,然后再把H2链表结点依次放入HashSet中,直到无法放入的时候就找到这个相交的节点了.
最优雅的解法:
把H1最后的结点指向H1的头部.然后就把问题转换成问题2了.
问题1:如何检测一个单链表有环.
问题2:一个有环的单链表找出环的入口.
问题3:两个无环单链表有一个结点相交,找出这个交点.
最近看到关于环的算法题觉得很有意思,于是思考了一会,现在分几步把解法展示出来.
问题1:如何检测一个单链表有环.
设两个指针,p=head,q=head,从头结点开始,每次p = p.next , q= q.next.next ,如果能找到一点p==q就说明这个有环.
问题2:一个有环的单链表找出环的入口.
如图所示,设置3个变量,根据第一次相遇时,q走的距离是p的两倍,可以列出一个方程等式, 2*(a+b) =a+2b+c,最后可以简化成 a = c.那么从第一次相遇的焦点到圆环的起始点和从head到圆环的起始点实际上结点数一样多,这样就可可以通过循环判断来完成.p=head , q=第一次相遇点. while(p!= q) {p=p.next ; q=q.next} 最终找到圆环的起点.
附上代码:
public class FindFrstCircleNode { public static void main(String[] args) { Node<Integer> head = new Node<Integer>(1); Node<Integer> n1 = new Node<Integer>(2); Node<Integer> n2 = new Node<Integer>(3); Node<Integer> n3 = new Node<Integer>(4); Node<Integer> n4 = new Node<Integer>(5); Node<Integer> n5 = new Node<Integer>(6); Node<Integer> n6 = new Node<Integer>(7); Node<Integer> n7 = new Node<Integer>(8); Node<Integer> n8 = new Node<Integer>(9); Node<Integer> n9 = new Node<Integer>(10); head.next = n1; n1.next = n2; n2.next = n3; n3.next = n4; n4.next = n5; n5.next = n6; n6.next = n7; n7.next = n8; n8.next = n9; n9.next = n5; FindFrstCircleNode ffcn = new FindFrstCircleNode(); Node<Integer> p = ffcn.getFirstCircleNode(head); System.out.println(p.data); } public Node<Integer> getFirstCircleNode(Node<Integer> head) { Node<Integer> p = head; Node<Integer> q = head; int count = 0; while (count == 0 || p != q) { p = p.next; q = q.next.next; count++; } p = head; while (p != q) { p = p.next; q = q.next; } return p; } static class Node<T> { T data; Node<T> next; public Node() { super(); } public Node(T data) { super(); this.data = data; } } }
问题3:两个无环单链表有一个结点相交,找出这个交点.
最烂的解法:
循环H1的结点,H1的每个结点与H2的所有结点对比,时间复杂度是O(n*m)
最简单的解法:
找到H1的长度m,找到H2的长度n.较长的结点先移动m-n的长度,然后遍历循环两个链表,结束的条件是p.next=q.next 时间复杂度是O().
最方便的解法:
把H1链表结点依次放到HashSet中,然后再把H2链表结点依次放入HashSet中,直到无法放入的时候就找到这个相交的节点了.
最优雅的解法:
把H1最后的结点指向H1的头部.然后就把问题转换成问题2了.
相关文章推荐
- POJ1018 DP 一道自己独立思考出的DP题目 兼 12月份算法学习小结[更新]
- 每天一道算法题目(20)——复杂链表的拷贝
- 一道题目引发的多角度思考
- 每天一道算法题目(20)——复杂链表的拷贝
- 一道算法题,引发的思考
- 附上一道题目,一下子还没想到答案,大家有兴趣的思考下哈
- 一道简单题目的复杂算法
- 一道多路归并算法分析的题目
- 如何找出数组中第二大的数?(一道面试算法题的思考)
- 一道面试题目引发的思考
- 听来的一道算法题目
- 一道面试题目引发的思考
- 一道原生js题目引发的思考(鼠标停留区块计时)
- 一道面试题目引发的思考
- 一道算法题目
- 一道socket题目引发的思考
- 每天一道算法题目——最大公约数
- LeetCode上面一道算法题目:79. Word Search
- 算法题——一道数字组合的题目的求解
- 请教一道算法题目