首页 > 编程语言 >单链表算法题(数据结构)

单链表算法题(数据结构)

时间:2024-11-12 22:15:30浏览次数:3  
标签:单链 ListNode struct fast next 链表 算法 数据结构 指针

1. 反转链表

https://leetcode.cn/problems/reverse-linked-list/description/

题目

看到这个题目的时候我们怎么去想呢?如果我们反应快的话,应该可以想到我们可以从1遍历到5然后依次头插,但是其实我们还有更好的办法,就是利用三个指针,如何使用呢?

反转链表OJ
假如结构体已经给出
typedef struct ListNode SL;
SL* reverseList(SL* head)
{
    //处理空链表
    if (head == NULL)
    {
        return head;
    }
    else
    {
        //创建三个指针
        SL* n1, n2, n3;
        n1 = NULL, n2 = head, n3 = n2->next;
        while (n2)
        {
            n2->next = n1;
            n1 = n2;
            n2 = n3;
            if (n3)
            {
                n3 = n3->next;
            }
        }
        return n1;

    }
}

 2. 链表的中间结点

https://leetcode.cn/problems/middle-of-the-linked-list/description/ 题目:  这个题目就是在一个链表中我们要返回中间结点,如果中间结点有两个的话就返回第二个结点。

对于这个题目我们可能会想到一个简单的思路,就是遍历两边数组然后找到中间的一个结点,但是呢,今天讲一个更方便的算法叫做快慢指针,也就如上图所示,一个慢指针和一个快指针,快指针走两步慢指针走一步,最终当快指针走到终的时候慢指针刚好就在中间,让我们来实现一下:

//找链表的中间结点
//Definition for singly-linked list.
struct ListNode
{
    int val;
    struct ListNode *next;
};
 
typedef struct ListNode SL;
struct ListNode* middleNode(struct ListNode* head)
{
	SL* slow = head;
	SL* fast = head;
	while (fast && fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;
	}
	return slow;
}

再上一个题目中我们有一个点需要注意就是我们在写while循环的条件时候注意不能将fast&&fast->next的位置搞反,原因就是不能解引用空指针,所以顺序一定注意一下。

3.  合并两个有序链表

https://leetcode.cn/problems/merge-two-sorted-lists/description/

题目:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。这个题目的思路也很好想出来,我们可以遍历两个升序链表,然后创建一个新的链表,将遍历的结点按升序放入新的链表中,要注意链表为空的情况。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode SL;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{
    //创建新的链表
    SL* newhead=NULL;
    SL* newtail=NULL;
    //创建两个指针分别指向两个链表
    SL* l1=list1;
    SL* l2=list2;
    //判断两个链表是否为空
    if(list1==NULL)
    {
        return l2;
    }
    if(list2==NULL)
    {
        return l1;
    }
    while(l1&&l2)
    {
        if(l1->val<=l2->val)
        {
            //l1尾插到新链表中
            if(newhead==NULL)
            {
                newhead=newtail=l1;
            }
            else
            {
                newtail->next=l1;
                newtail=newtail->next;
            }
            l1=l1->next;
        }
        else
        {
            //l2尾插到新链表中
            if(newhead==NULL)
            {
                newhead=newtail=l2;
            }
            else
            {
                newtail->next=l2;
                newtail=newtail->next;
            }
            l2=l2->next;

        }
    }
    //跳出循环有两种情况,要么l1为空,要么l2为空
    if(l1)
    {
        newtail->next=l1;
    }
    if(l2)
    {
        newtail->next=l2;
    }
    return newhead;
}

4. 链表的回文结构

https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa

