算法效率的判断及一些典型例题的讲解

news2024/11/18 7:49:09

一.算法效率

1.用处:判断算法的好坏,好的算法应该是高效的

2算法效率取决于时间复杂度和空间复杂度

<1>时间复杂度

    1.1概念:算法中基本操作的执行次数就是算法的时间复杂度

    1.2表示:大O的渐进表示法,例如O(N)

    1.3计算:以最坏运行情况算出可能需要执行的最多操作数的表达式,只保留最高阶项,并舍弃                      其系数

    1.4例子说明

    1.5常见的时间复杂度

O(1)常数阶
O(N)线性阶
O(N^2)平方阶
O(logN)对数阶例如:二分查找的空间复杂度为O(logN)
O(nlogn)nlogn阶
O(2^n)指数阶

例如:使用递归法计算斐波那契数,时间复杂度为O(2^n)

当时间复杂度为指数阶时,说明该方法不适用与解题,效率太低

<2>空间复杂度

     2.1概念:是对运行过程中额外开辟空间大小的度量

     2.2表示:大O的渐进表示法,例如O(1)

     2.3计算:数在实现程序的过程中共额外开辟了多少个变量,保留最高阶项,并舍弃其系数

     2.4例子说明:

     2.5常见的空间复杂度:

O(1)开辟有限的变量
O(N)新开辟了一个数组
O(N^2)

二.典型例题

1.旋转数组

  1.1题目介绍:给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

. - 力扣(LeetCode)

  1.2解法

  <1>逐个旋转

        1.1思路讲解:将尾部的数据拿下来,再将其他元素向后挪一位,最后将拿下来的数据放在头                                 部,重复操作,直至完成轮转(注意:当传入的k大于数组大小时会进行一些轮                                 回,可以先将k%数组大小,保证k<数组大小,提高效率;在进行数组往后操                                   作时需要从后往前操作)

        1.2时间复杂度:O(N^2)     空间复杂度:O(1)

        1.3代码实现

void rotate(int* nums, int numsSize, int k) {
    k%=numsSize;//避免重复操作
    int tmp=0;
    while(k--)
    {
        tmp=nums[numsSize-1];
        for(int i=numsSize-1;i>0;i--)
        {
            nums[i]=nums[i-1];
        }
        nums[0]=tmp;
    }
}

 <2>分三段逆置

        2.1思路讲解:封装一个函数用于将数组逆置,在进行轮转的位置将原数组视为两部分分别逆                                 置,最后将整个数组逆置即可(注意当传入的k大于数组大小时会进行一些轮                                     回,可以先将k%数组大小,保证k<数组大小,提高效率)

        2.2时间复杂度:O(N)     空间复杂度:O(1)

        2.3代码实现

//数组逆置
void reverse(int* nums,int left,int right)
{
    int tmp=0;
    while(left<right)
    {
        tmp=nums[left];
        nums[left]=nums[right];
        nums[right]=tmp;
        left++;
        right--;
    }
}

void rotate(int* nums, int numsSize, int k) {
    k%=numsSize;//避免重复操作
    reverse(nums,0,numsSize-k-1);
    reverse(nums,numsSize-k,numsSize-1);
    reverse(nums,0,numsSize-1);
}

<3>创建一个新数组

        3.1思路讲解:创建一个新数组,先按要轮转的位置将数据先后拷贝至新数组中,最后将新数                                 组的元素拷贝回原数组

        3.2时间复杂度:O(N)     空间复杂度:O(N)

        3.3代码实现

void rotate(int* nums, int numsSize, int k) {
    k%=numsSize;//避免重复操作
    int arr[]={0};
    int i=0;
    for(i=numsSize-k,j=0;i<numsSize;i++,j++)
    {
        arr[j]=nums[i];
    }
    for(i=0;i<numsSize-k;i++,j++)
    {
        arr[r]=nums[i];
    }
    for(i=0;i<numsSize;i++)
    {
        nums[i]=arr[i];
    }
}

2.找两个链表是否有公共节点,若有返回第一个公共节点的地址

2.1题目介绍:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始                         节点。如果两个链表不存在相交节点,返回 null 。

. - 力扣(LeetCode)

2.2解法

