算法小技巧:空间换时间,时间换空间?

news2025/4/8 19:16:38

前言:小细节,大道理,思路在前,代码在后。

名词解释:        

        算法效率:往往由时间效率和空间效率两个方面决定。

        时间效率:时间效率被称为时间复杂度,指的是算法执行过程耗费的时间。

        空间效率:空间效率被称为空间复杂度,指的是算法执行过程所耗费的最大的存储空间。 

        有时候时间效率与空间效率是相互矛盾的,要时间则要牺牲空间,要空间则要牺牲时间。而两者的衡量选择,往往是需要我们人来决定的。

空间换时间:

        用空间换时间: 当内存空间充足的时候,如果我们更加追求代码的执行速度,就可以选择空间复杂度相对较高、但时间复杂度相对很低的算法或者数据结构。

        数据结构与算法往往是来源于我们的生活,举一个生活中的案例:看下面小哥积攒了一个月的袜子,(小编只能说自己读书的时候也是这样干的),其实这也是以空间换时间的一个方式,我们来分析一下。

        洗一双:拿袜子,拿盆,洗袜子、收袜子...  这些都需要时间

        如果每次洗一双,洗完所有袜子,就需要将以上时间倍数相乘。

        理论上,袜子积攒越多(空间占用越大),洗袜子总耗时越少(时间效率越高)。

        (当然,生活中不建议这样做,因为我们是人,不是机器代码)

        言归正传,在计算机中以空间换时间的案例很多很多,例如缓存、索引缓存实际上就是利用了空间换时间的设计思想。如果我们把数据存储在硬盘上,会比较节省内存,但每次查找数据都要询问一次硬盘,会比较慢。但如果我们通过缓存技术,事先将数据加载在内存中,虽然会比较耗费内存空间,但是每次数据查询的速度就大大提高了。

        索引结构通常需要额外的存储空间,但是会提高查询效率。例如B+树是在磁盘上的数据记录之外又建立了一层树形索引,因此需要额外的存储空间,但与此同时用索引可以更快找到需要的记录。

时间换空间:

        用时间换空间:当内存比较紧缺时,例如代码跑在手机或者单片机上,这个时候,就要反过来用时间换空间的设计思路。

        举一个生活中案例:错峰吃饭。你有没有过这样的经历,在某些公共食堂(人多,地方小)吃饭时,吃饭往往会划分为好几个时间段(小编还记得当初被同事拉去第一波吃饭,被部门领导发现后的尬尴场景)。

        在计算机中以时间换空间的案例也很多(不过随着硬件资源的不断提高,这个方向相对不是热门),例如数据压缩。压缩和解压缩时以时间代价,换取更小的空间。通过应用适当的编码(例如哈夫曼树)算法,我们可以将原始数据用更少的比特数表示,然而经过编码的数据通常需要经过解压缩才能处理,如果需要更新数据也要解压缩后加入新数据再重新压缩。

小结:

        总结,程序是为了解决某一个或多个问题的,而具体实现它的方式即为算法,而衡量算法的优劣则有两个考量标准,就是时间效率和空间效率。对于执行较慢的程序,可以通过消耗更多的内存(空间换时间)来进行优化而消耗过多内存的程序,可以通过消耗更多的时间(时间换空间)来降低内存的消耗。


典型案例:

        以下两个简单案例,分别演示空间换时间和时间换空间的具体代码。思维思路很重要,下面感受一波,具体还是要根据实际情况去实现。一般优先考虑空间换时间(实际工作中,往往不仅要考虑高效、稳定和维护问题,成本和开发周期等现实问题也需要重视)

案例一:以空间换时间

        以经典求润年为案例,分析时间与空间的关系。

题目:输入一个从2000到3000 的年份(2000-3000),判断其是否为 “ 闰年 ”。

以下两个条件满足其一即为润年:

  1. 能被4整除而不能被100整除。
  2. 能被400整除。

两个思路:

