当前位置: 首页 > article >正文

链表算法练习

练习1:移除链表元素

203. 移除链表元素 - 力扣(LeetCode)

思路: 创建新链表,并且建立头尾指针,将原链表不等于val的值尾插到新链表中。

typedef struct ListNode LN;
struct ListNode* removeElements(struct ListNode* head, int val) 
{
    LN* newhead,*newtile;
    newhead=newtile=NULL;
    LN* pcur=head;
    while(pcur)
    {
        if(pcur->val!=val)
        {
            if(newhead==NULL)
            {
                newhead=newtile=pcur;
            }
            else
            {
                newtile->next=pcur;
                newtile=newtile->next;
            }
        }
        pcur=pcur->next;
    }
    if(newtile!=0)
        newtile->next=NULL;
    return newhead;
}

注意:在写代码中,最后一定要判断nwetile是否等于零,从而使下一个指针指向NULL,否则就会出现下面的错误,导致最后面与val相同的值没有删除。

if(newtile!=0)
    newtile->next=NULL;

练习2:反转链表

206. 反转链表 - 力扣(LeetCode)

思路:创建三个指针,就能在原链表上修改指针指向。

 typedef struct ListNode LN;
struct ListNode* reverseList(struct ListNode* head) 
{
    if(head==NULL)
    {
        return head;
    }
    LN* n1,*n2,*n3;
    n1=NULL;
    n2=head;
    n3=n2->next;
    while(n3)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        n3=n3->next;
    }
    n2->next=n1;
    return n2;
}

练习3:链表的中间结点

876. 链表的中间结点 - 力扣(LeetCode)

思路:快慢指针,慢指针每次走一次,快指针则每次走两次。

typedef struct ListNode LN;
struct ListNode* middleNode(struct ListNode* head) {
    LN* slow=head;
    LN* fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

练习4:返回倒数第k个节点

面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode)

思路:采用两次遍历,先求出链表一共有几个数,再进行返回。

typedef struct ListNode LN;
int kthToLast(struct ListNode* head, int k) {
    LN* pcur=head;
    int n=0;
    while(pcur)
    {
        pcur=pcur->next;
        n++;
    }
    pcur=head;
    while(n-k)
    {
        pcur=pcur->next;
        k++;
    }
    return pcur->val;
}

练习5:合并两个有序链表

21. 合并两个有序链表 - 力扣(LeetCode)

思路:创建新链表,遍历原链表,比较大小,谁小尾插到新链表后面

typedef struct ListNode LN;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{
    if(list1==NULL)
    {
        return list2;
    }
    else if(list2==NULL)
    {
        return list1;
    }

    LN* newhead,*newtile;
    newhead=newtile=(LN*)malloc(sizeof(LN));

    while(list1 && list2)
    {
        if(list1->val < list2->val)
        {
            newtile->next=list1;
            newtile=newtile->next;
            list1=list1->next;
        }
        else
        {
            newtile->next=list2;
            newtile=newtile->next;
            list2=list2->next;
        }
    }

    if(list1!=0)
    {
        newtile->next=list1;
    }
    else
    {
        newtile->next=list2;
    }

    LN *ret=newhead->next;
    free(newhead);
    newhead=NULL;
    return ret;
}

 

练习6:链表分割

链表分割_牛客题霸_牛客网

思路:创建两个链表的头尾结点,对链表分别进行小的和大的的尾差,连接两个链表。

class Partition 
{
public:
    ListNode* partition(ListNode* pHead, int x) 
    {
        // write code here
        ListNode* phead,*ptile;
        phead=ptile=(ListNode*)malloc(sizeof(ListNode));

        ListNode* ghead,*gtile;
        ghead=gtile=(ListNode*)malloc(sizeof(ListNode));

        ListNode* pcur=pHead;
        while(pcur)
        {
            if(pcur->val < x)
            {
                ptile->next=pcur;
                ptile=ptile->next;
                pcur=pcur->next;
            } 
            else
            {
                gtile->next=pcur;
                gtile=gtile->next;
                pcur=pcur->next;
            } 
        }

        gtile->next=NULL;
        ptile->next=ghead->next;
        ListNode* ret=phead->next;
        free(ghead);
        free(phead);
        ghead=phead=NULL;
        return ret;
    }
};

练习7:链表的回文结构

链表的回文结构_牛客题霸_牛客网

思路:先找到中间结点,然后对后半部分进行反转,比较前半部分和反转后的后半部分。

class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here
        ListNode* show=A;
        ListNode* fast=A;
        while(fast && fast->next)
        {
            show=show->next;
            fast=fast->next->next;
        } 

        ListNode* n1,*n2,*n3;
        n1=NULL;
        n2=show;
        n3=n2->next;
        while(n2)
        {
            n2->next=n1;
            n1=n2;
            n2=n3;
            if(n3)
                n3=n3->next;
        }
        ListNode* right=n1;

        ListNode* left=A;

        while(right)
        {
            if(right->val != left->val)
                return false;
            right=right->next;
            left=left->next;
        }
        return true;
    }
};

