(Java data structure) linked list question

circular linked list

Determine whether there is a cycle in the linked list

leetcode
141. 环形链表

insert image description here

Similar to the problem of chasing and meeting, define the fast and slow pointers. If there is no ring, the fast pointer will go to null; if there is a ring, the fast and slow pointers will definitely meet in the ring.
Here comes the question, if the slow pointer moves one step at a time, should the fast pointer move two steps at a time? Or take 3 steps? 4 steps?

If each time the fast pointer walks 2 steps and the slow pointer walks 1 step, in the worst case, when the slow pointer just enters the ring, the fast pointer walks one more ring distance than the slow pointer, because each time the fast pointer walks more than the slow pointer 1 step, so the fast pointer can catch up with the slow pointer before the slow pointer reaches a circleinsert image description here

If there are only two nodes in the ring, if the fast pointer moves 3 steps each time and the slow pointer moves 1 step each time, then the fast and slow pointers can never meet
insert image description here

So set the fast pointer to take 2 steps at a time, and the slow pointer to take 1 step at a time, and the two pointers will definitely meet in the ring. If the slow pointer moves 1 step and the fast pointer moves 3/4/5... steps, the two pointers may not meet.

public class Solution {
    
    
    public boolean hasCycle(ListNode head) {
    
    
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null){
    
    
            slow=slow.next;
            fast=fast.next.next;
            if(fast==slow){
    
    
                return true;
            }
        }
        return false;
    }
}

Find the first node where the linked list starts entering the ring

leetcode
142. 环形链表 II

insert image description here

Suppose the distance from the starting position of the linked list to the entry point is X, the length of the ring is C, the distance from the encounter point to the entry point is Y, and the distance from the entry point to the encounter point is CY

Assume that the fast pointer meets when it travels N times more than the slow pointer, that is, the slow pointer travels X+CY, and the fast pointer travels X+C-Y+N C, because the speed of the fast pointer is twice that of the slow pointer, so within the same time , the distance traveled by the fast pointer is twice that of the slow pointer, that is, X+C-Y+N C=2*(X+CY), the solution is XY=(N-1)*C.
When N=1, X =Y
Then a pointer p1 can be defined at the starting point of the linked list, and a p2 can be defined at the meeting point. The two pointers take one step at a time, and finally meet at the loop entry point.
When N=2, p2 has to walk Y+C two pointers to meet at the loop entry point. When N>2, the two pointers can always meet at the end, but the time becomes longer

public class Solution {
    
    
    public ListNode detectCycle(ListNode head) {
    
    
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null){
    
    
            slow=slow.next;
            fast=fast.next.next;
            if(fast==slow){
    
    
                slow=head;
                while(slow!=fast){
    
    
                    slow=slow.next;
                    fast=fast.next;
                }
                return slow;
            }
        }
        return null;
    }
}

Linked list partition

牛客网
CM11 链表分割
现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

insert image description here

Example: Divide two areas with 30 as the boundary, the area <30, the area >30, and the area
<30 define 2 pointers bs, be. The area >30 defines 2 pointers as, ae. Then define a cur pointer, point to the head node of the linked list, and traverse the linked list. If cur.val<30, then the node pointed by cur is placed in the area <30. When the second element is placed in the <30 area, be goes backwards. Until cur goes to null, then be.next=as, the nodes in the front and back areas are connected.

There are pitfalls here: ① If all elements are >30, then be will always be null, and if be.next will report a null pointer exception. ②If the end node pointed by ae is not the end node in the original linked list, that is, ae.next!=null, it will cause an infinite loop of the linked list, so we need to manually set ae.next=null to empty. ③ This will cause new problems. If as=ae=null, ae.next will cause a null pointer exception

public class Partition {
    
    
    public ListNode partition(ListNode pHead, int x) {
    
    
        // write code here
        ListNode bs = null;
        ListNode be = null;
        ListNode as = null;
        ListNode ae = null;
        ListNode cur = pHead;
        while (cur != null) {
    
    
            if (cur.val < x) {
    
    
                if (bs == null) {
    
    
                    bs = be = cur;
                    cur = cur.next;
                }else{
    
    
                    be.next = cur;
                be = be.next;
                cur = cur.next;
                }
                
            } else {
    
    
                if (as == null) {
    
    
                    as = ae = cur;
                    cur = cur.next;
                } else {
    
    
                    ae.next = cur;
                    ae = ae.next;
                    cur = cur.next;
                }

            }
        }
        if (be == null) {
    
    
            return as;
        }
        be.next = as;
        if(ae!=null){
    
    
            ae.next = null;
        }
        return bs;
    }
}

Guess you like

Origin blog.csdn.net/qq_63983125/article/details/126923151