思路一:直接求润年,根据输入的年份year进行逻辑判断,满足条件即为润年,否则不是润年。(一般直接算法)

#include<stdio.h>

int main()
{
    int year;
    printf("请输入2000-3000的数字:");
    scanf("%d",&year);

    if((year%400==0)||((year%4==0)&&(year%100!=0))){
        printf("%d是润年\n",year);
    }else{
        printf("%d不是润年\n",year);
    }
    return 0;
}

思路二:将2000-3000内为润年的年份放在数组arr中,将输入的年份year与数组arr中的元素进行比较,如果year存在于数组中,则为润年,否则不是润年。(以空间换时间)

#include<stdio.h>

int main()
{
    int arr[]={2000,2004,2008,2012,2016,2020,2024,2028,2032,2036,2040,2044,
    2048,2052,2056,2060,2064,2068,2072,2076,2080,2084,2088,2092,2096,2104,
    2108,2112,2116,2120,2124,2128,2132,2136,2140,2144,2148,2152,2156,2160,
    2164,2168,2172,2176,2180,2184,2188,2192,2196,2204,2208,2212,2216,2220,
    2224,2228,2232,2236,2240,2244,2248,2252,2256,2260,2264,2268,2272,2276,
    2280,2284,2288,2292,2296,2304,2308,2312,2316,2320,2324,2328,2332,2336,
    340,2344,2348,2352,2356,2360,2364,2368,2372,2376,2380,2384,2388,2392,
    2396,2400,2404,2408,2412,2416,2420,2424,2428,2432,2436,2440,2444,2448,
    452,2456,2460,2464,2468,2472,2476,2480,2484,2488,2492,2496,2504,2508,
    2512,2516,2520,2524,2528,2532,2536,2540,2544,2548,2552,2556,2560,2564,
    2568,2572,2576,2580,2584,2588,2592,2596,2604,2608,2612,2616,2620,2624,
    2628,2632,2636,2640,2644,2648,2652,2656,2660,2664,2668,2672,2676,2680,
    2684,2688,2692,2696,2704,2708,2712,2716,2720,2724,2728,2732,2736,2740,
    2744,2748,2752,2756,2760,2764,2768,2772,2776,2780,2784,2788,2792,2796,
    2800,2804,2808,2812,2816,2820,2824,2828,2832,2836,2840,2844,2848,2852,
    2856,2860,2864,2868,2872,2876,2880,2884,2888,2892,2896,2904,2908,2912,
    2916,2920,2924,2928,2932,2936,2940,2944,2948,2952,2956,2960,2964,2968,
    2972,2976,2980,2984,2988,2992,2996};
    int year;
    int i=0;
    int len=sizeof(arr)/sizeof(int);
    printf("请输入2000-3000的数字:");
    scanf("%d",&year);

    for(i=0;i<len;i++){
        if(year==arr[i]){
            printf("%d是润年\n",year);
            return 0;
        }
    }
    printf("%d不是润年\n",year);
    return 0;
}

案例二:以时间换空间

        以交换两个int类型数据为例,分析时间和空间的关系。

题目:给两个int类型数据,要求实现数据交换。

法一:直接设置第三个int类型变量,作为交换数据的中转站。(常用方式)

#include<stdio.h>
 
int main()
{
	int a=5;
	int b=6;
	int temp=0;//设置int类型变量temp作为数据a与数据b的周转容器
	
	printf("交换前a=%d,b=%d\n",a,b);
	temp=a;
	a=b;
	b=temp;
	printf("交换后a=%d,b=%d\n",a,b);
	
	return 0;
 } 

方法二:利用数据加减的性质,进行运算后达到数据交换的目的。(相对方法一:少了一个int类型变量,空间占用小;多了算术运算,时间效率下降。)

#include<stdio.h>
 
