【C语言】递归复杂度与链表OJ之双指针

news2025/3/3 5:26:25

【C语言】递归复杂度与链表OJ之双指针

🔥个人主页大白的编程日记

🔥专栏数据结构


文章目录

  • 【C语言】递归复杂度与链表OJ之双指针
    • 前言
    • 一.递归复杂度
      • 1.1递归时间复杂度
      • 1.2递归空间复杂度
    • 二.链表OJ之双指针
      • 2.1倒数第K个节点
      • 2.2链表的中间节点
      • 2.3反转链表
      • 2.4回文链表
      • 2.5相交链表
      • 双指针法
    • 后言

前言

哈喽,各位小伙伴大家好!今天我们继续深入探讨递归的复杂度和链表OJ常见的双指针法。话不多说,咱们进入正题!向大厂冲锋!

一.递归复杂度

1.1递归时间复杂度

前面我们讲的复杂度没有涉及到递归,那递归的复杂度又该如何计算呢?

// 计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{
 if(0 == N)
    return 1;
 return Fac(N-1)*N;
}


之前我们都是在一个函数中算时间算复杂度,但是递归会自己调用自己,所以递归的时间复杂度计算就需要把每次函数调用次数累加起来。

那我们现在修改一下代码,现在的时间复杂度又是多少呢?

// 计算阶乘递归Fac的时间复杂度?
long long Fac(size_t N)
{
	if (0 == N)
		return 1;
	for (int i = 0; i < N; i++)
	{
		;
	}
	return Fac(N - 1) * N;
}


函数的调用次数不变,每次函数调用的复杂度改变。将每次函数调用的消耗相加
,时间复杂度函数为等差数列。大O渐进表示法算出O(N^2)。

结论:递归时间复杂度==所有递归递归调用次数累加。

现在我们再来计算一下斐波那契数列的时间复杂度。

// 计算斐波那契递归Fib的时间复杂度?
long long Fib(size_t N)
{
 if(N < 3)
 return 1;
 
 return Fib(N-1) + Fib(N-2);
}

这里我们需要画出递归展开图,然后发现调用次数是等比数列。
再用错位相减法计算调用次数即可。实际调用次数没那么多。
但是也是O(2^N)的量级。

1.2递归空间复杂度

那递归的复杂度又该如何计算呢?

  • 阶乘
    递归会调用函数,每次调用函数都会开辟栈帧。
    所以递归的空间复杂度是函数调用的次数。
// 计算阶乘递归Fac的空间复杂度?
long long Fac(size_t N)
{
 if(N == 0)
 return 1;
 
 return Fac(N-1)*N;
}

  • 斐波那契数列
// 计算斐波那契递归Fib的空间复杂度?
long long Fib(size_t N)
{
 if(N < 3)
 return 1;
 
 return Fib(N-1) + Fib(N-2);
}

斐波那契数列的递归是双倍递归,那他的空间复杂度该如何计算呢?

因为函数栈帧会重复利用,所以斐波那契数列的空间复杂度就是O(N)。

二.链表OJ之双指针

2.1倒数第K个节点

  • 题目
    倒数第k个节点

  • 思路分析


我们先让快慢指针拉开k步,当快指针到NULL节点,慢指针就是倒数第K个节点。

  • 代码
typedef struct ListNode ListNode;
int kthToLast(struct ListNode* head, int k)
{
    ListNode* slow,*fast;
    slow=fast=head;
    while(k--)
    {
        fast=fast->next;
    }
    while(fast)
    {
        fast=fast->next;
        slow=slow->next;
    }
    return slow->val;
}

2.2链表的中间节点

  • 题目
    链表的中间节点
  • 思路分析
    我们可以定义两个指针,一个每次走一步,一个每次走两步。

这就是我们的快慢指针。两个指针走的路程是2倍关系,当快指针走完时,慢指针也走了快指针的一半路程。

  • 代码
 typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head)
 {
    //创建快慢指针
    struct ListNode* slow;
    struct ListNode* fast;
    slow=fast=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    //此时slow指向中间节点
    return slow;
 }

2.3反转链表

  • 题目
    反转链表
  • 思路
  • 我们创建三个节点指针n1,n2,n3。n1刚开始指向NULL,n2指向头节点,n3保存n2的下一个几点。每次都让n2指向n1,然后n1移动到n2,n2移动到n3.n3向后移动。当n2走到尾节点就完成反转。
  • 代码
 typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {
    if(head==NULL)
      return NULL;
    ListNode* n1=NULL;
    ListNode* n2=head;
    ListNode* n3=head->next;
    while(n2)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
          n3=n3->next;
    }
    return n1;
}

2.4回文链表

  • 题目
    回文链表

  • 思路

  • 我们先找到中间节点,反转以中间节点为头节点的子链表。然后分别从头节点和中间节点开始遍历,一一对比,当中间节点走到NULL时,说明是回文链表。
    在这里插入图片描述

  • 代码

