Java--算法--链表
- 链表:
-
-
快慢指针:
-
常见面时题:
-
-
-
package com.model.linkedlsit; /** * @Description:测试类 * @Author: 张紫韩 * @Crete 2021/8/17 15:34 * 给定一个链表list,和一个值target,将链表中小于于target的放在左面,等于target的放在中间,大于target的放在右面 * 返回新的链表 */ public class LinkedListDemo02 { public static void main(String[] args) { Node node1=new Node(3); Node node2=new Node(1); Node node3=new Node(1); Node node4=new Node(2); Node node5=new Node(0); Node node6=new Node(5); node1.next=node2; node2.next=node3; node3.next=node4; node4.next=node5; node5.next=node6; Node node = buildList(node1, 2); System.out.println(node); } public static Node buildList(Node head,int target){ if (head==null||head.next==null){ return head; } Node sH=null; Node sT=null; Node eH=null; Node eT=null; Node mH=null; Node mT=null; Node temp=head; while (head!=null){ temp=temp.next; head.next=null; if (head.val==target){ if (eH==null){ eH=head; eT=head; }else { eT.next=head; eT=eT.next; } }else if (head.val<target){ if (sH==null){ sH=head; sT=head; }else { sT.next=head; sT=sT.next; } }else { if (mH==null){ mH=head; mT=head; }else { mT.next=head; mT=mT.next; } } head=temp; } if (sH!=null){ if (eH!=null){ sT.next=eH; eT.next=mH; }else { sT.next=mH; } }else { if (eH!=null){ sH=eH; eT.next=mH; }else { sH=mH; } } return sH; } }
-
-
-
-
package com.model.linkedlsit; import java.util.HashSet; import java.util.Set; /** * @Description:测试类 * @Author: 张紫韩 * @Crete 2021/8/17 17:03 * 给定一个链表,如果有换就返回链表的第一个入环节点 * 如果没有环就返回null */ public class LinkedListDemo03 { public static void main(String[] args) { Node node1 = new Node(1); Node node2 = new Node(2); Node node3 = new Node(3); Node node4 = new Node(4); Node node5 = new Node(5); node1.next = node2; node2.next = node3; node3.next = node4; node4.next = node5; node5.next = node3; System.out.println(getFirstNode(node1).val); System.out.println(getLoopNode(node1).val); } // 如果有环就返回第一个入环节点,否则返回null // 1.使用set的方式 public static Node getFirstNode(Node head) { Set<Node> hashSet = new HashSet<>(); while (head != null) { if (hashSet.contains(head)) { return head; } hashSet.add(head); head = head.next; } return null; } // 2.使用快慢指针,追击问题解决 // slow从第二个节点开始,一次走一步 // fast从第三个节点开开始,一次走两步 // 直到slow和fast到达同一个位置,fast移动到head,slow不动 // fast和slow都是一步一步的移动,当他们再次相遇的位置就是第一个入环的节点位置 public static Node getLoopNode(Node head) { if (head == null || head.next == null || head.next.next == null) { return null; } Node slow = head.next; Node fast = head.next.next; while (slow != fast) { slow = slow.next; if (fast.next != null && fast.next.next != null) { fast = fast.next.next; } else { return null; } } fast = head; while (fast != slow) { fast = fast.next; slow = slow.next; } return slow; } // 给你两个无环的链表,如果他们相交了就返回相交的第一个节点位置,如果没有相交就返回null public static Node noLoopIntersect(Node head1, Node head2) { if (head1 == null || head2 == null) { return null; } // 查看两个链表是否有重合的部分 Node temp1 = head1; Node temp2 = head2; int n = 0;//统计两个链表的差 while (temp1.next != null) { n++; temp1 = temp1.next; } while (temp2.next != null) { n--; temp2 = temp2.next; } if (temp1 != temp2) { return null; } Node cur1 = null;//链表交长的一个 Node cur2 = null; if (n > 0) { cur1 = head1; cur2 = head2; } else { cur2 = head1; cur1 = head2; } // 使长链表先移动n个长度,然后长链表锻炼表一起移动 // 两个链表相等的位置就是第一个相交的位置 n = Math.abs(n); while (n > 0) { cur1 = cur1.next; n--; } while (cur1 != cur2) { cur1 = cur1.next; cur2 = cur2.next; } return cur1; } // 给你两个有环的链表,和两个链表的第一个入环的节点位置,如果有相交返回他们第一个相交界点的位置,如果没有相交返回null // 三种情况 // 1.没有共同的节点 // 2.有共同的节点,有共同的环,且入环地点相等 // 3.有共同的节点,有共同的环,但是入环节点不同 public static Node loopIntersect(Node head1, Node loop1, Node head2, Node loop2) { if (head1 == null || head2 == null) { return null; } // 入环节点相同 if (loop1 == loop2) { Node temp1 = head1; Node temp2 = head2; int n = 0; while (temp1 != loop1) { n++; temp1 = temp1.next; } while (temp2 != loop2) { n--; temp2 = temp2.next; } Node cur1 = null; Node cur2 = null; if (n > 0) { cur1 = temp1; cur2 = temp2; } else { cur1 = temp2; cur2 = temp1; } n = Math.abs(n); while (n > 0) { cur1 = cur1.next; n--; } while (cur1 != cur2) { cur1 = cur1.next; cur2 = cur2.next; } return cur1; } else { //入环节点不同 Node temp = loop1.next; while (temp != loop1) { if (temp == loop2) { return loop1; } temp = temp.next; } return null; } } // 给定两个链表可能有环也可能无环,可能相交也可能不相交,求出他们的第一个相交的位置,如果没有返回null public static Node getIntersectNode(Node head1, Node head2) { if (head1 == null || head2 == null) { return null; } // 获取到两个链表的第一个入环位置节点 Node loop1 = getLoopNode(head1); Node loop2 = getLoopNode(head2); if (loop1==null&&loop2==null){ return noLoopIntersect(head1, head2); } if (loop1!=null&&loop2!=null){ return loopIntersect(head1, loop1, head2, loop2); } return null; } }
-
-