int main()
{
	int a=5;
	int b=6;
	//数据a的容器起到了周转数据的作用
	printf("交换前a=%d,b=%d\n",a,b);
	a=a+b;//此时容器a存储的是a与b的数据之和
	b=a-b;//此时容器b存储的是数据a
	a=a-b;//此时容器a存储的是数据b
	printf("交换后a=%d,b=%d\n",a,b);
	
	return 0;
 } 

都看到这里了,一键三连啊,收藏点赞+关注!

后面陆续更新算法技巧。

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

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

相关文章

英文论文(sci)解读复现【NO.10】宁夏酿酒葡萄病虫害智能检测平台设计

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的 SCI论文&a…

龙蜥产品生态总监做客 InfoQ:后 CentOS 时代,国产操作系统能否扛起大旗?

随着 CentOS 全面停服即将进入尾声&#xff0c;企业选择一款既可保障系统稳定运行&#xff0c;又可提供专业技术支持的操作系统迁移显得尤为重要。那么&#xff0c;现存的 CentOS 以及衍生版用户或将面临哪些风险&#xff1f;一套完整的迁移方案应该包括哪些步骤&#xff1f;在…

Shap-E:3D资产的生成式AI大模型

OpenAI 刚刚发布了 Shap-E&#xff0c;这是一种基于文本提示和图像创建 3D 资产的生成模型&#xff0c;能够生成带纹理的网格和神经辐射场 &#xff0c;从而实现各种 3D 输出。 推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景。 在本教程中&#xff0c;我们将引导你在 Go…

【云原生进阶之PaaS中间件】第一章Redis-2.3.1主从复制部署模式

1 部署架构 Redis在日常部署的时候&#xff0c;可以有多种部署模式&#xff1a;单机、主从、哨兵、集群&#xff08;分区分片&#xff09;&#xff0c;因此本文将对上面这四种模式进行详细的讲解&#xff0c;特别是集群模式将进行最细致的讲解&#xff08;现行普遍使用的方式&a…

Cpolar内网穿透本地MariaDB数据库

Cpolar内网穿透本地MariaDB数据库 cpolar内网穿透本地MariaDB数据库&#xff0c;实现外公网环境下使用navicat图形化工具远程连接本地内网的MariaDB数据库 配置MariaDB数据库 安装MariaDB数据库 进入MariaDB数据库官网https://mariadb.com/downloads/community/,然后下载相应的…

知行之桥2023版本发布

我们很高兴地宣布知行之桥EDI系统2023版本正式发布。本次发布的知行之桥2023版&#xff08;版本号&#xff1a;8518&#xff09;包含了新的企业级功能&#xff0c;以下是新版本的一些亮点&#xff1a; 1.新增了概览页面&#xff0c;支持查看消息的整个生命周期&#xff0c;添加…

MySQL基础(三十三)MySQL事务日志

事务有4种特性&#xff1a;原子性、一致性、隔离性和持久性。那么事务的四种特性到底是基于什么机制实现呢&#xff1f; 事务的隔离性由 锁机制 实现。而事务的原子性、一致性和持久性由事务的 redo 日志和undo 日志来保证。 REDO LOG 称为 重做日志 &#xff0c;提供再写入操…

深度学习之神经网络是如何自行学习的?

大家好&#xff0c;我是带我去滑雪&#xff01; 深度学习算法是一种神经网络&#xff0c;而神经网络就是数据结构的图形结构&#xff0c;函数集的运算是向量和矩阵运算&#xff0c;调整函数集的参数需要使用微分和偏微分来找出最优解。深度学习可以通过几何学来进行解释&#x…

Excel的“升级版本”, 终于在2023年找到,替代Office包里的Access

Access的用户基数很大 首先&#xff0c;你要明白的是&#xff0c;Access是一款办公软件&#xff0c;其次才是一个数据库&#xff01; 之所以一直以来被微软放在Office的包里&#xff0c;没有被淘汰&#xff0c;是因为Access在Excel处理大数据时崩溃的时候&#xff0c;面向很多…

本机连接aws的ec2时报错:所选用户的用户密钥未在远程主机上注册

