百度APP iOS端包体积50M优化实践(二) 图片优化

news2025/6/28 8:22:00

**一、前言删除线格式 **

在上一篇文章,我们介绍了包体积优化的必要性、安装包组成部分和生成过程、国内外大厂APP包体积分析、百度APP包体积优化技术方案及各项收益,本文重点讲述图片优化,解压IPA包后发现,百度APP中asset和bundle里面图片共有94M,这是我们重点优化的对象。

本系列文章目录如下:

《百度APP iOS端包体积50M优化实践(一)总览》(点击标题即可跳转)

百度APP采用如下方式对不同的图片资源进行了优化:

第一、无用图片优化,解决的是随着版本迭代,一些图片已经没有了引用关系,但还在IPA包中保留,挖掘这部分图片并删除,这个优化是所有包体积优化项目中ROI最高的,影响范围局限在单个组件内,质量可控,关键是提高查找无用图片的准确度;

第二、Asset Catalog优化:使用Asset Catalog管理的图片能被App Store工具App Thinning处理,处理后用户只会下载匹配其设备分辨率的图片资源,从而降低了用户下载的包体积;

第三、HEIC图片优化:跟PNG、JPEG、WebP相比,HEIC图片编码格式体积减少最小,从解码效率角度来说,跟WebP相比,HEIC硬解码效率高。

二、无用图片优化

2.1 方案综述

首先获取所有图片资源,然后开发工具获取Objective-C、Swift、xib、storyboard、html、js、css、json、plist文件可能引用图片的静态字符串,接着前面两个集合做diff即可排查未引用的图片,最后针对字符串拼接的常见case做二次过滤,覆盖的case越多准确度越高,当然也要考虑ROI。

2.2 获取所有图片

开启每个库的源码,用脚本检测所有图片及图片所属关系,为后续分发及落地优化提供方便。如果不开源码使用二进制库或者ipa包会带来很多麻烦,如获取asset.car里面的图片资源比较困难,同时只能知道图片名称,不能直接获取图片属于哪一个库。开启每个库的源码后,用脚本递归遍历可获取所有图片,从图片路径可知道所属关系,参考代码如下所示:


def findAllPictures(path):
    pathDir = os.listdir(path)
    for allDir in pathDir:
        child = os.path.join('%s%s' % (path, allDir))
        if os.path.isfile(child):
            # 获取读到的文件的后缀
            end = os.path.splitext(child)[-1]
            if  end == ".png" or end == ".webp" or end == ".gif" or end == ".jpeg" or end == ".jpg":
                print("文件" + child + " 后缀 " + end)
        else:
            # 递归遍历子目录
            child = child + "/"
            findAllPictures(child)

2.3 获取可能引用图片静态字符串

在这个环节,我们重点是要找到在代码中可能会引用图片的字符串集合,如在Objective-C的.m文件中,我们经常用如下代码去加载图片account_login来创建一个UIImageView对象, 针对Objective-C的.m文件内容,用正则过滤,匹配表达式为 @“(.*?)”,即可获取所有可能加载图片的字符串集合。

imgView.image = [UIImageimageNamed:@"account_login"];
br

对于Swift文件我们通常通过如下代码去加载图片account_login,加载方式完全不一样,针对Swift这种文件,正则表达式应为"(.?)"。

let imageView = UIImageView(frame: CGRectMake(100, 10, 200, 200))
imageView.image = UIImage(named:"account_login.jpg")
self.view.addSubview(imageView)

对于html文件我们通常用如下代码去加载图片,正则表达式应为img\s+src=“'[”']。

<html>
<body>
<img src="图片地址" alt="文本说明" width=** height=**>
</body>
</html>

不同的文件加载图片的方式不同,如Objective-C、Swift、xib、storyboard、html、js、plist、json和css都不尽相同,在下面的表格,我整理出常用文件过滤图片使用的正则表达式。

图片

2.4 获取未引用图片

通过2.2章节我们获取的工程中的所有图片,通过2.3章节我们获取代码中所有可能引用图片的静态字符串,那么对于每张图片而言,如果不在引用图片的静态字符串集合中,这张图片可能就是未引用的图片。

2.5 字符串拼接的常见case做二次过滤

