首页 > 其他分享 >专题:链表(已完结)

专题:链表(已完结)

时间:2024-10-16 13:53:39浏览次数:9  
标签:专题 ListNode val int nullptr next 链表 dummyHead 完结

1.移除链表元素
就是续签prenode curnode 需要注意本地使用虚拟头节点逻辑更加简单

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        
      ListNode* dummyHead = new ListNode();
      dummyHead->next=head;
      ListNode* prenode= dummyHead;
      ListNode* curnode= dummyHead->next;
      while(curnode!=nullptr){
        if(curnode->val==val){
            ListNode* delenode=curnode;
            prenode->next=curnode->next;
            curnode=curnode->next;
            delete delenode;
        }else{
            prenode=curnode;
            curnode=curnode->next;
        }

      }
      auto result = dummyHead->next;
      delete dummyHead;
      return result;
    }
};

2.设计链表

class MyLinkedList {
public:
   struct mynode{
      int val;
      mynode * next;
      mynode():val(0),next(nullptr){}
   };
    MyLinkedList() {
        dummyHead=new mynode();
    }
    
    int get(int index) {
        mynode* cur = dummyHead;
        for(int i=0;i<=index;i++){
            cur=cur->next;
           if(cur==nullptr){
            break;
           }
        }
        // cout<<"after:index::"<<index<<endl;
        if(cur==nullptr){
          return -1;
        }
        return  cur->val;
    }
    
    void addAtHead(int val) {
        mynode *newHead=new mynode();
        newHead->val=val;
        newHead->next= dummyHead->next;
        dummyHead->next =newHead;
    }
    
    void addAtTail(int val) {
      // pre结点和cur结点同时移动直到cur是空节点 直接在pre后面插入即可
      mynode *prenode=dummyHead;
      mynode *curnode=dummyHead->next;
      while(curnode!=nullptr){
        prenode=curnode;
        curnode=curnode->next;
      }
      mynode *tailnode=new mynode();
      tailnode->val = val;
      prenode->next=tailnode;
    }
    
    void addAtIndex(int index, int val) {
        // 这里先判断index是否有效  然后pre和cur同时移动index个步数即可
        mynode * cur = dummyHead->next;
        int maxindex=-1;
        while(cur!=nullptr){
          maxindex++;
          cur=cur->next;
        }
        if(maxindex+1<index){
            return;
        }
        mynode* prenode = dummyHead;
        mynode* curnode = dummyHead->next;
        while(index--){
            prenode=curnode;
            curnode=curnode->next;
        }
        mynode *newnode=new mynode();
        newnode->val = val;
        newnode->next=prenode->next;
        prenode->next=newnode;
    }
    
    void deleteAtIndex(int index) {
        if(get(index)==-1){
            return;
        }
        mynode* pre = dummyHead;
        mynode* cur = dummyHead->next;
        while(index--){
            pre=cur;
            cur=cur->next;
        }
        mynode* deletnode = cur;
        pre->next=cur->next;
        delete deletnode;
    }

    // 使用虚拟头结点 方便插入删除 
    mynode * dummyHead=nullptr;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

3.反转链表
主要思路 使用虚拟有节点 然后遍历每个节点 直接插入头部即可

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* dummyHead = new ListNode();
        dummyHead->next=nullptr;

        ListNode* cur = head;
        while(cur!=nullptr){
            ListNode* nextnode = cur->next;
            cur->next=dummyHead->next;
            dummyHead->next=cur;
            cur=nextnode;
        }
        ListNode* result = dummyHead->next;
        delete  dummyHead;
        return result;
    }
};

4.两两交换链表中的节点
使用虚拟头结点 找到pre 然后取 待交换的两个节点

            ListNode* nextnode1=pre->next;
            ListNode* nextnode2=pre->next->next;

另外注意 交换之后 pre更新位置不是两个节点的下一个节点 而是

