【数据结构与算法】顺序表和链表题解

一、 移除链表元素

🎬 博主名称键盘敲碎了雾霭
🔥 个人专栏 : 《C语言》《数据结构》

⛺️指尖敲代码,雾霭皆可破


文章目录

  • [一、 移除链表元素](#一、 移除链表元素)
    • [1.1 问题描述](#1.1 问题描述)
    • [1.2 解题思想](#1.2 解题思想)
    • [1.3 代码实现](#1.3 代码实现)
    • 二、反转一个单链表
    • [2.1 问题描述](#2.1 问题描述)
    • [2.2 解题思想](#2.2 解题思想)
    • [2.3 代码实现](#2.3 代码实现)
    • 三、链表的中间结点
    • [3.1 问题描述](#3.1 问题描述)
    • [3.2 解题思想](#3.2 解题思想)
    • [3.3 代码实现](#3.3 代码实现)
  • 四、返回倒数第k个节点
    • [4.1 问题描述](#4.1 问题描述)
    • [4.2 解题思想](#4.2 解题思想)
    • [4.3 代码实现](#4.3 代码实现)
  • 五、合并两个有序链表
    • [5.1 问题描述](#5.1 问题描述)
    • [5.2 解题思想](#5.2 解题思想)
    • [5.3 代码实现](#5.3 代码实现)
  • 六、链表分割
    • [6.1 问题描述](#6.1 问题描述)
    • [6.2 解题思想](#6.2 解题思想)
    • [6.3 代码实现](#6.3 代码实现)
  • 七、链表的回文结构
    • [7.1 问题描述](#7.1 问题描述)
    • [7.2 解题思想](#7.2 解题思想)
    • [7.3 代码实现](#7.3 代码实现)
  • 八、相交链表
    • [8.1 问题描述](#8.1 问题描述)
    • [8.2 解题思想](#8.2 解题思想)
    • [8.3 代码实现](#8.3 代码实现)
  • 九、环形链表
    • [9.1 问题描述](#9.1 问题描述)
    • [9.2 解题思想](#9.2 解题思想)
    • [9.3 代码实现](#9.3 代码实现)
  • 十、环形链表2
    • [10.1 问题描述](#10.1 问题描述)
    • [10.2 解题思想](#10.2 解题思想)
    • [10.3 代码实现](#10.3 代码实现)

1.1 问题描述

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
原题链接:203.移除链表元素

1.2 解题思想

创建新链表,遍历原链表

1.3 代码实现

c 复制代码
struct ListNode* removeElements(struct ListNode* head, int val) 
{
    struct ListNode*phead=NULL;
    struct ListNode*ptail=NULL;
    struct ListNode *pur=head;
    while(pur)
    {
        if(pur->val!=val)
        {
            if(phead==NULL)
            {
                phead=ptail=pur;
            }
            else
            {
                ptail->next=pur;
                ptail=pur;
            }
        }
        pur=pur->next;
    } 
    if(phead==NULL)
    {
        return NULL;
    }
    ptail->next=NULL;
    return phead;   
}

二、反转一个单链表

2.1 问题描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
原题链接:206.反转链表

2.2 解题思想

建立三个指针,依次遍历

2.3 代码实现

c 复制代码
struct ListNode* reverseList(struct ListNode* head) 
{
    if(head==NULL)
    {
        return head;
    }
    struct ListNode*l1=NULL;
    struct ListNode*l2=head;
    struct ListNode*l3=l2->next;
    while(l2)
    {
        l2->next=l1;
        l1=l2;
        l2=l3;
        if(l3!=NULL)
        l3=l3->next;
    }
    return l1;
}

三、链表的中间结点

3.1 问题描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
原题链接:876.链表的中间结点

3.2 解题思想

建立三个指针,依次遍历

3.3 代码实现

c 复制代码
struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode*slow=head;  
    struct ListNode*fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

四、返回倒数第k个节点

4.1 问题描述

实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。
原题链接:面试题02.02.返回倒数第k个节点

4.2 解题思想

建立快慢指针,有原始距离

4.3 代码实现

c 复制代码
int kthToLast(struct ListNode* head, int k)
{
    struct ListNode*slow=head;
    struct ListNode*fast=head;
    while(k--)
    {
        fast=fast->next;
    }
    while(fast)
    {
        slow=slow->next;
        fast=fast->next;
    }
    return slow->val;
}

五、合并两个有序链表

5.1 问题描述

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
原题链接:21.合并两个有序链表

5.2 解题思想

新建立一个链表,遍历两个原链表

5.3 代码实现

c 复制代码
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{
    if(list1==NULL)
    {
        return list2;
    }
    else if(list2==NULL)
    {
        return list1;
    }
    struct ListNode*l1=list1;
    struct ListNode*l2=list2;
    struct ListNode*phead=NULL;
    struct ListNode*ptail=NULL;
    phead=ptail=malloc(sizeof(struct ListNode));
    while(l1&&l2)
    {
        if(l1->val<l2->val)
        {
            ptail->next=l1;
            ptail=l1;
            l1=l1->next;
        }
        else
        {
            ptail->next=l2;
            ptail=l2;
            l2=l2->next;
        }
    }
    if(l1)
    {
        ptail->next=l1;
        ptail=l1;
        l1=l1->next;
    }
    if(l2)
    {
        ptail->next=l2;
        ptail=l2;
        l2=l2->next;
    }
    struct ListNode*next =phead->next;
    free(phead);
    phead=next;
    return phead;
}

六、链表分割

6.1 问题描述

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针
原题链接:CM11 链表分割

6.2 解题思想

构建两个链表,最后再合并起来

6.3 代码实现

c 复制代码
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) 
    {
        struct ListNode *pur=pHead;
        struct ListNode * phead1=(struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode *ptail1=phead1;
        struct ListNode*phead2=(struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode*ptail2=phead2;
        while(pur)
        {
            if(pur->val<x)
            {
                ptail1->next=pur;
                ptail1=pur;
            }
            else
            {
                ptail2->next=pur;
                ptail2=pur;
            }
            pur=pur->next;
        }
        ptail2->next=NULL;
        ptail1->next=phead2->next;
        return phead1->next;
        // write code here
    }
};

七、链表的回文结构

7.1 问题描述

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
原题链接:OR36 链表的回文结构

7.2 解题思想

先找中间节点,再反转链表,然后两链表比较

7.3 代码实现

c 复制代码
class PalindromeList {
public:
    struct ListNode* CheckMid(struct ListNode*head)
    {
        struct ListNode*slow=head;
        struct ListNode*fast=head;
        while(fast&&fast->next)
        {
            slow=slow->next;
            fast=fast->next->next;
        }
        return slow;
    }
    struct ListNode*Rverse(struct ListNode*head)
    {
        struct ListNode*l1=NULL;
        struct ListNode*l2=head;
        struct ListNode*l3=head->next;
        while(l2)
        {
            l2->next=l1;
            l1=l2;
            l2=l3;
            l3=l3->next;
        }
        return l1;
    }
    bool chkPalindrome(ListNode* A)
    {
        struct ListNode*pur=A;
        struct ListNode* mid =CheckMid(A);
        struct ListNode*phead=Rverse((mid));
        while(pur&&phead)
        {
            if(phead->val!=pur->val)
            {
                return false;
            }
            pur=pur->next;
            phead=phead->next;
        }
        return true;
        // write code here
    }
};

八、相交链表

8.1 问题描述

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
原题链接:160.相交链表

8.2 解题思想

利用快慢指针,算出相差的距离,快的先走,从同一位置依次遍历

8.3 代码实现

c 复制代码
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    struct ListNode*l1=headA;
    struct ListNode*l2=headB;
    int count1=0;
    int count2=0;
    while(l1->next)
    {
        count1++;
        l1=l1->next;
    }
    while(l2->next)
    {
        count2++;
        l2=l2->next;
    }
    if(l1!=l2)
    {
        return NULL;
    }
    int dif=abs(count2-count1);
    struct ListNode*longlist=headA;
    struct ListNode*shortlist=headB;
    if(count1<count2)
    {
        longlist=headB;
        shortlist=headA;
    }
    while(dif--)
    {
        longlist=longlist->next;
    }
    while(longlist!=shortlist)
    {
        longlist =longlist->next;
        shortlist = shortlist->next;
    }
    return longlist;
}

九、环形链表

9.1 问题描述

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。
原题链接:141.环形链表

9.2 解题思想

利用快慢指针必相遇

9.3 代码实现

c 复制代码
bool hasCycle(struct ListNode *head) 
{
    struct ListNode*slow=head;
    struct ListNode*fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(fast==slow)
        {
            return true;
        }
    }
    return false;
}

十、环形链表2

10.1 问题描述

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
原题链接:142. 环形链表

10.2 解题思想

利用快慢指针,找到相遇的节点,从该节点到成环的起始节点与头节点到成环的起始节点距离相同,会相遇

10.3 代码实现

c 复制代码
struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode*slow=head;
    struct ListNode*fast=head;
    struct ListNode*phead=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(fast==slow)
        {
            struct ListNode*meet=fast;
            while(meet!=phead)
            {
                meet=meet->next;
                phead=phead->next;
            }
            return meet;
        }
    }
    return NULL;
}
相关推荐
TracyCoder1232 小时前
LeetCode Hot100(58/100)——138. 随机链表的复制
leetcode·链表
浅念-2 小时前
C++ STL list 容器
开发语言·数据结构·c++·经验分享·笔记·算法·list
重生之后端学习2 小时前
39. 组合总和
java·数据结构·算法·职场和发展·深度优先
二年级程序员2 小时前
一篇文章掌握“队列”
c语言·数据结构·算法
载数而行5202 小时前
算法系列3之拓扑排序
c语言·数据结构·c++·算法·排序算法
!停3 小时前
数据结构排序算法—插入排序
数据结构·算法·排序算法
We་ct3 小时前
LeetCode 124. 二叉树中的最大路径和:刷题解析
前端·数据结构·算法·leetcode·typescript
元亓亓亓5 小时前
考研408--数据结构--day15--排序&内部排序(上)
数据结构·408·排序·内部排序
程序员酥皮蛋12 小时前
hot 100 第三十五题 35.二叉树的中序遍历
数据结构·算法·leetcode