练习8:相交链表

160. 相交链表 - 力扣(LeetCode)

思路:找两个链表结点数的相差值,长链表先走相差的数,然后两个开始遍历,找是否有相交的点。

typedef struct ListNode LN;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    LN* l1=headA;
    LN* l2=headB;
    int size1=0,size2=0;
    while(l1)
    {
        size1++;
        l1=l1->next;
    }
    while(l2)
    {
        size2++;
        l2=l2->next;
    }
    int get=abs(size1-size2);

    LN* llong=headA;
    LN* sshort=headB;
    if(size1 < size2)
    {
        llong=headB;
        sshort=headA;
    }

    while(get)
    {
        llong = llong->next;
        get--;
    }

    while(llong && sshort)
    {
        if(sshort==llong)
        {
            return llong;
        }
        llong=llong->next;
        sshort=sshort->next;
    }
    return NULL;
}

练习9:环形链表(1)

141. 环形链表 - 力扣(LeetCode) 

思路:使用快慢指针。

typedef struct ListNode LN;
bool hasCycle(struct ListNode *head) {
    LN* slow=head;
    LN* fast=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(fast==slow)
        {
            return true;
        }
    }
    return false;
}

练习10:环形链表(2)

142. 环形链表 II - 力扣(LeetCode)

思路:快慢指针,找到相遇点后,从头结点和相遇结点分别开始遍历,如果两个中间相遇则找到索引的链表结点。

typedef struct ListNode LN;
struct ListNode *detectCycle(struct ListNode *head) {
    LN* slow=head;
    LN* fast=head;

    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(fast==slow)
        {
            LN* pcur=head;
            while(pcur!=fast)
            {
                pcur=pcur->next;
                fast=fast->next;
            }
            return pcur;
        }
    }
    return false;
}

练习11:随机链表的复制

138. 随机链表的复制 - 力扣(LeetCode)

 

 

思路:在原来链表基础上,每个结点后面加入新的结点,并且进行一比一复制,然后使复制链表与原链表断开。

typedef struct Node node;
struct Node* copyRandomList(struct Node* head) {
	if(head==NULL)
    {
        return NULL;
    }

    node* pcur=head;
    while(pcur)
    {
        node* next=pcur->next;
        node* newnode=(node*)malloc(sizeof(node));
        newnode->val=pcur->val;
        newnode->next=newnode->random=NULL;

        pcur->next=newnode;
        newnode->next=next;

        pcur=next;
    }

    pcur=head;
    while(pcur)
    {
        node* copy=pcur->next;
        if(pcur->random!=NULL)
        {
            copy->random=pcur->random->next;
        }
        pcur=copy->next;
    }

    pcur=head;
    node* phead,*ptile;
    phead=ptile=pcur->next;
    while(pcur->next->next)
    {
        pcur=pcur->next->next;
        ptile->next=pcur->next;
        ptile=ptile->next;
    }
    return phead;
}

http://www.kler.cn/a/467050.html

相关文章:

  • MySQL的三大日志
  • 【网络协议】IPv4 地址分配 - 第一部分
  • CANFD芯片在商业航天的应用
  • 凸包(convex hull)简述
  • umd格式
  • SpringBoot+Vue养老院管理系统设计与实现【开题报告+程序+安装部署+售后讲解】
  • Arduino Uno简介与使用方法
  • 如何逐步操作vCenter修改DNS服务器?
  • React 中的受控组件与非受控组件:深度剖析与实战应用
  • 微服务拆分的艺术:构建高效、灵活的系统架构
  • 清华发布Hyper-YOLO:超图计算+目标检测!捕捉高阶视觉关联
  • spring默认线程池SimpleAsyncTaskExecutor特点为什么要尽量避免使用
  • Java四大常用JSON解析性能对比:Hutool、Fastjson2、Gson与Jackson测试
  • Nginx:日志管理
  • 零基础WPF使用NLog记录日志
  • CPU与GPU的区别
  • C/C++中 <<与<<=的介绍和区别
  • Ungoogled Chromium127 编译指南 MacOS 篇(一)- 项目介绍
  • 【Leetcode 热题 100】74. 搜索二维矩阵
  • 【2025最新计算机毕业设计】基于Spring Boot+Vue影院购票系统(高质量源码,提供文档,免费部署到本地)
  • Python 开发框架搭建简单博客系统:代码实践与应用
  • Edge安装问题,安装后出现:Could not find Edge installation
  • 30分钟学会css
  • 电商Google广告:2025年提升转化率的5种策略
  • 八字算命网站搭建方法:从零开始用php搭建一个命理网
  • 才气小波与第一性原理