您好,欢迎来到九壹网。
搜索
您的当前位置:首页数据结构初阶-单链表题目1

数据结构初阶-单链表题目1

来源:九壹网

1.移除链表元素

题目链接:https://leetcode.cn/problems/remove-linked-list-elements/description/

题目思路:创建一个新的链表,链表头为newHead,链表尾为newTail,再创建一个指针变量遍历原链表,把值不为val的结点进行尾插,注意,如果我们在结束循环时,要把newTail->next=NULL,否则会报错。

struct ListNode* removeElements(struct ListNode* head, int val)
{

    struct ListNode* newHead, * newTail, * pcur;
    pcur = head;
    newHead = newTail = NULL;
    while (pcur)
    {
        if (pcur->val != val)
        {
            if (newHead == NULL)
            {
                newHead = newTail = pcur;
            }
            else
            {
                newTail->next = pcur;
                newTail = newTail->next;
            }
        }
        pcur = pcur->next;
    }
    if(newTail)
    {
        newTail->next = NULL;
    }
    return newHead;
}

这个代码可以通过,但是为什么我们没单独讨论链表为空的情况?1.我们如果在开始加判断是否为空的情况,确实可以避免原链表为空的情况,但是我们如果像if(newTail)的判断,则如果链表为空的情况,newTail本来为NULL,这样就不用分情况讨论了。2.如果我们原链表的所有val都为val,则我们新链表为空,这种情况我们还要再判断一次,所以我们干脆直接只判断newTail是否为NULL就可以了,所以那个if不能省略。即使新链表为空,也会正确得出结果。

2.反转链表

题目链接:https://leetcode.cn/problems/reverse-linked-list/description/

思路1:我们可以像上题一样通过创建新链表的方式来反转链表,但是这样如何改?

首先我们需要一个空链表为newHead,这个newHead一直在变,而我们需要创建一个指针pre,这个指针pre指向这个新链表的下一个结点,这个指针初始化为NULL,然后再创建一个指针遍历原链表,这个指针相对于newHead,开始循环的时候就已经走向了newHead->next,这个然后再把newHead->next指向pre,最后再把pre赋值为newHead,然后再把之前保存的newHead->next的指针赋值给newHead,代码如下:

struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* newHead = head, * pre = NULL;
    while (newHead)
    {
        struct ListNode* save = newHead->next;
        newHead->next = pre;
        pre = newHead;
        newHead = save;
    }
    return pre;
}

思路2:创建三个指针,n1为NULL,n2为head,n3-=n2->next,然后n1先走到n2,n2走到n3,n3指向n3的下一个结点,n1为头结点,代码如下:

struct ListNode* reverseList(struct ListNode* head)
{
    if (head == NULL)
    {
        return head;
    }
    struct ListNode* n1, * n2, * n3;
    n1 = NULL;
    n2 = head;
    n3 = head->next;
    while (n2)
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        //n3 = n3->next;
        //不能这样写,如果n3到原链表的尾结点,就不存在n2->next了
        if (n3)
        {
            n3 = n3->next;
        }
    }
    return n1;
}

3.链表的中间结点

题目链接:https://leetcode.cn/problems/middle-of-the-linked-list/description/

我们如何找中间结点:

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

但是我们要注意一个问题,我们可以把循环条件里面的fast和fast->next调换位置吗?

这个不行,如果调换位置,如果fast为NULL,就没有fast->next了,所以我们不能这样,&&是从左往右执行的,如果前面条件不成立就不会执行第二个条件的判断

4.合并两个有序链表

题目链接:https://leetcode.cn/problems/merge-two-sorted-lists/description/

如何合并?

