C语言基础数据结构习题第二辑

C语言基础数据结构习题第二辑

在这里插入图片描述

🎆个人主页:夜幕下的人海

在这里插入图片描述

今日金句:知识源于辛勤劳作,所有成就皆为刻苦努力之果。——宋庆龄

文章目录

  • 🎄一、链表特定区间的翻转
  • 🎉二、移除链表中总和为零的节点
  • 🚀三、链表数值相加
  • 🏝️四、括号的最大嵌套程度
  • 🚘五、规范字符串
  • 🏖️六、根到叶的二进制数求和
  • ⭐七、二叉树的倾斜度

🎄一、链表特定区间的翻转

题目描述:链表内指定区间翻转

在这里插入图片描述

解题思路:
1.首要处理特殊情形,若m等于n,表明反转区间仅有一个节点,无需开展任何操作,直接返回原链表的头节点head。
2.创建虚拟头节点ret,并令其next指针指向链表的头节点head。(虚拟头节点能简化边界状况的处理,比如当反转区间包含头节点时,可规避繁杂的头插操作。)
3.运用两个指针pm与pn,pn用于定位反转区间的前一个节点,pm用于定位反转区间的起始节点。
4.借助第一个for循环,将pm指向第m个节点,pn指向第m - 1个节点。
5.再通过第二个for循环,从第m个节点开始,逐个对节点进行反转,直至第n个节点。
6.最终返回虚拟头结点的下一个节点,也就是ret->next,此为反转后链表的头节点。

代码实现:

struct ListNode* reverseBetween(struct ListNode* head, int m, int n ) 
{
    struct ListNode* ret = (struct ListNode*)malloc(sizeof(struct ListNode));
    ret->next = head;
    struct ListNode* pm = ret;
    struct ListNode* pn = head;
    if(m == n)
    {
        return head;
    }
    for(int i = 0;i < m;i++)
    {
        pn = pm;
        pm = pm->next;
    }
    for(int i = m;i < n;i++)
    {
        struct ListNode* mid = pm->next;
        pm->next = mid->next;
        mid->next = pn->next;
        pn->next = mid;
    }
    return ret->next;
}

🎉二、移除链表中总和为零的节点

题目描述:从链表中删去总和值为零的节点

在这里插入图片描述

解题思路:
1.首先创建虚拟头节点ret,并将其next指针指向链表的头节点head。
2.运用指针prev从虚拟头节点开始对链表进行遍历。(prev的作用是记录当前需检查的子链表起始节点的前一个节点)
3.采用两层循环,外层循环用于遍历链表,内层循环负责检查子链表的和是否为0。
4.两层循环结束后,返回虚拟头节点ret的下一个节点,即处理后链表的头节点。

代码实现:

struct ListNode* removeZeroSumSublists(struct ListNode* head) {
    struct ListNode* ret = (struct ListNode*)malloc(sizeof(struct ListNode));
    ret->next = head;
    struct ListNode* prev = ret;
    while(prev)
    {
        int sum = 0;
        //内部计算结果
        struct ListNode* cur = prev->next;
        while(cur)
        {
            sum -= cur->val;
            if(sum == 0)
            {
                prev->next = cur->next;
            }
            cur = cur->next;
        }
        prev = prev->next;
    }
    return ret->next;
}

🚀三、链表数值相加

题目描述:链表求和

解题思路:
1.检查输入是否合法,若l1和l2均为空,则直接返回0。
2.创建虚拟头节点dummy,并初始化指针cur指向虚拟头节点,使用变量count表示进位。
3.通过while循环遍历两个链表,直至两个链表均为空。
4.在每次循环中,获取当前节点的值,创建新节点newnode,其值为计算结果,并将其连接到结果链表中。
5.若l1或l2不为空,持续判断,直至两个链表均为空。
6.若循环结束后count不为0,说明还有进位需处理,创建新节点并连接到结果链表末尾。

代码实现:

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
    if(l1 && l2 == NULL)
    {
        return 0;
    }
    struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* cur = dummy;
    //进位
    int count = 0;
    while(l1 || l2)
    {
        int val1 = (l1?l1->val:0);
        int val2 = (l2?l2->val:0);
        int sum = val1 + val2 + count;
        //获取个位
        int data = sum % 10;
        count = sum / 10;
        struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
        newnode->val = data;
        newnode->next = NULL;
        cur->next = newnode;
        cur = cur->next;
        if(l1)
        {
            l1 = l1->next;
        }
        if(l2)
        {
            l2 = l2->next;
        }
    }
    if(count)
    {
        struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
        newnode->val = count;
        newnode->next = NULL;
        cur->next = newnode;
    }
    return dummy->next;
}

🏝️四、括号的最大嵌套程度

题目描述:括号的最大嵌套深度

在这里插入图片描述

解题思路:
1.首先创建三个变量:top用于记录当前括号的嵌套层数;count用于记录最大的嵌套深度;i用于遍历字符串的索引。
2.通过while循环遍历字符串,直至遇到字符串的结束符‘\0’。
3.遇到左括号时,top加1,利用fmax函数更新count,确保count始终记录最大嵌套深度。
4.遇到右括号时,top减1。
5.循环结束后,返回count,即最大嵌套深度。

代码实现:

int maxDepth(char* s) {
    int top = 0;
    int count = 0;
    int i = 0;
    while(s[i] != '\0')
    {
        if(s[i] == '(')
        {
            top++;
            count = fmax(top,count);
        }
        else if(s[i] == ')')
        {
            top--;
        }
        i++;
    }
    return count;
}

🚘五、规范字符串

题目描述:整理字符串

在这里插入图片描述

