10.23链表练习

2.4反转链表

class Solution {

public:

  ListNode* reverseList(ListNode* head) {

​    ListNode* pre = nullptr;创建一个空的头节点

​    ListNode* cur = head;

​    ListNode* temp;

​    while(cur){

​      temp = cur->next;//保存后方链表

​      cur->next=pre;//将原来cur的next指针反向指向它的前驱结点pre

​      pre=cur;//pre和cur同步向后方移动

​      cur=temp;

​    }

​    return pre;//返回的是pre,此时cur作为循环出口为空

  }

};

2.5两两交换链表结点

image

class Solution {

public:

  ListNode* swapPairs(ListNode* head) {

​    ListNode* dummyHead = new ListNode(0);

​    dummyHead->next = head;

​    ListNode* p=dummyHead;

​    while(p->next != nullptr && p->next->next != nullptr){

​      ListNode* temp1 = p->next;//保存头结点后的第一个结点

​      ListNode* temp2 = p->next->next->next;//保存下一组准备交换的元素首位



​      p->next = temp1->next;

​      temp1->next->next = temp1;

​      temp1->next = temp2;



​      p=p->next->next;

​    }

​    return dummyHead->next;

  }

};

2.6删除链表的倒数第k个结点

快指针先行移动k个位置。然后快慢指针同步移动

class Solution {

public:

  ListNode* removeNthFromEnd(ListNode* head, int n) {

​    ListNode* dummyHead = new ListNode(0);

​    dummyHead->next = head;

​    ListNode* p = dummyHead;

​    ListNode* q = dummyHead;//快慢指针

​    while(n--)

​      p=p->next;

​    p=p->next;//这里容易丢失。如果没有实际上q最终指向的是待删除元素本身而不是前驱

​    while(p){

​      p=p->next;

​      q=q->next;

​    }

​    q->next = q->next->next;

​    return dummyHead->next;

  }

};

2.7链表相交

先找出两个;链表长度之差。然后同步链表向后方移动。

class Solution {

public:

  ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {

​    int count1=0,count2=0,dist;//dist是差额

​    ListNode* longlist;

​    ListNode* shortlist;

​    ListNode* p=headA;

​    ListNode* q=headB;

​    while(p){

​      count1++;

​      p=p->next;

​    }

​    while(q){

​      count2++;

​      q=q->next;

​    }

​    if(count1>count2){

​      longlist = headA;

​      shortlist = headB;

​      dist = count1-count2;

​    }

​    else{

​      longlist = headB;

​      shortlist = headA;

​      dist = count2-count1;

​    }

​    while(dist--)

​      longlist = longlist->next;

​    

​    while(longlist){

​      if(longlist == shortlist)

​        return longlist;

​      longlist = longlist->next;//这两个部分不能忘

​      shortlist = shortlist->next;

​    }

​    return 0;

  }

};

2.8环形链表

fast指针每次移动两步,slow指针每次移动一步。如果存在环形则两指针一定可以相遇。

x是头结点到环形入口的长度;y是环形入口到相遇点的长度;z是相遇点到环形入口的长度。

推导过程: fast位移距离:x+y+n(y+z)

​ slow位移距离:x+y

​ (x+y)2 = x+y+n(y+z) => x+y = n(y+z) => x = (n-1)y+nz => x = (n-1)*(y+z)+z

对于n=1时,公式是x = z

相当于,如果两指针分别从头结点和相遇结点出发,都是一个步伐长度的移动。那么这两者的位移距离是相同的。此时这个位移的终点就是我们的环形入口结点

image


class Solution {

public:

  ListNode *detectCycle(ListNode *head) {

​    int count=0;

​    ListNode* fast;

​    ListNode* slow;

​    fast = head;

​    slow = head;

​    while(fast&&fast->next){

​      fast = fast->next->next;

​      slow = slow->next;

​      if(fast == slow){

​        ListNode* index1 = fast;

​        ListNode* index2 = head;

​        while(index1!=index2){

​          index1 = index1->next;

​          index2 = index2->next;

​        }

​        return index1;

​      }

​    }



​    return 0;

  }

};
posted @ 2023-10-23 20:24  Ref-rain-  阅读(12)  评论(0)    收藏  举报