pre=nextnode1;
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode();
        dummyHead->next=head;
        ListNode* pre=dummyHead;
        while(pre->next!=nullptr && pre->next->next!=nullptr){
            ListNode* nextnode1=pre->next;
            ListNode* nextnode2=pre->next->next;
            ListNode* tempnode=nextnode2->next;
            nextnode2->next=nextnode1;
            nextnode1->next=tempnode;
            pre->next=nextnode2;

            pre=nextnode1;
        }
        ListNode* result=dummyHead->next;
        delete dummyHead;
        return result;

    }
};

5.删除链表的倒数第N个节点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyhead = new ListNode();
        dummyhead->next = head;
        ListNode *slow=dummyhead;
        ListNode *fast=dummyhead;
        while(n--){
            // 快指针先走n个节点
            fast=fast->next;
            if(fast==nullptr){
                break;
            }
        }
        if(fast==nullptr){
            // 证明n已经大于节点个数 无意义
            delete dummyhead;
            return head;
        }
        while(fast->next!=nullptr){
            slow=slow->next;
            fast=fast->next;
        }
        ListNode *delenode=slow->next;
        slow->next=delenode->next;
        delete delenode;
        ListNode * result = dummyhead->next;;
        delete dummyhead;
        return result;

    }
};

6.链表相交
主要思路:
方法一:首先长的链表先移动差值个单位 然后 然后判断两个链表此时位置是否是同一个节点 不是的话一起一个单位 再次判断 还不是的话 再次移动 如此反复判断 直到其中一个链表移动到末尾即可。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int lenA =0;
        ListNode *curA=headA;
        while(curA){
            lenA++;
            curA=curA->next;
        }

        int lenB =0;
        ListNode *curB=headB;
        while(curB){
            lenB++;
            curB=curB->next;
        }
        // cur1指向更长的
        ListNode * cur1=headA;
        ListNode * cur2=headB;
        int k = abs(lenA-lenB);
        if(lenA<lenB){
            swap(cur1,cur2);
        }
        while(k--){
            cur1=cur1->next;
        }
        while(cur1!=nullptr){
            if(cur1==cur2){
                return cur1;
            }else{
                cur1=cur1->next;
                cur2=cur2->next;
            }

        }
        return nullptr;
    }
};

方法二:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
      ListNode *curA= headA;
      ListNode *curB= headB;
      while(curA!=curB){
          curA=curA==NULL?headB:curA->next;
          curB=curB==NULL?headA:curB->next; 
      }
      return curA;
    }
};

7.环形链表II
注意
快慢指针都是从第一个节点出发

        ListNode *slow=head;
        ListNode *fast=head;

循环体内慢指针每次走一个节点 快指针每次走两个节点

             slow = slow->next;
             fast=fast->next->next;

如果快慢指针不相遇一直这么走 直到fastnullptr或者fast->nextnullptr结束 相遇的话 直接重新设置两个指针 一个从头节点出发 一个从相遇节点出发 每次比较 如果不是同一个节点 每次都走一个节点长度 直到相遇即可

                ListNode *cur1=head;
                ListNode *cur2=slow;
                while(cur1!=cur2){
                    cur1=cur1->next;
                    cur2=cur2->next;
                }
                return cur1;

完整代码如下

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *slow=head;
        ListNode *fast=head;
        while(fast!=nullptr&&fast->next!=nullptr){
             slow = slow->next;
             fast=fast->next->next;
            if(fast==slow){
                ListNode *cur1=head;
                ListNode *cur2=slow;
                while(cur1!=cur2){
                    cur1=cur1->next;
                    cur2=cur2->next;
                }
                return cur1;
            }

        }
        return nullptr;
        
    }
};

标签:专题,ListNode,val,int,nullptr,next,链表,dummyHead,完结
From: https://blog.csdn.net/qq_23923713/article/details/142910374