解题思路:
1.创建三个变量,i用于遍历字符串的索引;len表示字符串的长度;top用于模拟栈的栈顶指针,初始值为-1(表示栈为空)。
2.通过循环遍历字符串,每次将当前字符放入栈中。
3.检查栈顶的两个字符是否满足相邻且大小写不同的条件,若满足则移除这两个字符,否则继续处理下一个字符。
4.循环结束后,栈中剩余字符即为结果。

代码实现:

char* makeGood(char* s) {
    int i = 0;
    int len = strlen(s);
    int top = -1;
    for(i = 0;i<len;i++)
    {
        s[++top] = s[i];
        if(top > 0)
        {
            if(abs(s[top] - s[top - 1]) == 'a' - 'A')
            {
                top -= 2;
            }
        }
    }
    s[top + 1] = '\0';
    return s;
}

🏖️六、根到叶的二进制数求和

题目描述:从根到叶的二进制数之和

在这里插入图片描述

解题思路:
1.处理特殊情况,若当前节点为空,则返回0,表示无路径。
2.若节点非空,则将当前节点的值加入路径的二进制表示中。
3.若当前节点是叶子节点,则返回当前路径的二进制值val。
4.若当前节点不是叶子节点,递归计算左子树和右子树的路径和,并将结果相加。
5.在主函数中调用Count,从根节点开始,初始路径值为0。

代码实现:

//计算左右路径之和
int Count(struct TreeNode* root,int val)
{
    if(root == NULL)
    {
        return 0;
    }
    val = (val<<1) + root->val;
    if(root->left == NULL && root->right == NULL)
    {
        return val;
    }
    return Count(root->left,val) + Count(root->right,val);
}

int sumRootToLeaf(struct TreeNode* root) {
    return Count(root,0);
}

⭐七、二叉树的倾斜度

题目描述:二叉树的坡度

在这里插入图片描述

解题思路:
1.使用辅助函数Count,用于计算以root为根的子树的所有节点值之和。
2.运用辅助函数prevOrder,通过前序遍历计算整棵树的坡度,并将结果累加到sum中。
3.在主函数中定义变量ret,表示整棵树的坡度,调用prevOrder函数从根节点开始计算整棵树的倾斜度。
4.最后返回坡度ret。

代码实现:

int Count(struct TreeNode* root)
{
    if(root == NULL)
    {
        return 0;
    }
    return Count(root->left) + Count(root->right) + root->val;
}

void prevOrder(struct TreeNode* root,int* sum)
{
    if(root == NULL)
    {
        return;
    }
    int left = Count(root->left);
    int right = Count(root->right);
    (*sum) += abs(left - right);
    prevOrder(root->left,sum);
    prevOrder(root->right,sum);
}

int findTilt(struct TreeNode* root) {
    int ret = 0;
    prevOrder(root,&ret);
    return ret;
}

今日分享到此结束啦,若觉得不错,期望能给博主来个一键三连,感激大家的支持!愿这篇文章能帮到大家,咱们下期再会!

文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/12763.html

(0)
LomuLomu
上一篇 2025 年 7 月 5 日
下一篇 2025 年 7 月 5 日

相关推荐

  • HashMap 在高并发场景下可能出现的性能问题以及如何规避这些问题

    JDK1.8 之前 HashMap 底层是 数组和链表, 之后在之前基础上加上红黑树。相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。 HashMap 在容量不…

    未分类 2025 年 1 月 6 日
    39600
  • 【Java多线程】如何使用Java多线程下载网络文件 断点续传

    如何使用Java多线程下载网络文件,并实现断点续传 在现代网络应用中,多线程下载是一种常见的技术,它可以显著提高下载速度并提供更好的用户体验。本篇文章将介绍如何使用Java实现多线程下载,并结合项目中的代码作为示例进行讲解。 1. 多线程下载的基本原理 多线程下载的基本思想是将一个文件分成多个部分,每个部分由一个线程独立下载,最后将这些部分合并成完整的文件。…

    未分类 2025 年 1 月 11 日
    34700
  • 2025最新版pycharm专业版破解教程永久激活,亲测可用2099到期

    2025最新版pycharm专业版破解教程永久激活,亲测可用2099到期 本教程适用于IDEA、PyCharm、DataGrip、Goland等,支持Jetbrains全家桶! 我们开门见山,先上最新PyCharm版本破解成功的截图,如下截图,可以看到已经成功破解到 2099 年辣,舒服! 接下来,接下来我会用图加文字, 来详细讲解如何激活 PyCharm至…

    2025 年 4 月 10 日
    4.8K00
  • 数据结构之图形概览

    一、概念 由非空的顶点有限集合 ( V )(包含 ( n>0 ) 个顶点)以及边的集合 ( E )(表示顶点之间的关系)所构成的结构。其形式化定义为 ( G=(V,E) )。 顶点(Vertex) :图中的数据元素一般被称作顶点,在下面的示意图里用圆圈来代表顶点。 边(Edge) :图中两个数据元素之间的关联关系通常叫做边,在示意图中用连接两个顶点的线…

    2025 年 7 月 25 日
    5800
  • 2025年最新IDEA激活码永久破解教程 – 支持JetBrains全家桶2099年授权

    适用于JetBrains全系列开发工具的破解方案 本教程将详细介绍如何为IntelliJ IDEA、PyCharm、DataGrip、GoLand等JetBrains系列开发工具获取永久授权。如下图所示,成功激活后有效期将延长至2099年! 本教程适用于所有操作系统平台和各个版本,下面将分步骤详细讲解激活流程。 第一步:获取IDEA官方安装包 若尚未安装,请…

    IDEA破解教程 2025 年 7 月 7 日
    10400

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信