经过上面的环节,我们通过全字符串匹配获取了未引用的图片,实际开发过程,有一些常见情况,代码中引用图片的名称是通过字符串拼接生成的,因此我们需要进行二次过滤。第一种常见的case,就是当手机支持暗黑模式时,同一个位置的图片通常会有两套,通过后缀如light、dark或者day、night来做区分;第二种常见的case,就是后缀是数字的图片序列,iOS端有一种动画类型是ImageView加载多图动画,图片名称是由字符串和动态数字后缀拼接而成,过滤时需要覆盖如下后缀_%d,_%ld,_%zd,_%lu。

三、Asset Catalog 图片优化

3.1 背景

Asset Catalog 是 Xcode 提供的在iOS7系统开始引入的资源管理工具,将分散在项目中大大小小的资源进行统一存放和集中管理,包括但不限于images、sprites、textures, ARKit resources和PDF,我们可以把之前放在bundle的图片或者其他资源放入Asset catalog中,XCode最后统一压缩成一个Assets.car的文件。

在Asset Catalog之前,我们通常将图片直接放到工程的bundle,这种方式存在一些缺点:第一、空间浪费,不同设备需要不同分辨率图片,所以在bundle里对同一张图片同时存在二倍图和三倍图,浪费资源;第二、图片压缩只能针对单个文件,没有统一的压缩功能;第三、信息冗余,每个图片资源都会存储自己的元数据和其他的一些属性信息,如果存在很多同类型的资源,这些相同的信息会产生冗余,造成空间浪费。

3.2 Asset Catalog优点

针对bundle存在的上述问题,Asset Catalog做了诸多优化,无论是包体积优化、统一的图片压缩和便利的资源管理,还是高效的IO操作,每一项优化都做到了极致,下面详细介绍:

第一、包体积瘦身:Asset Catalog为不同类型设备(分辨率不同)或者相同类型设备但不同配置(磁盘和内存不同)提供定制化资源下载,之前在bundle需要放二倍图和三倍图,同一张图片最后在用户手机上会有两份,有了Asset Catalog后,当用户下载App时,只有跟用户手机硬件设备参数相匹配的资源才会被下载,其他不会下载,比如说,iphone8手机用户只会下载二倍图片,iphone13的用户只会下载三倍图片,这样可明显减少下载包大小。

第二、统一的图片无损压缩:Asset Catalog默认对文件夹中的所有图片采用无损压缩,压缩方法是Apple Deep Pixel Image Compression,这是苹果新引入的一种压缩形式,会根据图片的色谱特性选择最优的算法进行压缩,压缩比能提高15~20%。WWDC2018:Optimizing App https://developer.apple.com/videos/play/wwdc2018/227/ 有详细介绍。具体来说,针对不同类型的图片采用有不同的优化方式,一类是简单的图片资源,如很多icon图片,这类图片只有相对简单的配色和设计。另一类指的是复杂的图片资源,Apple Deep Pixel Image Compression针对这两种形式都做了不同形式的优化,图片资源体积越大使用Asset Catalog后优化的效果就越明显,统一的压缩更有利于实现包体积瘦身,下面这张图是苹果官方给出的Apple Deep Pixel Image Compression体积压缩比的优化。

图片

第三、便利的资源管理:如果将图片直接放在工程目录下面,项目打包后图片文件是散落在iPA包里面,而如果用Asset Catalog来管理放在xcassets中,在打包后会将这些图片统一压缩成一个Assets.car的文件。

第四、高效的I/O操作:Assets Catalogs图片加载耗时比普通的bundle加载图片耗时要少两个数量级,这是因为编译最后生成Assets.car文件包含了BOM文件,BOM文件提供了图片加载时需要的的rendition、renditionKey和attribute属性值,rendition是 CoreUI.framework 对某一图像资源的不同样式的统称,如@2x,@3x,每一个rendition有一个renditionKey与之对应,通过renditionKey获取到对应的attribute,attribute中包含了各种属性,如图片的分辨率、垂直大小、水平大小等参数。

用Assets Catalogs管理的图片,通过imageNamed方法进行加载,因为car文件里面的上述资源信息是XCode编译时生成好的,当解析完car文件后,可以直接通过图片名称获取renditionKey和attribute属性并读取图片资源,没有任何多余操作,相反对于用bundle管理的图片,额外的操作太多导致耗时严重。对于bundle管理图片有两种加载方式,第一种通过imageName方式加载图片,需要先去Assets.car里面查询,由于图片资源并不在Assets.car里面,所以在获取rendition和renditionKey时多次调用canGetRenditionWithKey,canGetRenditionWithKey,最后再重新通过mmap加载读取图片属性和图片资源,形成rendition和renditionKey,总体耗时最大;第二种通过imageWithContentsOfFile加载图片,不需要去Assets.car里面查询,没有生成rendition和renditionKey的相关操作和缓存操作,只有读取图片属性和图片二进制的操作耗时,但是没有图片属性等相关缓存所以耗时比较长。

