单链表算法经典OJ题

简介: 单链表算法经典OJ题

1、移除链表元素

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

typedef struct ListNode LSNode;
struct ListNode* removeElements(struct ListNode* head, int val){
    LSNode* newHead,*newTail;
    //令头结点和尾结点都置为空
    newHead = newTail = NULL;
    //令新指针pcur指向原链表的头结点head,遍历原链表
    LSNode* pcur = head;
    while(pcur)
    {
        //当不满足.val==val时,开始向新建的空链表中插入
        if(pcur->val != val)
            {
                //1、如果新建的链表为空,插入的新节点就是链表的头结点和尾结点
                if(newHead == NULL)
                    {
                        newHead = newTail = pcur;
                    }
                //2、如果新建的链表不为空,直接尾插,让新插进来的结点作为新的尾结点
                else
                    {
                        newTail->next = pcur;
                        newTail = newTail->next;//令newTail移位
                    }
            }
        //当满足pcru->val = val,直接跳过进行下一个读取即可
        pcur = pcur->next;
    }
    //当pcur指向存储整数6的结点时,pcur满足pcur.val = val不会进入if,直接执行pcur = pcur->next,此时pcur = NULL
    //pcur为NULL,跳出while循环,如果此时直接返回newHead那么新链表的newTail->next指向的位置仍是旧链表存储数据6
    //的结点,所以此时需要再判断newTail是否为空,如果不为空则让它最后指向的方向置为空,最后再返回头结点
    if(newTail)
        newTail->next = NULL;
    return newHead;
}

2、翻转链表

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

typedef struct ListNode LSNode;
struct ListNode* reverseList(struct ListNode* head)
{
    //如果传入的链表为空的时候直接返回NULL
    if(head == NULL)
    {
        return NULL;
    }
     LSNode* n1,*n2,*n3;
     n1 = NULL; n2 = head;n3 = head->next;
     while(n2)
     {
         n2->next = n1;
         n1 = n2;
         //当n3为空时已经将n3的值交给n2
         n2 = n3;
         //当n3所处的位置不为空时才能接着移动n3,否则结束一次while循环
         if(n3)
            n3 = n3->next;
     }
     //此时n1为链表的头
    return n1;
}

3、合并两个有序链表

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

typedef struct ListNode LSNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    //当传入的两个链表其中有一个为空,那么返回另一个链表即可
    if(list1 == NULL)
    {
        return list2;
    }
    if(list2 == NULL)
    {
        return list1;
    }
    //当两个链表都不为空时,遍历链表
    LSNode* cur1 = list1;
    LSNode* cur2 = list2;
    //创建新的空链表--带头(结点)单向不循环链表(后续进行尾插等情况就不需要考虑头结点是否为空的情况,减少重复代码)
    LSNode* newHead,*newTail;
    //malloc创建一个内存空间,该空间不含有效数据,刚好用于存放该链表的头结点(头结点的有空间但是不存储有效数据)
    newHead = newTail = (LSNode*)malloc(sizeof(LSNode));
    //当两个结点有一个走到空就不能进行比较了
    while(cur1 && cur2)
    {
        //把值小的结点尾插到新的链表
        if(cur1->val < cur2->val)
            {
            newTail->next = cur1;
            newTail = newTail->next;
            cur1 = cur1->next;
            }
        //当cur2->val <= cur1->val时
        else
        {
            newTail->next = cur2;
            newTail = newTail->next;
            cur2 = cur2->next;
        }
    }
if(cur1)
    newTail->next = cur1;
if(cur2)
    newTail->next = cur2;
return newHead->next;
}

4、获取链表的中间结点

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

typedef struct ListNode LSNode;
struct ListNode* middleNode(struct ListNode* head)
{   
    if(head == NULL)
        return NULL;
    //快慢指针
    LSNode* slow,*fast;
    slow = fast = head;
    //只要fast和fast->next有一个为空则停止循环
    //因为我们也不知道链表的结点数是奇数还是偶数
    while(fast && fast->next)
    //注意二者判断顺序不能交换,因为如果链表结点数为偶数时最后一次循环 
    //fast指向的位置刚好空,下次循环前判断时,由于fast以及指向空了,更别提fast->next了
    //虽然此时slow指向了我们想要的位置但是由于fast->next本身就不合理程序就会报错
    //当然如果是奇数个就可以交换
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    //当循环结束时,slow必定指向我们要找的链表中间结点
    return slow;
}

5、环形链表解决约瑟夫问题

环形链表的约瑟夫问题_牛客题霸_牛客网 (nowcoder.com)