<1>思路:1.判断是否两链表相交:看他们的尾结点的地址是否相同,若相同则相交

                 2.找出较长的链表与较短链表的差值,让长链表先走差值步,再让两链表同时走,当他                      们指向的空间相同时,即是第一个公共节点处

<2>时间复杂度:O(N)       空间复杂度:O(1)

<3>代码实现

typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    //判断是否有公共节点
    ListNode* A=headA;
    ListNode* B=headB;
    int len1=0;
    int len2=0;
    while(A)
    {
        A=A->next;
        len1++;
    }
    while(B)
    {
        B=B->next;
        len2++;
    }
    if(A!=B)
    {
        return NULL;
    }
    else
    {
        int gap=abs(len1-len2);
        ListNode* greatlist=headA;
        ListNode* shortlist=headB;
        if(len1<len2)
        {
            greatlist=headB;
            shortlist=headA;
        }
        //先让长链表走直至弥补两链表的差距
        while(gap--)
        {
            greatlist=greatlist->next;
        }
        while(greatlist && shortlist)
        {
            if(greatlist==shortlist && greatlist->val==shortlist->val)
            {
                return greatlist;
            }
            greatlist=greatlist->next;
            shortlist=shortlist->next;
        }
        return NULL;
    }

    
}

3.判断链表是否带环

<1>题目介绍:给你一个链表的头节点 head ,判断链表中是否有环。

. - 力扣(LeetCode)

<2>思路:定义slow,fast两个指针,slow走一步,fast走两步,若在某时刻slow=fast,则说明链表                中带环

<3>方法证明

<4>代码实现

typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) {
    ListNode* fast=head;
    ListNode* slow=head;
    while(fast!=NULL)
    {
        slow=slow->next;
        if(fast->next==NULL)
        {
            return false;
        }
        else
        {
            fast=fast->next->next;
        }
        if(slow==fast)
        {
            return true;
        }
    }
    return false;

    
}

<5>拓展:Q:当fast=3*slow时,可以用来判断是否带环吗?

                 A:可以

                 Q:当fast=4*slow呢?

                 A:可参考上述分析,这里就不在一一证明了

4.返回带环链表进入环时的第一个节点地址

<1>题目介绍:给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

. - 力扣(LeetCode)

<2>思路:先判断是否为带环链表,记录slow和fast相遇时的位置,让cur指向头节点,meet位相                    遇的位置,让meet和cur同时开始走,当meet和cur相等时,cur刚好位于入环的第一个                    节点处

<3>方法证明:

<4>代码实现:

typedef struct ListNode ListNode;
ListNode* hasCycle(ListNode *head) {
    ListNode* fast=head;
    ListNode* slow=head;
    while(fast!=NULL)
    {
        slow=slow->next;
        if(fast->next==NULL)
        {
            return NULL;
        }
        else
        {
            fast=fast->next->next;
        }
        if(slow==fast)
        {
            return slow;
        }
    }
    return NULL;
}

struct ListNode *detectCycle(struct ListNode *head) {
    ListNode* cur=head;
    ListNode* meet=hasCycle(head);
    if(meet==NULL)
    {
        return NULL;
    }
    else
    {
        while(cur)
        {
            if(cur==meet)
            {
                return cur;
            }
            cur=cur->next;
            meet=meet->next;
        }
        return NULL;
    }
}

5.随机链表的复制

<1>题目介绍:

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个全新节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。

. - 力扣(LeetCode)

<2>思路:先开辟新节点,将其连在原链表的每个节点后面,再对新节点的random进行赋值,最后将原链表与拷贝链表分离

<3>代码实现:

typedef struct Node Node;
struct Node* copyRandomList(struct Node* head) {
    if(head==NULL)
    {
        return NULL;
    }
    Node* cur=head;
    //遍历原链表,复制其内容并插在原节点的后面
    while(cur)
    {
        Node* copy=(Node*)malloc(sizeof(Node));
        copy->val=cur->val;
        copy->next=cur->next;
        copy->random=NULL;
        cur->next=copy;
        cur=copy->next;
    }
    //再遍历链表,设置随机指针
    cur=head;
    while(cur)
    {
        Node* copy=cur->next;
        if(cur->random)
        {
            copy->random=cur->random->next;
        }
        cur=copy->next;
    }