3.3 Assets.car生成过程

具体来说,Xcode 在处理Asset Catalog节点时, 构建 Asset Catalog 的工具 actool 会先对 Asset Catalog 中的 png 图片进行解码,得到 Bitmap 数据,然后再运用 actool 的压缩算法进行编码压缩处理生成Assets.car 文件,这就可以解释在Asset Catalog中放jpg格式图片,最后生成的Assets.car 文件中却是png格式图片。

3.4 Assets.car操作

用Assets Catalogs管理的图片,XCode编译时并不是简单的拷贝操作,而是将所有资源打包生成的Assets.car文件,这是一种压缩文件,直接解压无法操作的,利用XCode 自带工具assetutil可以分析.car文件,分析命令如下所示:

sudo xcrun --sdk iphoneos assetutil --info ./Assets.car > ./AssetsInfo.js

通过AssetsInfo.json获取图片相关属性,但是无法获取里面的图片。

图片

如果想将car文件中的图片提取出来,推荐一个开源工具叫Asset Catalog Tinkerer,可以从github下载,这里给出github地址:https://github.com/insidegui/AssetCatalogTinkerer

图片

3.5 Asset Catalog的压缩算法

使用3.4节介绍的XCode 自带工具assetutil可以知道每张图片的压缩算法,Compression字段值代表不同图片的采用的不同压缩算法,通过实践发现actool支持的压缩算法有 deepmap2、deepmap_lzfse、zip、lzfse、palette_img,具体采用哪种压缩算法跟很多因素有关,如图片自身特性、打包的XCode版本、Framework支持的iOS最低版本、编译配置(Asset Catalog Compiler - Options Optimization),从实际效果来看,XCode会根据综合上述因素选择一个压缩比最优的算法,另外这些压缩算法都是无损的。

图片

3.6 不要做无损压缩

开发者在图片放入Asset Catalog之前千万不要做无损压缩,无损压缩算法是通过改变图片的压缩编码算法达到减少体积大小的目的,不会改变解码后的Bitmap 数据,从3.3节中我们知道Assets.car 文件的生成过程中,Asset Catalog 的工具 actool先做解码得到Bitmap数据,然后再编码压缩处理,针对无损压缩算法actool接收的Bitmap 数据并没有改变,所以无损压缩无法优化包体积,UI设计师给出的PNG图片如果采用Asset Catalog优化就千万不要做无损压缩。

3.7 bundle多倍图片Asset优化

Asset Catalog是Apple在2013年发布的iOS7的系统开始引入的,从iOS 9 之后开始支持做资源管理,老代码(尤其是16年前的代码)都是用bundle的方式去管理图片,为此,我们开发脚本专门针对bundle多倍图片做检查,然后采用Asset优化,这种优化方式可以实现包体积立减一半,参考脚本如下所示:


def find_all_bundle_pic(app_package_path, all_pic_list):
    """
    将所有bundle图片存入list中
    """
    pathDir = os.listdir(app_package_path)
    for child_file in pathDir:
        child_path = os.path.join('%s/%s' % (app_package_path, child_file))
        # isfile:如果child是一个存在的文件则返回true,否则(bundle、文件夹会等)返回false
        if os.path.isfile(child_path):
            if child_path.endswith(".png") or child_path.endswith(".jpg") or child_path.endswith(".jpeg") or child_path.endswith(".gif") or child_path.endswith(".webp"):
                if child_path.find(".bundle") > 0:
                    all_pic_list.append(child_path)
        else:
            find_all_bundle_pic(child_path, all_pic_list)

def find_opt_pic(all_picture_list,final_opt_pic_list):
    """
    查找bundle中重复的多倍图片
    """
    for picture in all_picture_list:
        if picture.endswith("@2x.png"):
            prefix_2x = picture[0: len(picture) - 7]
            for picture1 in all_picture_list:
                # 前缀匹配
                if picture1 != picture and picture1.startswith(prefix_2x):
                    if (len(picture) == len(picture1) and picture1.endswith("@3x.png")) or len(picture) == len(picture1) + 3:
                        final_opt_pic_list.append(picture)
                        final_opt_pic_list.append(picture1)

3.8 有损图片压缩可减少Assets.car大小

