Data structure - singly linked list OJ question (second round)

Insert image description here


Preface

There are two practice questions this time!
It’s a little difficult, but I believe it won’t be difficult for everyone!

I will also give links to the two OJ questions, so everyone should try it quickly.


1. Return the first node where the linked list begins to enter the loop

Question link: OJ link
Insert image description here
Insert image description here

hint:

The number of nodes in the linked list ranges from [0, 104]
-105 <= Node.val <= 105.
The value of pos is -1 or a valid index in the linked list.

There are two analytical ideas for this question ~
Insert image description here
Insert image description here

Idea 1

Insert image description here
Code demo:

//解题方法一
struct ListNode *detectCycle(struct ListNode *head) {
    
    
    struct ListNode *move1=head;
    struct ListNode *move2=head;
    while(move1&&move2&&move2->next){
    
    //快慢指针移动
        move1=move1->next;
        move2=move2->next->next;
            if(move1==move2){
    
    {
    
    //找到相遇点
            struct ListNode *meet=move1;//meet从相遇点开始移动
            struct ListNode *move3=head;//move3从head开始移动
            while(meet!=move3){
    
    //两个指针同时移动找到起始点
                meet=meet->next;
                move3=move3->next;
            }
            return meet;
        }
    }
   
    return NULL;
}

Idea 2

Insert image description here

Tip: If you don’t know how to find common points, the previous blog will help you!
Blog link: Single linked list OJ question

Code demo:

//解题方法二
struct ListNode *detectCycle(struct ListNode *head) {
    
    
   struct ListNode *move1=head;
   struct ListNode *move2=head;
   while(move1&&move2&&move2->next){
    
    //快慢指针移动
        move1=move1->next;
        move2=move2->next->next;
        if(move1==move2){
    
    //找到相遇点
            struct ListNode *temp=move1;//保存相遇点位置
            move1=move1->next;//将move1变为第二链表起始点
            temp->next=NULL;//将相遇点的next置空
            struct ListNode *head1=head;
            struct ListNode *head2=move1;
            int len1=0,len2=0;
            while(head1!=NULL){
    
    //计算链表长度
                len1++;
                head1=head1->next;
            }
            while(head2!=NULL){
    
    
                head2=head2->next;
                len2++;
            }
            int k=abs(len1-len2);//得到两链表长度相减的绝对值
            //将longs指向较长的链表,shorts指向较短的链表
            struct ListNode *shorts=head;
            struct ListNode *longs=move1;
            if(len1>len2){
    
    
                shorts=move1;
                longs=head;
            }
            while(k--&&longs!=NULL){
    
    //较长的链表移动k位
                longs=longs->next;
            }
            if(k>0&&longs==NULL){
    
    
                return NULL;
            }
            while(shorts!=longs){
    
    //两链表同时遍历,找到第一个公共点
                shorts=shorts->next;
                longs=longs->next;
            }
            return longs;
         }
    }
    return NULL;
}

2. Return a deep copy of the linked list

Question link: OJ link
Insert image description here
Insert image description here
Insert image description here

hint:

0 <= n <= 1000
-104 <= Node.val <= 104
Node.random is null or points to a node in the linked list.

Problem-solving ideas:
Insert image description here
Insert image description here

code demo

struct Node* BuyNewnode(int x){
    
    //创建结点函数
    struct Node*newnode=(struct Node*)malloc(sizeof(struct Node));
    newnode->val=x;
    newnode->next=NULL;
    newnode->random=NULL;
    return newnode;
}
//查找random所在位置的函数
struct Node* findrandom(struct Node* head,struct Node* newhead,struct Node* random){
    
    
    struct Node*move1=head;
    struct Node*move2=newhead;
    while(move1!=random){
    
    
        move1=move1->next;
        move2=move2->next;
    }
    return move2;
}

struct Node* copyRandomList(struct Node* head) {
    
    
	struct Node*move=head;
    struct Node*newhead=NULL;
    struct Node*tail=NULL;
    while(move!=NULL){
    
    //将新建结点依次尾插到新链表中
         if(tail==NULL){
    
    
            struct Node*newnode= BuyNewnode(move->val);
            newhead=tail=newnode;
            move=move->next;
         }
              else{
    
    
             struct Node*newnode= BuyNewnode(move->val);
             tail->next=newnode;
             tail=tail->next;
             move=move->next;
         }
    }
    struct Node*setran=newhead;
    struct Node*findran=head;
      while(setran&&findran){
    
    
        struct Node*temp=findrandom(head,newhead,findran->random);
        setran->random=temp;
        setran=setran->next;
        findran=findran->next;
    }
    return newhead;
}

Summarize

This time the questions are a little more difficult!
But it will definitely not be a problem for everyone!
come on! come on!

Guess you like

Origin blog.csdn.net/mdjsmg/article/details/132092860