什么是回文结构?比如1221,它看起来像是对称的可以从中间重叠的感觉,叫做回文数字。像上图1->2->2->1,就是链表的回文结构。我们就是思考如何去判读一个链表是否是回文结构。我们可能会想到说这个题目需要去遍历比较是否相等,但是有一个问题就是在单链表中是不能向后遍历的,又因为这个题目是的链表长度是有限的,所以我们不妨把链表放入数组中来比较,那么如何操作呢?

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) 
    {
        // write code here
        //创建一个数组
        int arr[900] = {0};
        ListNode* pcur = A;
        int i = 0;
        //遍历链表,将链表中的每个结点的数值放入数组中
        while(pcur)
        {
            arr[i++] = pcur->val;
            pcur=pcur->next;
        }
        //找中间结点,判断是否是回文数字
        int left=0;
        int right=i-1;
        while(left<right)
        {
            if(arr[left]!=arr[right])
            {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
};

对于这个题目来说,它是有限制的,所以我们可以放在数组中去双向遍历,但是一旦链表没有限制,我们就不能这样来写,我们可以有另一种方法,我们的前两道题目是反转链表和找中间结点,看下面的图,如果是回文链表的话我们可以先找到中间结点,然后将其反转成为一个新的链表,再创建两个指针遍历链表,判断链表结点是否相等,最终以一个指针为NULL而结束。

5. 相交链表

https://leetcode.cn/problems/intersection-of-two-linked-lists/description/

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    //创建两个指针遍历链表
    ListNode* l1=headA;
    ListNode* l2=headB;
    //先计算两个链表的长度
    int sizeA=0;
    int sizeB=0;
    while(l1)
    {
        sizeA++;
        l1=l1->next;
    }
    while(l2)
    {
        sizeB++;
        l2=l2->next;
    }//得出了两个链表的长度
    //计算两数之差
    int gap=abs(sizeA-sizeB);
    //让长链表先走gap步
   
    ListNode* longlist=headA;
    ListNode* shortlist=headB;
    if(sizeA<sizeB)
    {
        longlist=headB;
        shortlist=headA;
    }
    while(gap--)
    {
        longlist=longlist->next;
    }
    //此时在同一个起点处,进行两个链表结点的比较
    while(longlist&&shortlist)
    {
        if(longlist==shortlist)
        {
            return longlist;
        }
        longlist=longlist->next;
        shortlist=shortlist->next;
    }
    //链表不相等
    return NULL;
}

 6. 环形链表

https://leetcode.cn/problems/linked-list-cycle/description/

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

标签:单链,ListNode,struct,fast,next,链表,算法,数据结构,指针
From: https://blog.csdn.net/OKkankan/article/details/143608430

相关文章

  • 数据结构复习——链、链栈。
    1、栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。2、栈的常见基本操作:InitStack(&S):初始化一个空栈S。StackEmpty(S):判断一个栈是否为空,若栈为空则返回true,否则返回false。Push(&S,x):进栈(栈的插入操作),若栈......
  • 浅谈贪心算法
    浅谈贪心算法贪心算法,指在问题求解时,每一步都做出“当前看起来最好的决策”。它没有固定的算法模板,灵活性强。在OI领域,无论是入门组,还是省选,NOI,或多或少都出过贪心题。可见贪心的重要性之大。使用贪心算法解决问题,必须满足“无后效性”。满足“无后效性”不一定当前的决策......
  • 2024年最新优化算法:海市蜃楼算法(Fata Morgana Algorithm ,FATA)介绍
    海市蜃楼算法(FataMorganaAlgorithm,FATA)是2024年提出一种新型的群体智能优化算法,它的设计灵感来源于自然现象中的海市蜃楼形成过程。FATA算法通过模仿光线在不均匀介质中的传播方式,提出了两种核心策略——海市蜃楼光过滤原则(MLF)和光传播策略(LPS)——来优化搜索过程,增强算法......
  • 利用阿燑目算法训练平台实现智能任务:从数据集到算法部署的完整流程
    引言在当今的数字化时代,算法训练已成为实现智能化任务的关键环节。通过专业的算法训练平台,如阿燑目算法训练平台,用户可以轻松完成从数据准备到算法部署的整个流程,实现各种智能应用。本文将基于阿燑目算法训练平台的使用手册,详细介绍如何利用算法训练平台完成智能任务。一、创......
  • 算法训练平台的内心独白
    我是阿燑目算法训练平台,大家都说我很神秘,今天就要好好和大家絮叨絮叨到底是怎么个事儿!在数字时代,算法训练平台成为了小微科技工作者在日常工作中不可或缺的一部分。我在这里分享我的一些服务和经验,希望能给你带来一些启发。网址:https://hub.atm008.com/首先,我提供图像集自......
  • 我是阿燑目,算法训练得看我
    在人工智能的浪潮中,计算机视觉领域正经历着前所未有的变革。作为这场变革的先锋,我——阿燑目算法训练平台,应运而生,专为深度学习打造,致力于简化图像识别模型的整个生命周期,从训练到部署,我无所不包。记住我们的网址:https://hub.atm008.com/一站式解决方案,让复杂变简单企业......
  • C语言第九周课——经典算法
    目录一、冒泡法排序1.1原理1.2代码实现(以升序排序为例) 1.3逻辑 1.4分析二、二分法查找2.1原理2.2代码实现 2.3逻辑2.4算法效率分析三、素数判断3.1原理3.2代码实现3.3逻辑3.4分析一、冒泡法排序1.1原理冒泡排序(BubbleSort)是一种简单的排序算法。它重......
  • 代码随想录算法训练营第十一天|LeetCode150.逆波兰表达式求值、239.滑动窗口最大值、3
    前言打卡代码随想录算法训练营第49期第十一天 φ(゜▽゜*)♪首先十分推荐学算法的同学可以先了解一下代码随想录,可以在B站卡哥B站账号、代码随想录官方网站代码随想录了解,卡哥清晰易懂的算法教学让我直接果断关注,也十分有缘和第49期的训练营大家庭一起进步。今日题目在学......
  • 【24年新算法故障诊断】基于FVIM-DBN四向量优化深度置信网络的故障诊断(Matlab代码,评估
    本文采用四向量优化算法(FVIM,2024年新算法)优化深度置信网络DBN的超参数,形成FVIM-DBN故障诊断模型,以进一步提升其在数据分类任务中的性能。深度置信网络(DBN)是经典强大的深度神经网络,是一种具有多个隐藏层的前馈深度神经网络。它由若干堆叠的受限玻尔兹曼机(RestrictedBolt......
  • 排序算法 -堆排序
    文章目录1.堆排序(HeapSort)1.1简介1.2堆排序的步骤1.3堆排序C语言实现1.4时间复杂度1.5空间复杂度1.堆排序(HeapSort)1.1简介堆是一种特殊的完全二叉树,分为最大堆(MaxHeap)和最小堆(MinHeap)。在最大堆中,每个节点的值都大于或等于其子节点的值;在最小堆中,每个......