    //将复制的链表和原链表分隔开
    Node* newhead=NULL,*prev,*next;
    cur=head;
    while(cur)
    {
        next=cur->next->next;
        if(newhead==NULL)
        {
            newhead=cur->next;
            prev=cur->next;
        }
        else
        {
            prev->next=cur->next;
            prev=cur->next;
        }
        cur->next=next;
        cur=next;
    }
    return newhead;
}

    

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

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

相关文章

什么是场内期权,场内期权是如何操作的?

今天期权懂带你了解什么是场内期权,场内期权是如何操作的&#xff1f;场内期权是标准化、规范化且在公开市场交易的金融衍生品。相比场外期权&#xff0c;场内期权具有更高的流动性和透明度。 什么是场内期权&#xff1f; 场内期权&#xff0c;也称为交易所期权&#xff0c;是…

【C++航海王:追寻罗杰的编程之路】C++11(四)

目录 1 -> 相关文章 【C航海王&#xff1a;追寻罗杰的编程之路】C11(一) 【C航海王&#xff1a;追寻罗杰的编程之路】C11(二) 【C航海王&#xff1a;追寻罗杰的编程之路】C11(三) 2 -> lambda表达式 2.1 -> C98中的一个例子 2.2 -> lambda表达式 2.3 ->…

HCIA-题目解析1

0x00 前言 遇到这样一道题,这种题目对于我来说还是比较复杂的,所以记录一下。主要还是和熟练度有关系。 0x01 题目 路由器RouterID邻居关系如下,下列说法正确的是 A:本路由器和Router-lD为10.0.3.3的路由器不能直接交换链路状态信息 B:DR路由器的Router-lD为10.0.1.2 C:…

Flutter运行项目一直:running gradle task

大体原因就是访问国外的资源由于网络等原因导致访问失败&#xff0c;解决方法就是换成国内的源 修改项目的android/build.gradle 文件&#xff0c;将里面的 google() mavenCentral()替换为 maven {allowInsecureProtocol trueurl https://maven.aliyun.com/repository/googl…

前端 CSS

目录 选择器 复合选择器 伪类-超链接 结构伪装选择器 伪元素选择器 画盒子 字体属性 CSS三大属性 Emmet写法 背景属性 显示模式 盒子模型 盒子模型-组成 盒子模型-向外溢出 盒子模型-圆角 盒子模型-阴影 flex position定位 CSS小精灵 字体图标 垂直对齐方式…

Oracle集群-常用查询及操作(工作日常整理)

1.Oracle集群状态 select * from gv$instance; 示例结果&#xff1a; 2.Oracle集群-增大表空间 常见问题&#xff1a; 导入时或使用时&#xff0c;提示无法extend table ,增加表空间即可 常用操作&#xff1a; 1&#xff09;查询表空间 select * from dba_tablespaces; --…

Redisson分布式锁,重试锁和锁续命的原理

RedissonLock 锁重试原理 tryLock有三个三个参数&#xff0c;第一个是等待时间&#xff0c;第二个是锁失效后自动释放的时间,不填默认为-1&#xff0c;第三个是时间单位&#xff1b; 当设置了第一个参数&#xff0c;那这个锁就成了可重试锁&#xff1b;获取锁失败后&#xff0c…

【redis】Redis数据类型(三)List类型

目录 List类型介绍特点 List数据结构附&#xff1a;3.2以前的版本(介绍一下压缩列表和双向链表)压缩列表ZipList双向链表LinkedList 常用命令lpush示例 lpushx示例 rpush示例 rpushx示例 LPOP示例 RPOP示例 BLPOP非阻塞行为阻塞行为相同的 key 被多个客户端同时阻塞在 MULTI/EX…

vscode 使用code runner 运行代码输出乱码

vscode 使用code runner 运行代码输出乱码 先指出问题所在&#xff1a; 代码文件使用的编码格式和终端使用的编码格式不一致&#xff0c;查看代码文件右下角&#xff0c;会显示代码文件的编码格式。 测试代码如下&#xff1a; #include<iostream> using namespace std…