从3.6节我们得知无损压缩对于Asset Catalog是没有体积优化效果的,但是有损压缩可减少Assets.car 大小,因为Asset Catalog自身也会对图片进行压缩优化,所以有损压缩图片的收益没有bundle转Asset Catalog收益明显,常用的有损压缩工具有TinyPng和pngquant。

TinyPng是一个网页版的工具,通过合并图片中相似的颜色,将 24 位的 PNG 图片压缩成 8 位色值的图片,并且去掉了图片中不必要的元数据来实现压缩。对于单张图片压缩使用非常方便,链接地址如下:https://tinypng.com/,但是如果要处理批量图片压缩,上传过程中容易出现上传不成功等问题,这个工具不支持自定义压缩配置。

pngquant是一个有损的PNG压缩开源库,提供了命令行和源码库两种形式。将24位或32位的RGBA PNG图转换成8位PNG图并保留透明度通道。通过这个库的转化可以显著减少png文件大小,pngquant采用的是本地脚本压缩,工具下载地址:https://pngquant.org,对批量压缩图片支持的比较友好,pngquant支持自定义压缩品质,配置压缩品质小于90后压缩率会高于TinyPng,并且pngquant是开源的,可以自定义,这是百度APP图片压缩的首选。

四、HEIC图片编码优化

4.1 HEIC图片编码优点

HEIC(High Efficiency Image Coding)是一种图像编码标准,它可以极大提升压缩率,并有效减小储存占用,自iOS 11和macOS High Sierra(10.13)开始,苹果将HEIC设置为图片存储的默认格式,它由动态影像专家小组(MPEG)开发,并在MPEG-H Part 12(ISO/IEC 23008-12)中定义,以下是HEIC图片的特点:

压缩率高:HEIC图片比JPEG图片压缩率高1.5倍,比PNG图片压缩率高3倍,也比GIF图片压缩率高3倍。

节省内存:HEIC图片比JPEG图片节省20%的存储空间,比PNG图片节省50%的存储空间,比GIF图片节省80%的存储空间。

解码效率高:在iOS系统中,HEIC采用硬解码,解码效率高,跟WebP(软编码)相比,是其100倍,但略慢于JPEG。

保留原始图像质量:HEIC图片采用H.264和JEP格式压缩,可以保留原始图像质量。

支持无损放大:HEIC图片支持无损放大,可以将图片放大两倍而不失真。

色彩处理方面:HEIC图片可以根据像素点的亮度分布自动亮度、对比度和饱和度,从而更好地还原图像的真实色彩。

系统兼容性好:我们知道iOS 11开始HEIC是图片存储的默认格式,也就是iOS 11以后的系统都支持HEIC图片,但我们百度APP目前还支持iOS10系统,对这部分用户如何处理?在实践中发现,在iOS10系统上,当把HEIC图片放xcasset文件里,最后图片也是可以正常显示的,我们做了一番原因排查,用Asset Catalog Tinkerer工具解压出Assets.car 文件,发现在xcasset里的HEIC图片,对于iOS10的系统,在打包时会被系统转化为png格式图片,Asset Catalog解决了HEIC图片的兼容性问题。

4.2 如何生成HEIC图片

利用Mac自带功能实现png转HEIC方法:右键图片,快速操作-》转换图像, 格式选HEIF,选择原图像。

图片

优化结果如下所示,左边是png原图(1.6M),右边是HEIC图片(106KB)。

图片

4.3 HEIC图片使用方法

4.3.1 必须在Asset Catalog使用

HEIC图片必须放在Asset Catalog中才能使用,bundle方式不支持HEIC图片加载。

图片

HEIC图片的加载使用方法和普通的asset图片一样,如下所示:

imgView.image = [UIImage imageNamed:@"account_login"];

4.3.2 对于大图HEIC格式明显体积小

理论上来说,HEIC格式图片的体积是PNG格式图片的三分之一,但实际过程发现对于大图,这个优化效果很明显,但是对于小图尤其是小于10K的图片,HEIC图片还有可能超过PNG格式图片,所以我们在做HEIC图片编码优化时,对于小图不建议用这种方式。

4.3.3 带有Alpha通道的PNG图片不要做有损压缩

在实践过程中发现,一张PNG原图,尤其是带有Alpha通道,经过有损压缩(TinyPng或ImageOptim)后,再生成HEIC图片时,在iOS12,13,14系统上会显示绿幕,所以带有Alpha通道的PNG图片不要做有损压缩,存在兼容性问题。

五、总结