引言 由于工作的需要&#xff0c;所以需要去学习下AWS相关的知识&#xff0c;所以自己注册了一个AWS的账号去进行学习。 问题发现 按照启动ec2实例的步骤&#xff1a;选择镜像->选择系统配置->配置密钥对->配置安全组->设置存储卷大小->启动实例 在上述操作…

237:vue+openlayers绘制多边形,生成geojson数据,计算出面积

第237个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中绘制多边形形,利用Geojson的writeFeatures,来生成geojson格式的数据,然后使用turf.area来计算面积。这里面着重解决了在3857的坐标系下,将geojson文件的坐标转化为4326的状态。 直接复制下面的 vue…

短视频矩阵源码系统

短视频矩阵源码系统开发要则&#xff1a; 1. 需求分析&#xff1a;对短视频平台的需求进行全面分析&#xff0c;确立系统开发目标和方向。 2. 技术选型&#xff1a;选用最适合的技术开发短视频矩阵系统&#xff0c;如前端框架、数据库、服务器等。 3. 系统设计&#xff1a;按…

EBAZ4205踩坑记录

这块ZYNQ-7000的二手板子很经典&#xff0c;最早在2019年被人发现。板子资源还是不错的&#xff0c;共引出了3*14个PL侧的IO&#xff0c;可用来研究PL、PS-PL交互&#xff0c;学习PS侧SDK&#xff0c;Linux开发。唯一的遗憾是Bank电压固定为3.3V&#xff0c;没法玩LVDS。 参考…

golang中的websocket,使用wireshark抓包

websocket 是一个长连接协议&#xff0c;全双工通信&#xff0c;主要应用在及时通信&#xff1a;实时聊天&#xff0c;游戏&#xff0c;在线文档等等。 简单示例 客户端 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&quo…

分支语句和循环语句

控制语句&#xff1a;用于控制程序的执行流程&#xff0c;以实现程序的各种结构方式&#xff0c;它们由特定的语句定义符组成&#xff0c;C语言有9种控制语句&#xff0c;可分为三类&#xff1a; 条件判断语句也叫分支语句&#xff1a;if语句&#xff0c;switch语句&#xff1b…

【基础算法】贪心算法基础

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招算法的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于代码随想录进行的&#xff0c;每个算法代码参考leetcode高赞回答和…

对SRC逻辑漏洞挖掘的思考

对SRC逻辑漏洞挖掘的思考 1.限制购买逻辑漏洞一人一单限制差价活动购买限制 2.支付类逻辑漏洞3.接口未授权逻辑漏洞4.越权类逻辑漏洞5.修改返回包进入后台6.任意用户注册7.重置任意用户 1.限制购买逻辑漏洞 一人一单限制 很多厂商都会搞一些活动&#xff0c;在享受优惠的时候…

微服务架构及工作原理!

在移动计算时代&#xff0c;应用程序开发人员应该能够快速部署操作并进行更改&#xff0c;而无需重新部署整个应用程序。结果&#xff0c;它导致了一种称为“微服务”的构建软件的新方法。 微服务是应用程序中独立的小部分&#xff0c;每个部分都完成自己的工作并通过API相互通…

Dubbo学习笔记

目录 简介 Dubbo高可用 集群容错 服务治理 Dubbo线程IO模型 源码层面 Java SPI 的问题 源码解析 简介 Apache Dubbo是一款高性能的Java RPC框架。其前身是阿里巴巴公司开源的一个高性能、轻量级的开源Java RPC框架&#xff0c;可以和Spring框架无缝集成。 Dubbo提供了…

主流总线通信和系统接口技术

一、关于现场控制总线 现场总线是自动控制领域的计算机局域网&#xff0c;应用在生产现场&#xff0c;在微机测控设备之间实现双向、串行、多节点数字通信&#xff0c;是一种开放式、数字化、多点通信的底层控制网络。 现场总线具有较高的测控能力指数 得益于仪表的微机化&am…