Java--算法--链表

  1. 链表:
    1.  

       

  2.  快慢指针:

  3. 常见面时题:

    1.  

       

       

    2.  

       

      1. 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;
        
        
        
            }
        
        
        }

         

    3.  

       

       

      1. 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;
            }
        }
    4.   

 

posted @ 2021-08-17 21:02  张紫韩  阅读(44)  评论(0编辑  收藏  举报