专注 APT 攻击与防御—工具介绍-the-backdoor-factory

工具介绍 the-backdoor-factory 项目地址&#xff1a;GitHub - secretsquirrel/the-backdoor-factory: Patch PE, ELF, Mach-O binaries with shellcode new version in development, available only to sponsors 原理 可执行二进制文件中有大量的 00&#xff0c;这些 00 是…

计算机毕业设计python_django宠物领养系统z6rfy

本宠物领养系统主要包括两大功能模块&#xff0c;即管理员模块、用户模块。下面将对这两个大功能进行具体功能需求分析。 &#xff08;1&#xff09;管理员&#xff1a;管理员登录后主要功能包括个人中心、用户管理、送养宠物管理、地区类型管理、失信黑名单管理、申请领养管理…

瑞芯微-I2S | ALSA基础-3

针对音频设备&#xff0c;linux内核中包含了两类音频设备驱动框架&#xff1b; OSS&#xff1a;开放声音系统 包含dsp和mixer字符设备接口&#xff0c;应用访问底层硬件是直接通过sound设备节点实现的&#xff1b; ALSA&#xff1a;先进linux声音架构&#xff08;Advanced Lin…

bun 换源 国内阿里源 npmmirror 加速下载

Github https://github.com/oven-sh/bun 版本号 bun 1.1.5 windows 安装 bun 如果本机有 nodejs 环境, 可以 npm install -g bun 安装 ( 官方把 exe 已经传到了 npm 仓库, 走的国内 npm 镜像, 下载速度会很快) 没有 nodejs, 可以用 powershell 脚本安装 具体操作 全局 …

Python数据分析实验二:Python数据预处理

目录 一、实验目的与要求二、实验任务三、主要程序清单和运行结果&#xff08;一&#xff09;对chipotle.csv文件的销售数据进行分析&#xff08;二&#xff09;对描述泰坦尼克号成员的信息进行可视化和相关分析 四、实验体会 一、实验目的与要求 1、目的&#xff1a;   掌握…

python爬取网页趋势图的底层数据信息——以历年的黄金价格为例

一、问题引入 黄金价格网址&#xff1a;https://china.gold.org/goldhub/data/gold-prices 问题引入&#xff1a;现有历年的黄金价格信息&#xff08;如图所示&#xff09;&#xff0c;但呈现的方式是趋势图&#xff0c;并没有直接以表格的形式罗列出来&#xff0c;只有当鼠标悬…

家政服务小程序:家政行业的数字化转型

随着大众生活水平的提高&#xff0c;以及老龄化的加速&#xff0c;家政服务已经成为了大众生活中不可或缺的一部分。目前&#xff0c;我国家政服务市场的规模在持续扩大&#xff0c;发展前景一片大好。在日益提升的家政需求下&#xff0c;大众对家政服务的种类也逐渐多样。 为…

RuoYi-Vue-Plus (SPEL 表达式)

RuoYi-Vue-Plus 中SPEL使用 DataScopeType 枚举类中&#xff1a; /*** 部门数据权限*/DEPT("3", " #{#deptName} #{#user.deptId} ", " 1 0 "), PlusDataPermissionHandler 拦截器中定义了解析器&#xff1a; buildDataFilter 方法中根据注解的…

Vue 项目 尚品汇(一)

一、开发环境构造 Vue-cli 脚手架初始化项目 node 平台 和 webpack 和 淘宝镜像 环境 &#xff08;一&#xff09;脚手架 1.安装脚手架 在我们的项目文件夹中路径输入 cmd 然后在终端中输入 vue create app(项目名) 选择 vue 2 然后安装 &#xff08;因为是基于 vue2 开…

Object类的公共方法面试问题及回答

1. 什么是 Object 类&#xff1f; 答&#xff1a; Object 类是 Java 中所有类的超类。每个类都使用 Object 作为树的根&#xff0c;所有对象&#xff08;包括数组&#xff09;都实现这个类的方法。 2. Object 类中有哪些重要的方法&#xff1f; 答&#xff1a; equals(Obje…

上海开放大学《Java程序基础课程实验1》形考作业线上实践答案

答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 上 海 开 放 大 学 学生实验报告 分校&#xff08;站&…