typedef struct ListNode ListNode;
 struct ListNode* reverseList(struct ListNode* head)
{
    //创建三个指针
  ListNode *n1,*n2,*n3;
  n1=NULL;
  n2=head;
  if(n2)
   n3=n2->next;
  while(n2)
  {
    n2->next=n1;
    n1=n2;
    n2=n3;
    if(n3)
      n3=n3->next;
  }
  return n1;
}
struct ListNode* middleNode(struct ListNode* head)
 {
    //创建快慢指针
    struct ListNode* slow;
    struct ListNode* fast;
    slow=fast=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    //此时slow指向中间节点
    return slow;
 }
bool isPalindrome(struct ListNode* head) 
{
    ListNode* mid=middleNode(head);//找到中间节点
    ListNode* reverse=reverseList(mid);//反转后面节点
    ListNode*pcur=head;
    while(reverse)
    {
        if(pcur->val!=reverse->val)//匹配
        {
            return false;
            break;
        }
        reverse=reverse->next;//移动
        pcur=pcur->next;
    }
    return true;
}

2.5相交链表

  • 题目
    相交链表

  • 思路

  • 判断相交
    分别遍历两个链表到尾节点,判断尾节点地址是否相等。相等就相交

  • 找交点
    让长链表走两链表长度的差距步,此时两节点距离交点差距相等。两节点同时往后遍历,相遇的位置就是交点。

  • 代码
typedef struct ListNode ListNode;
struct ListNode* getIntersectionNode(struct ListNode* headA,struct ListNode* headB) {
    int lena = 0, lenb = 0;
    ListNode* pa = headA;
    ListNode* pb = headB;
    while (pa->next)
    {
        lena++;
        pa = pa->next;//遍历统计
    }
    while (pb->next)
    {
        lenb++;
        pb = pb->next;//遍历统计
    }
    if (pb != pa) 
    {
        return NULL;
    }
    ListNode* pshort = headA;
    ListNode* plong = headB;
    if (lena > lenb) //假设法
    {
        plong = headA;
        pshort = headB;
    }
    int tmp = abs(lena - lenb);
    while (tmp--) 
    {
        plong = plong->next;//走差距步
    }
    while (plong!=pshort)
    {
        pshort = pshort->next;
        plong = plong->next;
    }
    return plong;
}

双指针法

大家发现这些题目都会用到两个指针解决问题,这就是我们说的双指针法,具体如何运用双指针,得看具体题目灵活运用。

后言

这就是递归的复杂度和链表常见OJ。今天就分享到这里,感谢大家耐心垂阅。咱们下期见!拜拜~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1822958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LangChain入门学习笔记(一)——Hello World

什么是LangChain LangChain是一个开源&#xff08;github repo&#xff09;的大语言模型应用开发框架&#xff0c;提供了一整套的工具、方法和接口去帮助程序员构建基于大语言模型的端到端应用。LangChain是长链&#xff08;long chain&#xff09;的意思&#xff0c;它的一个…

Flowable-决策表设计器

✨✨✨ 最好用的Flowable决策表设计器 ✨✨✨ 最好用的Flowable流程设计器 本文中内容和案例出自贺波老师的书《深入Activiti流程引擎&#xff1a;核心原理与高阶实战》&#xff0c;书中的介绍更全面、详细&#xff0c;推荐给大家。 深入Activiti流程引擎

深入理解渲染引擎:打造逼真图像的关键

在数字世界中&#xff0c;图像渲染是创造逼真视觉效果的核心技术。渲染引擎&#xff0c;作为这一过程中的关键组件&#xff0c;负责将二维或三维的模型、纹理、光照等数据转化为人们肉眼可见的二维图像。本文将深入探讨渲染引擎的工作原理及其在打造逼真图像中所起的关键作用。…

【Linux】常见指令的使用

文章目录 which指令stat 指令wc指令echo指令tree 指令whoami指令clear指令alias指令ls指令pwd指令cd 指令touch指令mkdir指令&#xff08;重要&#xff09;rmdir指令 && rm 指令&#xff08;重要&#xff09;man指令&#xff08;重要&#xff09;cp指令&#xff08;重要…

5-1RT-Thread互斥量

5-1RT-Thread互斥量 互斥量斥量的管理方式 互斥量 互斥量又称为互斥型信号量&#xff0c;是一种特殊的二值信号量。以超市的储物柜为例&#xff0c;当用户A存入物品并关闭柜门&#xff0c;则用户A就获得了此格柜子的使用权。此时其他用户无法使用此个柜子&#xff0c;只有当用户…

java-多态数组的多态参数