图片优化是包体积优化的重头戏,百度APP经过两个Q的优化落地9.75M的收益解决了存量图片的问题,随后建立图片使用规范和无用图片检测流水线解决增量图片的问题。

本文详细介绍了无用图片检测方案、Asset Catalog图片优化和HEIC图片优化方案,后续我们会针对其他优化类型详细介绍其原理与实现,敬请期待。

——END——

参考资料:

[1]Asset使用方法:https://developer.apple.com/library/archive/documentation/Xcode/Reference/xcode_ref-Asset_Catalog_Format/index.html#//apple_ref/doc/uid/TP40015170-CH18-SW1

[2]Asset介绍:https://help.apple.com/xcode/mac/current/#/dev10510b1f7

[3]WWDC2018:Optimizing App Assets:https://developer.apple.com/videos/play/wwdc2018/227/

[4]TinyPng:https://tinypng.com/

[5]pngquant:https://pngquant.org

[6]HEIC图片介绍:https://mobiletrans.wondershare.com/heic-convert/what-is-heic-file.html

推荐阅读:

浅论分布式训练中的recompute机制

剖析多利熊业务如何基于分布式架构实践稳定性建设

百度工程师的软件质量与测试随笔

百度APP iOS端包体积50M优化实践(一)总览

基于FFmpeg和Wasm的Web端视频截帧方案

百度研发效能从度量到数字化蜕变之路

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

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

相关文章

Seurat -- Normalize Data

brief seurat提供的教学里面包含了Standard pre-processing workflow,workflow包括QC&#xff0c;normalization&#xff0c;scale data &#xff0c;detection of highly variable features。其中 normalization就有蛮多方法的&#xff0c;seurat自己就提供了两种&#xff0c…

ChatGpt接入Word文档,让你秒变职场达人!

今天跟大家分享下我们如何使用VBA代码&#xff0c;将ChatGpt接入Word文档&#xff0c;操作非常的简单&#xff0c;但是开始之前我们需要做2项准备 1. 获取ChatGpt的API 2. 魔法上网 准备好这2件事后&#xff0c;我们就可以着手制作了: 一&#xff0c;设置代码 二&…

微软的“牛头怪时刻”

2014年&#xff0c;当萨提亚纳德拉接任微软CEO时&#xff0c;他面对的是一家停滞且难以在快速发展的技术领域保持竞争优势的公司。自那以后&#xff0c;纳德拉将其重点从传统操作系统和生产力软件&#xff0c;转向云计算和人工智能&#xff0c;被认为重振了微软。​ 让我们以O…

ThreadPoolExecutor源码阅读流程图

1.创建线程池 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), def…

shell脚本编程规范与变量

目录 一.shell脚本的概述2.1 shell的作用 三. shell脚本的作用3.1 编写第一个shell脚本3.1.1 Shell 脚本的构成&#xff1a;3.1.2 脚本的执行方式 三. 重定向与管道符操作3.2 重定向操作3.2 管道操作符号 四. shell的变量的作用&#xff0c;类型4.1 定义变量4.2 命名的规则4.3 …

辛弃疾最有代表性的十首词

辛弃疾的词&#xff0c;风格多样&#xff0c;题材广阔&#xff0c;几乎涉及到生活中的各个方面&#xff0c;从爱国情怀到日常生活&#xff0c;甚至连戒酒这种事都能写入词中。辛弃疾也是两宋词人中&#xff0c;存词最多的作家之一&#xff0c;现存的六百多首作品。 辛弃疾的词…

【数据结构:线性表】单链表

在学习了顺序表&#xff0c;我们可能会对其有一些思考&#xff1a; 中间/头部的插入删除&#xff0c;时间复杂度为O(N)增容需要申请新空间&#xff0c;拷贝数据&#xff0c;释放旧空间。会有不小的消耗。增容一般是呈2倍的增长&#xff0c;势必会有一定的空间浪费。例如当前容…

第四次工业革命的里程碑-chatgpt

文章目录 一、 介绍二、 训练数据方法、数据来源三、 能帮你做什么做表格论文降重写文案、周报写代码改bug写注释写作业制作游戏策划方案 四、 搭建自己的chatgpt方法五、 安全、安全试用chatgpt的方法六、 几款类似chatgpt的工具七、 优点八、 缺点九、下一步的期待十、 总结 …

vue中vue-cli项目各种报错

目录 sockjs.js报错 [WDS] Disconnected报错 假如有以上报错&#xff0c;首先看下index.html有没有这句 <meta http-equiv"Content-Security-Policy" content"upgrade-insecure-requests"> 是限制资源获取&#xff1a;限制网页当中一系列的资源获…