#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode ListNode;
//申请链表结点函数,同时为结点中添加数据x
ListNode* ListByNode(int x)
{
    ListNode* node = (ListNode*)malloc(sizeof(ListNode));
    if(node == NULL)
    {
        perror("malloc fail!");
        exit(1);
    }
    node->val = x;
    node->next = NULL;
    return node;
}
//创建带环链表
ListNode* CreateList(int n)
{
    ListNode* phead = ListByNode(1);
    ListNode* pTail = phead;
    for(int i = 2;i<=n;i++)
    {
        ListNode* node = ListByNode(i);
        pTail->next = node;
        pTail = pTail->next;
    }
    //以上只是在创建单链表,想要让链表成环,需要将尾结点和头结点相连
    pTail->next = phead;
    //这里直接返回尾结点因为有尾结点就能直接找到头结点,返回头结点的话还需要遍历链表才能找到尾结点
    return pTail;
}
//实现函数
int ysf(int n, int m ) {
    //创建不带头单向循环链表
    ListNode* prev = CreateList(n);
    //进行游戏逻辑实现
    ListNode* cur = prev->next;//就是头结点
    int count = 1;
    while (cur->next != cur) 
    {
        if(count == m)
        {
            //删除结点
            prev->next = cur->next;
            free(cur);
            cur = prev->next;
            count = 1;//人死后记得让下一个人从1开始报数(count重置为初始值1)
        }
        else 
        {
            //继续向下报数
            prev = cur;
            cur = cur->next;
            count++;
        }
    }
    //此时链表中只剩下一个结点,返回该结点中的数
    return cur->val;
}

6、分割链表

面试题 02.04. 分割链表 - 力扣(LeetCode)

typedef struct ListNode ListNode; 
struct ListNode* partition(struct ListNode* head, int x)
{
    if(head == NULL)
        return head;
    //创建带头的大小链表
    ListNode* lessHead,*lessTail;
    ListNode* greatHead,*greatTail;
    //创建大小链表的哨兵位
    lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));
    greatHead = greatTail = (ListNode*)malloc(sizeof(ListNode));
    //遍历原链表,将结点放到大小链表中
    ListNode* cur = head;
    //当cur读取原链表后循环结束
    while(cur)
    {   
        //放入小链表
        if(cur->val < x)
        {
            lessTail->next = cur;
            lessTail = lessTail->next;
        }
        //放入大链表
        else
        {
            greatTail->next = cur;
            greatTail = greatTail->next;
        }
        cur = cur->next;  //cur向后走
    }
    //原链表循环结束此时greatTail后指向的内容并未被置空所以要判断
    if(greatTail)
        greatTail->next = NULL;
    //小链表的尾和大链表的哨兵位的下一个结点连接起来
    lessTail->next = greatHead->next;
    return lessHead->next;
}

~over~

相关文章
|
3月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
55 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
5月前
|
算法 索引
【初阶数据结构篇】单链表算法题进阶
深拷贝应该正好由 n 个全新节点组成,其中每个新节点的值都设为其对应的原节点的值。
36 0
|
7月前
|
算法 分布式数据库
【数据结构和算法】--- 二叉树(5)--二叉树OJ题
【数据结构和算法】--- 二叉树(5)--二叉树OJ题
47 1
|
7月前
|
机器学习/深度学习 算法 C语言
【C/数据结构与算法】:10道链表经典OJ
【C/数据结构与算法】:10道链表经典OJ
25 1
|
7月前
|
算法
【C/数据结构与算法】:二叉树经典OJ
【C/数据结构与算法】:二叉树经典OJ
41 0
【C/数据结构与算法】:二叉树经典OJ
|
7月前
|
算法 程序员 数据处理
【数据结构与算法】使用单链表实现队列:原理、步骤与应用
【数据结构与算法】使用单链表实现队列:原理、步骤与应用
|
7月前
|
算法 C语言
【数据结构与算法 经典例题】返回单链表的倒数第 k 个节点
【数据结构与算法 经典例题】返回单链表的倒数第 k 个节点
|
7月前
|
存储 算法 C语言
【数据结构与算法】深入理解 单链表
【数据结构与算法】深入理解 单链表
|
8月前
|
存储 算法 C语言
数据结构与算法②(复杂度相关OJ)(六道数组OJ题)(上)
数据结构与算法②(复杂度相关OJ)(六道数组OJ题)
63 2
|
8月前
|
存储 算法 IDE
数据结构与算法⑯(第四章_下)二叉树的层序遍历+判断完全二叉树+一道OJ
数据结构与算法⑯(第四章_下)二叉树的层序遍历+判断完全二叉树+一道OJ
58 1

热门文章

最新文章