介绍 代码 employer父类 package hansunping;public class employer {private String name;private double salary;public employer(String name,double salary) {this.namename;this.salarysalary;// TODO Auto-generated constructor stub}public double getsalary() {retu…

[C#]使用C#部署yolov10的目标检测tensorrt模型

【测试通过环境】 win10 x64vs2019 cuda11.7cudnn8.8.0 TensorRT-8.6.1.6 opencvsharp4.9.0 .NET Framework4.7.2 NVIDIA GeForce RTX 2070 Super cuda和tensorrt版本和上述环境版本不一样的需要重新编译TensorRtExtern.dll&#xff0c;TensorRtExtern源码地址&#xff1a;T…

Python基于 Jupyter Notebook 的图形可视化工具库之ipysigma使用详解

概要 在数据科学和网络分析中,图(Graph)结构是一种常用的数据结构,用于表示实体及其关系。为了方便图数据的可视化和交互操作,ipysigma 提供了一个基于 Jupyter Notebook 的图形可视化工具。通过 ipysigma,用户可以在 Jupyter Notebook 中创建、编辑和展示图结构,方便进…

Vue基础面试题(二)

文章目录 1.Vue 单页应用与多页应用的区别2.Vue template 到 render 的过程3. Vue data 中某一个属性的值发生改变后&#xff0c;视图会立即同步执行重新渲染吗&#xff1f;4.Vue的优点5.vue如何监听对象或者数组某个属性的变化6.Vue模版编译原理7. 对SSR的理解8.Vue的性能优化…

现货白银实时交易平台的成长阶段 你出在哪个阶段?

很多人喜欢在现货白银平台上做模拟交易&#xff0c;因为他们认为现货白银实时交易平台上交易太痛苦了&#xff0c;不光随时会面临风险&#xff0c;而且还可能让自己出现大的亏损。如果投资者认为痛苦&#xff0c;那笔者觉得投资者不妨将在现货白银实时交易平台上做交易&#xf…

前端数据模拟Mock.js

新建mock-demo的项目&#xff0c;安装npm install mockjs 新建index.js //引入mockjs import Mock from mockjs //设置延迟时间 // Mock.setup({ // timeout:4000 // }) //使用mockjs模拟数据 Mock.mock(/product/search,{"ret":0,"data":{"mtim…

6年前端社招一个月上岸20K经历,附简历

面经哥只做互联网社招面试经历分享&#xff0c;关注我&#xff0c;每日推送精选面经&#xff0c;面试前&#xff0c;先找面经哥 本人普通本科6年前端经历&#xff0c;从年前开始准备跳槽&#xff0c;一开始感觉自己履历算不上突出&#xff0c;经历过迷茫和沮丧的时候&#xff0…

即时聊天系统

功能描述 该项目是一个前后端分离的即时聊天项目&#xff0c;前端采用vue2、后端使用springboot以mysql8.0作为数据库。 项目功能包含了单聊、群聊功能。在此基础上增加了对好友的功能操作&#xff0c;如备注设为通知、视频聊天、语音聊天、置顶、拉入黑名单、清空聊天记录等。…

小白如何入门编程?零基础入门指南,助你一步步成为编程达人!

零基础编程入门先学什么&#xff1f;编程语言有几百种&#xff0c;我们应该怎么选择。想学习编程&#xff0c;加入互联网行业&#xff0c;哪一个更有前途&#xff1f;在小白学习编程会有各种各样的问题&#xff0c;今天小编我就来为你解答。 一、程序员的类别 程序员从事的人…

Nginx部署Vue项目css文件能加载但是不生效

目录 问题描述问题解决 问题描述 Nginx部署打包后的Vue项目css文件能加载但是不生效&#xff0c; 问题解决 查看响应标头&#xff0c;发现不对劲&#xff0c; Content-Type: text/plain正确的应该是 Content-Type: text/css根本原因是nginx没有告诉浏览器正确的文件类型 所…

如何下载proDAD V4软件及详细安装步骤

简介&#xff1a; proDAD Adorage 是一款一体化的效果库&#xff0c;完美拥有所有的效果&#xff0c;集所有Adorage卷于一体&#xff0c;该系列包含13种可用套装中的17,000多种效果。 对于每种情况都能获得完美的效果&#xff0c;支持Adobe、avid、Corel、Cyberlink、MAGIX等多…

【Android】打开需要NDK的项目的一些报错的问题解决

文章简述 在打开一个新的项目的时候&#xff0c;遇到了一些问题&#xff0c;记录一下问题的解决步骤。 问题1 FAILURE: Build failed with an exception.* What went wrong: A problem occurred configuring project :app. > NDK not configured. Download it with SDK m…

redis 06 集群

1.节点&#xff0c;这里是把节点加到集群中的操作&#xff0c;跟主从结构不同 这里是在服务端使用命令&#xff1a; 例子&#xff1a; 2.启动节点 节点服务器 首先&#xff0c;先是服务器节点自身有一个属性来判断是不是可以使用节点功能 一般加入集群中的节点还是用r…

24K 纯干干干货:深入探讨 JavaScript 中变量相等性判断

比较两个变量是否相等&#xff0c;确切得说是内容是否相等&#xff0c;首先要划分为引用数据类型之间、基本数据类型之间和引用数据类型和基本数据类型之间&#xff08;这一种使用场景比较少&#xff09;这三种情形。因为引用数据类型和基本数据类型数据存储的方式是不一样的。…

AI模型究竟应该开源还是闭源?

随着人工智能技术的飞速发展&#xff0c;关于AI模型是否应该开源的问题引起了广泛关注。特别是最近Elon Musk对OpenAI及其领导层提起诉讼&#xff0c;指责其违背了开源的初心&#xff0c;这一争论变得更加激烈。在这篇博客中&#xff0c;我们将探讨开源与闭源AI模型的优缺点&am…