OkHttp3源码解析 - 拦截器

系列文章目录 第一章 OkHttp3源码解析 - 请求流程 第二章 OkHttp3源码解析 - 拦截器 第三章 OkHttp3源码解析 - 连接机制和缓存机制 文章目录 系列文章目录前言一、五大内置拦截器二、拦截器分发流程1.RetryAndFollowUpInterceptor-重试重定向拦截器2.BridgeInterceptor-桥接拦…

用友BIP助力中国领先企业数智化国产替代

随着数字经济的快速发展&#xff0c;软件的重要性日益凸显。软件是新一代信息技术的灵魂&#xff0c;已经成为数字中国、制造强国、网络强国建设的关键支撑。面对全球竞争新格局&#xff0c;关键软件自主创新与国产化替代已迫在眉睫。 助力华为成功替换国外ERP系统 在此背景下…

android studio Switch按钮

1.添加按钮 <LinearLayoutandroid:layout_width"match_parent"android:layout_height"wrap_content"android:orientation"horizontal"><TextViewandroid:id"id/tv1"android:layout_width"0dp"android:layout_weig…

JavaScript如何实现继承?

&#x1f4dd;个人主页&#xff1a;爱吃炫迈 &#x1f48c;系列专栏&#xff1a;JavaScript &#x1f9d1;‍&#x1f4bb;座右铭&#xff1a;道阻且长&#xff0c;行则将至&#x1f497; 文章目录 继承JavaScript如何实现继承&#xff1f;原型链继承构造函数继承组合继承原型式…

纽扣电池出口欧盟ce认证EN62133测试项目

纽扣电池CE证办理&#xff0c;锂电CE证旨在提高环境性能的2006/66/EC入了电池和 蓄电池中0.0005%汞和便携式电池和蓄电池中0.002%镉的限值。自2013/56/EU 修订了2006/66/EC&#xff0c;2013/56/EU(修订2006/66/)规定&#xff0c;2015年10月1日 起&#xff0c;纽扣电池中汞的…

从零基础到条码高手:傻瓜式操作,告别excel、AI和PS的烦恼

条形码是一种用于商品识别、库存管理等方面的编码标识系统&#xff0c;它是通过将数字和字符以特定的图案排列组合起来&#xff0c;从而形成一组能被机器扫描和识别的条纹图案。 通常情况下&#xff0c;条形码的生成可以分为如下几个步骤&#xff1a; 1、编号&#xff1a;首先…

【神秘题 整数溢出】牛客小白月赛71 C-猫猫与数列

被教育了 学到了一些只有我不知道的常识 C-猫猫与数列_牛客小白月赛71(重现赛) (nowcoder.com) 题意&#xff1a; 思路&#xff1a; 直接模拟即可 值得注意的是&#xff0c;他在算数列的过程中可能会爆long long&#xff0c;因此在算的时候注意开__int128&#xff0c;这样…

微信小程序 开发中的问题(simba_wx)

目录 一、[将 proto 文件转成 json 文件](https://blog.csdn.net/wzxzRoad/article/details/129300513)二、[使用 test.json 文件](https://blog.csdn.net/wzxzRoad/article/details/129300513)三、[微信小程序插件网址](https://ext.dcloud.net.cn/)四、[vant-weapp网址](http…

为什么停更ROS2机器人课程-2023-

机器人工匠阿杰肺腑之言&#xff1a; 我放弃了ROS2课程 真正的危机不是同行竞争&#xff0c;比如教育从业者相互竞争不会催生ChatGPT…… 技术变革的突破式发展通常是新势力带来的而非传统行业的升级改革。 2013年也就是10年前在当时主流视频网站开启分享&#xff1a; 比如 …

电脑开机后出现哭脸错误无法启动解决方法

电脑开机后出现哭脸错误无法启动解决方法。有用户安装好电脑系统之后&#xff0c;遇到了哭脸错误的情况。出现这样的错误原因有很多。如果你无法找到问题的根源的话&#xff0c;其实都是可以通过U盘重装系统的方法来解决的&#xff1f;接下来我们一起来看看以下的操作教学吧。 …

BM39-序列化二叉树

题目 请实现两个函数&#xff0c;分别用来序列化和反序列化二叉树&#xff0c;不对序列化之后的字符串进行约束&#xff0c;但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。 二叉树的序列化(Serialize)是指&#xff1a;把一棵二叉树按照某种遍历方式的结…