相关文章

  • 【K8s】专题十四(2):Kubernetes 安全机制之 Security Context
    本文内容均来自个人笔记并重新梳理,如有错误欢迎指正!如果对您有帮助,烦请点赞、关注、转发、订阅专栏!专栏订阅入口| 精选文章 | Kubernetes |Docker |Linux |羊毛资源 | 工具推荐 |往期精彩文章【Docker】(全网首发)KylinV10下MySQL容器内存占用异常的解决......
  • 提高组 dp 专题 4 做题记录
    八百万年没有写过做题记录了,主要还是因为暑假忘了,现在重新写一下。带*表示未做出,带^表示半做出。*A[PA2021]Oddeskidodeski这个题的难点在于设计状态。首先明确这道题不是区间dp,因为不同的区间答案显然一致。所以考虑对每一个长度dp。接下来进一步考虑,我们对于一......
  • vjudge数学专题1
    挑了几道可做的做了,难度大概升序排序F NewYearandArbitraryArrangementNewYearandArbitraryArrangement期望dp,考虑逆推。考虑设\(f_{i,j}\)为有\(i\)个\(a\),当前序列有\(j\)个\(ab\)的期望长度。有\(f_{i,j}=f_{i+1,j}\timesp_a+f_{i,j+i}\timesp_b\)目标要设为......
  • 合并两个排序的链表
    输入两个链表,并将它们的值按照递增的顺序合并成一个新的链表。题目要求如下:  我们可以创建两个新的链表,其中一个作为中间变量来存储合并后的链表,另一个链表记录中间链表并作为返回值返回。代码如下:/***structListNode{* intval;* structListNode*next;*}......
  • 【专题】2024年经销商车后用户研究:洞察车主变化制胜售后未来报告合集PDF分享(附原数据
    原文链接:https://tecdat.cn/?p=37875 在汽车行业快速变革的时代,“互联网原住民”成为车主群体的重要组成部分。2023-2024年,车后用户线上渠道使用比例不断上升,App/小程序备受青睐,各线上渠道各具优势。同时,购车关注点也在不断变化,价格成为关键因素,本土品牌崛起,新能源汽车受青睐......
  • 单链表的基本概念
    单链表的定义typedefstructLNode{intdata;structLNode*next;//定义一个指向结构体自身的指针,用来指向下一个节点}LNode,*LinkList;_____________________________________________LNode*p=LinkListp;//两种定义指针的形式,侧重点不......
  • Python私房菜——筑基篇(已完结)
    1Python私房菜【一】——(前置基础)1.1编码就是把人类语言(文字)通过编码的形式(如a-->1100001)一一映射成计算机认识的语言(0101…),即将人类语言通过某种形式转换成计算机认识的二进制数。这种编码形式是人为定义的,因此就有多种不同的编码方式。1.1.1ASCII码是早期的......
  • AOT漫谈专题(第四篇): C#程序如何编译成Native代码
    一:背景1.讲故事大家都知道所谓的.NETNativeAOT即通过AOT编译器直接将C#代码编译成机器码,大家也习惯用C/C++的编译过程来类比,都是静态编译本质上都差不多,这篇我们借助工具从宏观层面去看一看AOT的编译过程。二:C/C++的编译过程用gcc编译过c代码的朋友都知道,分别可以用-E,-......
  • 03 线性结构——链表(逻辑与物理结构、分类、时间复杂度分析、相关功能定义与代码实现)
    目录1 链表是什么1.1 逻辑结构1.2物理结构1.3 相关概念2链表的分类2.1单链表2.2双链表2.3循环单链表2.4循环双链表2.5静态链表3链表的优缺点3.1优点3.2缺点3.3与数组的对比4功能定义5功能实现5.1初始化链表5.2返回链表的长度5.3在指定位......
  • 算法题——合并两个已排序链表(不使用额外空间)
    题目如下:        输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。        数据范围: 0≤n≤10000≤n≤1000,−1000≤节点值≤1000−1000≤节点值≤1000要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)      ......