Quick start ring linked list to solve Joseph problem

Posted by JonathanV on Thu, 13 Jan 2022 09:54:28 +0100

The idea of this paper is as follows:
1: What is a circular linked list and where is it used?
2: How to construct a ring linked list
3: Double pointer to solve the problem of circular linked list
4: Summary
5: Share songs
Note that this article only talks about the circular linked list composed of single linked list

What is a circular linked list

First of all, we can review what is a single linked list. We can learn a circular linked list better than a gourd.
The single linked list is about this long:

It is easy to see that it is probably a line led by the head node, and the head and tail are not connected.
Then the circular linked list is just to string the beginning and end. It is about as long as this:

The difference between a circular linked list and a single linked list is their connection structure. In fact, a two-way linked list can also form a circular linked list. In the future, we'll talk about it in detail. We'll eat rice one mouthful at a time.

How to construct a ring linked list

Build rules:
1: The first and last nodes are connected together
2: The node is a single linked list node
3: Double pointer, an auxiliary pointer helper and a first pointer.
4: First create the first node and let the first point to the node to form a ring
5: After each additional node, it will be added to the ring.

First, explain the simple situation:
1: Add linked list
First show an initial situation:

At this time, we set the pointer, connect itself end to end, and add an auxiliary pointer. When adding the pointer later, the first point to the latest. At this time, the auxiliary pointer stays at the last node before and can connect to the new node.

Now suppose you add a linked list:
a: Initial situation

b: Then the pointer starts pointing to the build:
1: (process start) the first pointer always points to the head linked list to facilitate the new linked list to point to the first pointer
2: The auxiliary pointer first connects the pointed list to the new list (process q), and then moves to the new list (process w)
When you reach process q:

When walking to process w:

The linked list structure code is as follows:

public class people {
    private int id;
    private String name;
    private people next;

    public people(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public people getNext() {
        return next;
    }

    public void setNext(people next) {
        this.next = next;
    }
}

Code for building circular linked list:

public class CircleSingleLInkedList {
    public static void main(String[] args) {
        CircleSingleLInkedList list =new CircleSingleLInkedList();
        list.addpeople(6);
        list.showPeo();
    }
 private people first =new people(-1,"-1");//It doesn't matter what number is assigned here. The correct value will be assigned again later
    //Add linked list
    public void addpeople(int peos){
        if(peos<1){
            System.out.println("peos The value of is not canonical");
            return;
        }
        people curpeo =null;//Auxiliary pointer to help build a circular linked list
        for(int i=1;i<= peos;i++){
            people peo = new people(i,"w"+i);
            if(i==1){   //The first linked list should be specially treated to form a ring first!
                first=peo;
                first.setNext(first);//Form a ring
                curpeo=first;//Let the auxiliary pointer point to the first person
            }else {
                curpeo.setNext(peo);//The last previous node connects to the new node
                peo.setNext(first);//The new node connects the first node and reconstructs the ring
                curpeo=peo;//The last auxiliary pointer points to the last node
            }
        }
    }
    //Traverse circular linked list
    public void showPeo(){
        if(first==null){
            System.out.println("No data");
            return;
        }
        //When traversing the node, the first pointer does not move and is completed using the auxiliary node
        people peo= first;
        while (true){
            System.out.println("Linked list"+peo.getId());
            if(peo.getNext()==first){
                System.out.println("Traversal complete");
                break;
            }
            peo=peo.getNext();//Auxiliary pointer backward
        }
    }
}

result:

Double pointer to solve the problem of circular linked list

Classic case, Joseph problem.
Joseph question:
After the Romans occupied jotapat, 39 Jews hid in a cave with Josephus and his friends. 39 Jews decided that they would rather die than be caught by the enemy, so they decided to commit suicide. 41 people lined up in a circle, counting from the first person. Every time they counted to the third person, they had to commit suicide, and then counting again from the next one, Until everyone committed suicide.
Use the circular linked list to solve or array is also OK. Here is the double pointer solution of the circular linked list. I feel it is simpler than the fast and slow pointer.
If you understand the process above, you should understand it here, so give the code directly. If you don't understand anything, you can see the above, which should be mentioned.
The code is as follows:

public class CircleSingleLInkedList {


    public static void main(String[] args) {
        CircleSingleLInkedList list =new CircleSingleLInkedList();
        list.addpeople(5);
        list.showPeo();
        list.killpeo(1,2,5);
    }
    private people first =new people(-1,"-1");//It doesn't matter what number is assigned here. The correct value will be assigned again later
    //Add linked list
    public void addpeople(int peos){
        if(peos<1){
            System.out.println("peos The value of is not canonical");
            return;
        }
        people curpeo =null;//Auxiliary pointer to help build a circular linked list
        for(int i=1;i<= peos;i++){
            people peo = new people(i,"w"+i);
            if(i==1){
                first=peo;
                first.setNext(first);//Form a ring
                curpeo=first;//Let the auxiliary pointer point to the first person
            }else {
                curpeo.setNext(peo);//The last previous node connects to the new node
                peo.setNext(first);//The new node connects the first node and reconstructs the ring
                curpeo=peo;//The last auxiliary pointer points to the last node
            }
        }
    }

    //Traverse circular linked list
    public void showPeo(){
        if(first==null){
            System.out.println("No data");
            return;
        }

        //When traversing the node, the first pointer does not move and is completed using the auxiliary node
        people peo= first;
        while (true){
            System.out.println("Linked list"+peo.getId());
            if(peo.getNext()==first){
                System.out.println("Traversal complete");
                break;
            }
            peo=peo.getNext();//Auxiliary pointer backward
        }
    }
    //startId: indicates the number of people starting from; countNum: indicates how many times to count; Num: indicates how many people were there at first
    public void killpeo(int startId,int countNum,int nums){
        if(first==null||startId<1||startId>nums){
            System.out.println("If you dare to tease us, I'll kill you first");
            return;
        }
        //Auxiliary pointer to help Jews commit suicide
        people helper =first;
        while(true){
            if(helper.getNext()==first){  //To the Last Jew
              break;
            }
            helper=helper.getNext();
        }
        for(int k=0;k<startId-1;k++){//First, move the first and helper pointers k-1 times. At this time, the first pointer just points to the person with the number of startId, and the auxiliary pointer is one bit in front of it
            first=first.getNext();
            helper=helper.getNext();
        }
        //When you start counting, let the first and helper pointers move n-1 times at the same time, and then commit suicide
        while (true){
            if(helper==first){//There is only one person left in the circle
                break;
            }
            for(int l=0;l<countNum-1;l++){
                first=first.getNext();
                helper=helper.getNext();
            }
            System.out.println("The first"+first.getId()+"The Jews committed suicide");
            //Remove the suicidal person from the circle
            first=first.getNext();
            helper.setNext(first);
        }
        System.out.println("The last person who committed suicide was the number"+first.getId());
    }

}

result:

summary

The circular linked list should understand the intermediate process and pointer transformation. I feel that I have gained a lot. The thinking method of double pointer is applied in many places. It has good learning significance. Pay attention to the pointing of pointer when learning.

Share songs

10:30 at the airport
-Tao Zhe
Why I like it: Tao Zhe is one of my favorite singers. I like all his songs and like listening to his whole album. This song is really a direct God. I like this album so much. I will start listening to the first song of the album directly by high-speed rail or train subway. The cover of this album is also my wechat avatar hh.

Topics: Java Algorithm data structure linked list