创建一个新链表,然后比较两个链表的首结点所存储的数据,然后把这个比较小的数据的结点进行尾插,注意:最后我们需要把没有插入的结点进行尾插。如果有个链表为空,我们直接返回另外一个链表的首结点。有:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if (list1 == NULL)
    {
        return list2;
    }
    if (list2 == NULL)
    {
        return list1;
    }
    struct ListNode* l1, * l2, * newHead, * newTail;
    l1 = list1;
    l2 = list2;
    newHead = newTail = NULL;
    while (l1 && l2)
    {
        if (l1->val < l2->val)
        {
            if (newHead == NULL)
            {
                newHead = newTail = l1;
            }
            else
            {
                newTail->next = l1;
                newTail = newTail->next;
            }
            l1 = l1->next;
        }
        else
        {
            if (newHead == NULL)
            {
                newHead = newTail = l2;
            }
            else
            {
                newTail->next = l2;
                newTail = newTail->next;
            }
            l2 = l2->next;
        }
    }
    if (l1)
    {
        newTail->next = l1;
    }
    else
    {
        newTail->next = l2;
    }
    return newHead;
}

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if (list1 == NULL)
    {
        return list2;
    }
    if (list2 == NULL)
    {
        return list1;
    }
    struct ListNode* l1, * l2, * newHead, * newTail;
    l1 = list1;
    l2 = list2;
    newHead = newTail = (struct ListNode*)malloc(sizeof(struct ListNode));
    while (l1 && l2)
    {
        if (l1->val < l2->val)
        {
            newTail->next = l1;
            newTail = newTail->next;
            l1 = l1->next;
        }
        else
        {
            newTail->next = l2;
            newTail = l2;
            l2 = l2->next;
        }
    }
    if (l1)
    {
        newTail->next = l1;
    }
    else
    {
        newTail->next = l2;
    }
    newTail = newHead->next;
    //但是我们的头结点不是有效的,所以我们不能直接返回newHead,要保存其下一个结点
    free(newHead);
    newHead = NULL;
    return newTail;
}

5.链表分割

题目链接:https://nowcoder.com/practice/0e27e0b0de4eacac178676ef9c9d70

不要看这个代码只能用C++或Java写,但是C与C++差不多,如果要按照我的写法,要把语言改为C++

ListNode* smallHead, * smallTail, * bigHead, * bigTail;
smallHead = smallTail = (ListNode*)malloc(sizeof(ListNode));
bigHead = bigTail = (ListNode*)malloc(sizeof(ListNode));
ListNode* pcur = pHead;
while (pcur)
{
    if (pcur->val < x)
    {
        smallTail->next = pcur;
        smallTail = smallTail->next;
    }
    else
    {
        bigTail->next = pcur;
        bigTail = bigTail->next;
    }
    pcur = pcur->next;
}

今天就讲5个题目,我们不是解决这一个题目这么简单,要学会这里面的算法,不能只解决完题目就可以了,我们也要知道其中的含义。12.30我将发布下一个单链表题目的解答。喜欢的可以一键三连哦。所有代码如下,要的自取:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>

struct ListNode* removeElements(struct ListNode* head, int val) 
{
    if (head == NULL)
    {
        return head;
    }
    struct ListNode* newHead, * newTail, * pcur = head;
    newHead = newTail = NULL;
    while (pcur)
    {
        if (newHead == NULL)
        {
            newHead = pcur;
            newTail = pcur;
        }
        else
        {
            newTail->next = pcur;
            newTail = newTail->next;
        }
        pcur = pcur->next;
    }
    newTail->next = NULL;
    return newHead;
}
struct ListNode* removeElements(struct ListNode* head, int val) 
{
    if (head == NULL)
    {
        return head;
    }
    struct ListNode* newHead, * newTail, * pcur;
    pcur = head;
    newHead = newTail = NULL;
    while (pcur)
    {
        if (pcur->val != val)
        {
            if (newHead == NULL)
            {
                newHead = newTail = pcur;
            }
            else
            {
                newTail->next = pcur;
                newTail = newTail->next;
            }
        }
        pcur = pcur->next;
    }
    newTail->next = NULL;
    return newHead;
}
struct ListNode* removeElements(struct ListNode* head, int val)
{

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 91gzw.com 版权所有 湘ICP备2023023988号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务