Leetcode刷题---C语言实现初阶数据结构---单链表

1 删除链表中等于给定值 val 的所有节点

删除链表中等于给定值 val 的所有节点

给你一个链表的头节点head和一个整数val,请你删除链表中所有满足Node.val==val的节点,并返回新的头节点

输入:head = 1,2,6,3,4,5,6, val = 6

输出:1,2,3,4,5

示例 2:

输入:head = , val = 1

输出:

示例 3:

输入:head = 7,7,7,7, val = 7

输出:

思路如下

见详细代码

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode*prev=NULL;
    struct ListNode*cur=head;
    while(cur)
    {
        if(cur->val==val)
        {
            if(cur==head)
            {
                head=cur->next;
                cur=head;
            }
            // head=cur->next;
            // cur=head;
            else
            {
                prev->next=cur->next;
                cur=prev->next;
            }
        }
        else
        {
            prev=cur;
            cur=cur->next;
        }
        // else
        // {
        //     prev->next=cur->next;
        //     cur=prev->next;
        // }
    }
    return head;
}

上述注释掉的代码是我在写的时候犯的错误,大家也可以试着自己写写看会不会和我犯同样的错误

如果有其他思路可以随意发表意见!

2 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点

给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点

给你单链表的头结点head ,请你找出并返回链表的中间结点

如果有两个中间结点,则返回第二个中间结点

输入:head = 1,2,3,4,5

输出:3,4,5

解释:链表只有一个中间结点,值为3

输入:head = 1,2,3,4,5,6

输出:4,5,6

解释:该链表有两个中间结点,值分别为3和4,返回第二个结点

思路

大部分人呢第一个想到的就是先去遍历一遍链表计算出链表的长度---然后再次遍历一遍链表找到链表的的中间结点

但是如果是在面试的时候面试官让你只能遍历一次那你应该怎么处理呢?

这里运用的是快慢指针的相对速度

这时候我们可以考虑用快慢指针来作答

fast走两步,slow走一步,刚好天时地利人和走到了中间结点的位置

详细代码

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
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;
}

3 输入一个链表,输出该链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点

描述

输入一个链表,输出该链表中倒数第k个结点

示例1

输入:1,{1,2,3,4,5}

返回值:{5}

思路一致

这里运用的快慢指针的相对距离

解法一

cpp 复制代码
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
   struct ListNode* cur=pListHead;
   int count=0;//建立一个计数器
   if(pListHead==NULL)//如果链表为空,则返回空指针
   {
    return NULL;
   }
   while(cur)//循环遍历链表,求出链表的长度
   {
    cur=cur->next;
    count++;
   }
   if(k>0&&k<=count)//对k值的合理性进行判断
   {
    int pos=count-k;//求出循环的次数
   while(pos)
   {
    pListHead=pListHead->next;
    pos--;
   }
   return pListHead;//找到就返回目标结点
   }
   return NULL;
}

解法二

cpp 复制代码
//计数法 时间复杂度:0(n) 空间:O(1)
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) 
{
    // write code here
    if(pListHead == NULL || pListHead->next == NULL)
    //若链表没有结点或只有一个结点时返回(第二条件不必须)
    {
        return pListHead;
    }
    int nodenums = 0;//记录总结点数(第一次遍历)
    int returnnums = 0;//第二次遍历(每经过一次结点,前置+1)用于排查K结点
    struct ListNode* cur = pListHead;
    while(cur != NULL)//计数遍历
    {
        nodenums++;
        cur = cur->next;
    }
     if(k>nodenums)//如果k>总结点数,则代表不存在这一结点,返回空
    {
        return NULL;
    }
    struct ListNode* pwe = pListHead;
    while(pwe != NULL)//第二次遍历,寻找倒数K点
    {
        ++returnnums;//每经过一个结点就+1
         if(nodenums-returnnums < k)
        //如果结点总数减去当前结点数小于K,那么这个结点就是倒数K结点;
        {
            break;
        }
        pwe = pwe->next;
    }
    return pwe;
}

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

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

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

输入:l1 = 1,2,4, l2 = 1,3,4

输出:1,1,2,3,4,4

示例 2:

输入:l1 = , l2 =

输出:

示例 3:

输入:l1 = , l2 = 0

输出:0

思路

本质上是结构体指针的地址和成员变量next的相互赋值,这里也涉及到了链表的尾插,直接套用就可以了,前提是掌握好了链表的增删查改基本逻辑

代码演示

cpp 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    if(list1==NULL)
    {
        return list2;
    }
    else if(list2==NULL)
    {
        return list1;
    }
    //定义一个head和tail
    //head和tail最初都置为NULL
    //tail=tail->next
    //尾部插入
    struct ListNode*head=NULL;
    struct ListNode*tail=NULL;
    while(list1&&list2)
    {
        //取小的尾部插入
        if(list1->val<list2->val)
        {
            if(tail==NULL)
            {
                head=tail=list1;
                //tail=tail->next;
            }
            else
            {
                tail->next=list1;
                tail=tail->next;
            }
            list1=list1->next;   
        }
        else
        {
            if(tail==NULL)
            {
                head=tail=list2;
            }
            else
            {
                tail->next=list2;
                tail=tail->next;
            }
            list2=list2->next; 
        }
    }
    if(list1)
    {
        tail->next=list1;
    }
    else if(list2)
    {
        tail->next=list2;
    }
    return head;
}
相关推荐
8Qi82 小时前
LeetCode 235. 二叉搜索树的最近公共祖先(LCA)
算法·leetcode·二叉树·递归·二叉搜索树·lca·迭代
是阿建吖!3 小时前
【Linux】信号
android·linux·c语言·c++
sugar__salt3 小时前
从栈队列数据结构到JS原型面向对象全解
前端·javascript·数据结构
三品吉他手会点灯4 小时前
C语言学习笔记 - 43.运算符与表达式 - 运算符1 - 运算符的分类和简单介绍
c语言·笔记·学习·算法
8Qi84 小时前
LeetCode 494:目标和(Target Sum)—— 题解 ✅
算法·leetcode·职场和发展·动态规划·01背包
froyoisle5 小时前
CSP-J 历年复赛 T1 及解析(2019~2025)
数据结构·c++·算法·csp-j·csp·算法竞赛·信息学
喜欢打篮球的普通人6 小时前
LLVM 后端流程与关键数据结构:从 IR 到机器码的入门笔记
java·数据结构·笔记
wuminyu6 小时前
Java锁机制之轻量级锁判断与尝试逻辑源码剖析
java·linux·c语言·jvm·c++
Misnearch6 小时前
1、数组/字符串
java·数据结构·算法
008爬虫实战录7 小时前
【数据结构】 树、二叉树、完全二叉树,先序遍历、中序遍历、后序遍历
数据结构·算法