谷粒商城第十一天-品牌管理中关联分类
目录
一、总述
二、前端部分
1. 调整查询调用
2. 关联分类
三、后端部分
四、总结
一、总述
之前是在商品的分类管理中直接使用的若依的逆向代码
有下面的几个问题:
1. 表格上面的参数填写之后,都是按照完全匹配进行搜索,没有模糊匹配
2. 分页有问题
上面的这两个问题只要是你不做任何的修改,就是这个样子
下面是这里品牌管理特殊的:
1. 每个品牌需要关联分类
总的来说
前端:
在前端上面,将api啊,请求参数啊配好,因为其实这里是为了规范,原本的话,这个若依逆向生成的,的表单数据除了本身的填写的那些信息,还有分页参数也填上去了。这样的话就一个参数,当然后端可以只用一个参数接收,但是这个参数类除了含品牌的信息还额外的需要分页信息,就不合理了,因此得拆分,所以前端需要修改一下
另外因为每个品牌需要关联分类,因此还得添加上关联分类的这个按钮
后端:
这里的话,还是发生了一些改变的,相比之前直接无脑用。
首先:
1. 查询要分页并且模糊查询
2. 其次删除接口不能只删品牌本身,其品牌分类的关联也要将其删除(要有这种意识,其实这种意识是最基本的,我之前还傻傻的没有意识到,写博文的时候重看才发现问题的)
然后对于品牌本身接口就这些修改。然后这里涉及到品牌-分类关联,因此
这里的话,这个关联的相关接口,要考虑是否需要对逆向生成的接口作修改
1. 通过需求,显示的时候需要显示分类名和品牌名
还好这个在关系表中都做了冗余存储,所以查的话正常查,不需要多次查啥的
2. 但是新增的时候,就需要查出品牌名和分类名,然后存入到关联表中
二、前端部分
两点:
1. 调整查询调用
现在需要分页(其实本来就可以分页的,只是这里规范一下子,其实也不知道是不是真的规范,但是我现在就这样弄吧!)
api:
// 查询品牌列表
export function listBrand(brandParams,pageParams) {return request({url: '/product/brand/list',method: 'get',params: {brand: JSON.stringify(brandParams),pageParams: JSON.stringify(pageParams)}})
}
这里的话其实如果要想两个参数还是get请求的话,就必须得这样写,就是先将其转为字符串,
直接对象的话,我测试了后端接收不到。除非换成post请求,后端使用@RequestBody进行接收
调用:
/** 查询品牌列表 */getList() {this.loading = true;const {name,descript,firstLetter,sort} = this.queryParams;const {pageNum,pageSize} = this.queryParams;let brandParams = {name,descript,firstLetter,sort};let pageParams = {pageNum,pageSize};listBrand(brandParams,pageParams).then((response) => {this.brandList = response.rows;this.total = response.total;this.loading = false;});},
2. 关联分类
1. 从老师给的代码中选取相关构件(有基本样子)
1. 1 将其”关联分类“按钮放好
<el-button type="text" size="mini" @click="updateCatelogHandle(scope.row.brandId)">关联分类</el-button>
1.2 弹窗代码放置好
<el-dialog title="关联分类" :visible.sync="cateRelationDialogVisible" width="30%"><el-popover placement="right-end" v-model="popCatelogSelectVisible"><category-cascader :catelogPath.sync="catelogPath"></category-cascader><div style="text-align: right; margin: 0"><el-button size="mini" type="text" @click="popCatelogSelectVisible = false">取消</el-button><el-button type="primary" size="mini" @click="addCatelogSelect">确定</el-button></div><el-button slot="reference">新增关联</el-button></el-popover><el-table :data="cateRelationTableData" style="width: 100%"><el-table-column prop="id" label="#"></el-table-column><el-table-column prop="brandName" label="品牌名"></el-table-column><el-table-column prop="catelogName" label="分类名"></el-table-column><el-table-column fixed="right" header-align="center" align="center" label="操作"><template slot-scope="scope"><el-buttontype="text"size="small"@click="deleteCateRelationHandle(scope.row.id,scope.row.brandId)">移除</el-button></template></el-table-column></el-table><span slot="footer" class="dialog-footer"><el-button @click="cateRelationDialogVisible = false">取 消</el-button><el-button type="primary" @click="cateRelationDialogVisible = false">确 定</el-button></span></el-dialog>
注意到,它这里用了一个popover标签,这其实就是弹出窗
还是嵌套弹出窗。我把最后的效果拿出来:
至于这个分类怎么出来的,就是下面这一句:
<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
这里的sync的作用是当选择的分类发生变化的时候,父组件中的catelogPath也将动态的变化
所以得在父组件也就是引用这个组件的组件,也就是在品牌的这个组件中,在数据域中声明好:catelogPath这个属性
这里就是一个分类组件,自己封装的,因为很多地方需要使用
要正确使用还是那三步:
1. 抽取组件
这里之前第十天的时候添加属性分组的时候,已经抽取出来了:
但是我那个比较简单,没有涉及到categoryPath的动态感应
没什么好说的,直接用老师的:
<template>
<!--
使用说明:
1)、引入category-cascader.vue
2)、语法:<category-cascader :catelogPath.sync="catelogPath"></category-cascader>解释:catelogPath:指定的值是cascader初始化需要显示的值,应该和父组件的catelogPath绑定;由于有sync修饰符,所以cascader路径变化以后自动会修改父的catelogPath,这是结合子组件this.$emit("update:catelogPath",v);做的--><div><el-cascaderfilterableclearable placeholder="试试搜索:手机"v-model="paths":options="categorys":props="setting"></el-cascader></div>
</template><script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
import {treeListCategory} from "@/api/product/category"
export default {//import引入的组件需要注入到对象中才能使用components: {},//接受父组件传来的值props: {catelogPath: {type: Array,default(){return [];}}},data() {//这里存放数据return {setting: {value: "catId",label: "name",children: "children",expandTrigger: 'hover'},categorys: [],paths: this.catelogPath};},watch:{catelogPath(v){this.paths = this.catelogPath;},paths(v){this.$emit("update:catelogPath",v);//还可以使用pubsub-js进行传值this.PubSub.publish("catPath",v);}},//方法集合methods: {getCategorys() {treeListCategory().then((response)=>{this.categorys = response.data;})}},//生命周期 - 创建完成(可以访问当前this实例)created() {this.getCategorys();}
};
</script>
<style scoped>
</style>
2. 导入组件
3. 使用组件
2. 从模板中提取好数据,绑定到数据域中
无非就是一些 弹窗的标志值还有数据
3. 修改方法
就是对老师给的方法看是不是要修改一下,无非就是修改一下数据格式,逻辑基本上不需要修改,无非就是请求那里使用自己的,导入一下自己的api,调用自己的请求对象
1.
这个没什么好说的,不要修改,就是打开一下弹窗,并且记录当前那一行的品牌id,为以后查关联作铺垫
2. 获取关联列表
到这里,直接把查曾删都全部导入进来
这个没什么好说的,主要是记得若依框架的查询接口,最终是以TableDataInfo对象返回的,所以得拿到里面的row才是真正的数据,这里的话不涉及到分页,所以拿到这个row真正的数据就行了。
//查询关联列表getCateRelation() {listRelation({brandId: this.brandId}).then((response)=>{this.cateRelationTableData = response.rows;})},
3. 新增关联
没什么好说的,传上品牌id和分类id即可
//新增品牌分类关联addCatelogSelect() {this.popCatelogSelectVisible =false;addRelation({brandId: this.brandId,catelogId: this.catelogPath[this.catelogPath.length-1]}).then((response)=>{if(response.code == 200){this.$modal.msgSuccess("新增品牌分类关系成功");this.getCateRelation();}else{this.$modal.confirm("新增品牌分类关系失败");}})}
4. 删除关联
也没什么好说的,直接传入关联id也就是当前这条记录的id即可
//删除关联deleteCateRelationHandle(id) {delRelation(id).then((response)=>{if(response.code == 200){this.$modal.msgSuccess("删除品牌分类关系成功");this.getCateRelation();}else{this.$modal.confirm("删除品牌分类关系失败");}})}
三、后端部分
1. 首先品牌本身
1.1 分页模糊查询
这个得话使用MP带的分页功能,因为若依自带的我还没弄明白。
需要注意的是要使用MP带的分页,就得配置一下,不然不起作用:
@Configuration
@EnableTransactionManagement
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();paginationInnerInterceptor.setOptimizeJoin(true);paginationInnerInterceptor.setDbType(DbType.MYSQL);paginationInnerInterceptor.setOverflow(true);interceptor.addInnerInterceptor(paginationInnerInterceptor);OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor();interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);return interceptor;}
}
反正我用的3.4.3版本的MP是需要这个的:
接口:
/*** 查询品牌列表*/
@ApiOperation("查询品牌列表")
//@PreAuthorize("@ss.hasPermi('product:brand:list')")
@GetMapping("/list")public TableDataInfo list(@RequestParam("brand") String brandJson,@RequestParam("pageParams") String pageParamsJson) {Brand brand = new Gson().fromJson(brandJson, Brand.class);PageParamsDto pageParamsDto = new Gson().fromJson(pageParamsJson, PageParamsDto.class);TableDataInfo tableDataInfo = brandService.pageList(brand,pageParamsDto);return tableDataInfo;}
当前端需要传递两个参数还需要是get请求的时候,后端参数就是用字符串接收,然后使用Gson类进行解析
前端部分接口:
// 查询品牌列表
export function listBrand(brandParams,pageParams) {return request({url: '/product/brand/list',method: 'get',params: {brand: JSON.stringify(brandParams),pageParams: JSON.stringify(pageParams)}})
}
后端接口实现:
/*** 分页并且模糊查询获取品牌列表** @param brand* @param pageParamsDto* @return*/@Overridepublic TableDataInfo pageList(Brand brand, PageParamsDto pageParamsDto) {LambdaQueryWrapper<Brand> wrapper = new LambdaQueryWrapper<>();wrapper.like(StringUtils.hasText(brand.getName()),Brand::getName,brand.getName());wrapper.eq(brand.getFirstLetter()!=null,Brand::getFirstLetter,brand.getFirstLetter());wrapper.eq(brand.getSort()!=null,Brand::getSort,brand.getSort());wrapper.eq(Brand::getShowStatus,1);wrapper.like(StringUtils.hasText(brand.getDescript()),Brand::getDescript,brand.getDescript());Page<Brand> page = new Page<>(pageParamsDto.getPageNum(),pageParamsDto.getPageSize());page(page,wrapper);return new TableDataInfo(page.getRecords(),page.getTotal());}
1.2 删除需要注意关系也要删除
接口:
/*** 删除品牌*/@ApiOperation("删除品牌")//@PreAuthorize("@ss.hasPermi('product:brand:remove')")@Log(title = "品牌", businessType = BusinessType.DELETE)@DeleteMapping("/{brandIds}")public AjaxResult remove(@PathVariable Long[] brandIds) {return toAjax(brandService.removeMore(Arrays.asList(brandIds)));}
实现:
@Override@Transactionalpublic boolean removeMore(List<Long> list) {boolean remove = removeByIds(list);AtomicBoolean flag = new AtomicBoolean(true);list.stream().forEach(item->{LambdaQueryWrapper<CategoryBrandRelation> wrapper = new LambdaQueryWrapper<CategoryBrandRelation>().eq(CategoryBrandRelation::getBrandId, item);if(categoryBrandRelationService.list(wrapper).size()!=0){boolean remove1 = categoryBrandRelationService.remove(wrapper);if (!remove1) {flag.set(false);}}});return remove&& flag.get();}
这里操作了多张表,加上@Transactional注解
注意这里是存在关系再去进行删除,而非对每个都去删除,当不存在的时候去删除就是false,最终就会返回false了,就出错了。
2. 关联那边的
2.1 查询列表
很简单,直接逆向的,因为不涉及分页模糊
/*** 查询品牌分类关联列表*/
@ApiOperation("查询品牌分类关联列表")
//@PreAuthorize("@ss.hasPermi('product:relation:list')")
@GetMapping("/list")public TableDataInfo list(CategoryBrandRelation categoryBrandRelation) {startPage();List<CategoryBrandRelation> list = categoryBrandRelationService.list(new QueryWrapper<CategoryBrandRelation>(categoryBrandRelation));return getDataTable(list);}
2.2 新增
接口:
/*** 新增品牌分类关联*/@ApiOperation("新增品牌分类关联")//@PreAuthorize("@ss.hasPermi('product:relation:add')")@Log(title = "品牌分类关联", businessType = BusinessType.INSERT)@PostMappingpublic AjaxResult add(@RequestBody CategoryBrandRelation categoryBrandRelation) {return categoryBrandRelationService.saveDetails(categoryBrandRelation);}
实现:
@Overridepublic AjaxResult saveDetails(CategoryBrandRelation categoryBrandRelation) {//先判断当前的关联关系是否已存在LambdaQueryWrapper<CategoryBrandRelation> wrapper = new LambdaQueryWrapper<>(categoryBrandRelation);CategoryBrandRelation relation = getOne(wrapper);if (relation != null) {return AjaxResult.error("当前分类关联已存在");}Brand brand = brandService.getById(categoryBrandRelation.getBrandId());Category category = categoryService.getById(categoryBrandRelation.getCatelogId());categoryBrandRelation.setBrandName(brand.getName());categoryBrandRelation.setCatelogName(category.getName());boolean save = save(categoryBrandRelation);if (save) {return AjaxResult.success();}else{return AjaxResult.error();}}
这里要为两个冗余字段附上值,以便查询的时候不要多表去查,提高效率
2.3 删除
没什么好说的,利用传来的关联id集合,直接使用MP的批量删除就行了
/*** 删除品牌分类关联*/@ApiOperation("删除品牌分类关联")//@PreAuthorize("@ss.hasPermi('product:relation:remove')")@Log(title = "品牌分类关联", businessType = BusinessType.DELETE)@DeleteMapping("/{ids}")public AjaxResult remove(@PathVariable Long[] ids) {return toAjax(categoryBrandRelationService.removeByIds(Arrays.asList(ids)));}
四、总结
前端就是引入那个分类关联相关的东西,该导入的组件导好,该导入的方法导好,把数据域配好,方法修改好就行了
总结前端开发步骤:
1. 导入好组件相关的基本构件,就是那三部分
别的组件、方法等
2. 看数据域是否要增添
3. 看方法是否要修改
这里后端的话:
1. 要知道分页模糊查询,这是最基本的,知道配合若依开发
2. 要对增删改接口有全局的意识,这点很重要,比如说增加的话,是不是需要额外的添加属性
删除的话,是不是还要删其他表,修改的话是不是也要动其他表
3. 了解若依的返回逻辑,对于增删改,若依是以toAjax()这种顶级封装的方式进行返回的,按照布尔值,选择是success还是error。而对于查询,是以TableDataInfo对象返回的,我们可以根据自己的需要,也可以改变这种方式,在service实现中来返回request对象,这样可以增加异常信息返回给前端。
相关文章:

谷粒商城第十一天-品牌管理中关联分类
目录 一、总述 二、前端部分 1. 调整查询调用 2. 关联分类 三、后端部分 四、总结 一、总述 之前是在商品的分类管理中直接使用的若依的逆向代码 有下面的几个问题: 1. 表格上面的参数填写之后,都是按照完全匹配进行搜索,没有模糊匹配…...

Selenium自动化测试实战之自动化测试基础
自动化测试概念 是把以人为驱动的测试转化为机器执行的一种过程,它是一种以程序测试程序的过程。 自动化只是测试方式,跟测试阶段无关。 可以把任何测试工作写一个程序自动化实现都可以称为自动化测试。 selenium自动化测试:2023最新的Sele…...
vue3+vite中使用postcss-px-to-viewport适配问题
适配方案postcss-px-to-viewport使用过程中出现以下问题: postcss-px-to-viewport 不适配最新版本的postcss8 ⚠️报错: postcss-px-to-viewport: postcss.plugin was deprecated. Migration guide: https://evilmartians.com/chronicles/postcss-8-plugin-migrati…...

web测试与app测试的区别
web测试与app测试的区别 首先从系统架构来看的话: web项目,一般都是b/s架构,基于浏览器的,而app则是c/s的,必须要有客户端。那么在系统测试测试的时候就会产生区别了。 web测试只要更新了服务器端,客户端…...
深入理解高并发编程 - 分析创建线程池究竟有哪些方式
1、使用Executors工厂方法: 使用Executors工厂方法创建线程池是一种简单快捷的方式,适用于一些常见的线程池需求。以下是几个示例,演示如何使用Executors工厂方法创建不同类型的线程池: 固定大小线程池 (newFixedThreadPool)&am…...

Kafka第一课概述与安装
生产经验 面试重点 Broker面试重点 代码,开发重点 67 章了解 如何记录行为数据 1. Kafka概述 1.产生原因 前端 传到日志 日志传到Flume 传到HADOOP 但是如果数据特比大,HADOOP就承受不住了 2.Kafka解决问题 控流消峰 Flume传给Kafka 存到Kafka Hadoop 从Kafka…...

Linux MQTT智能家居项目(智能家居界面布局)
文章目录 前言一、创建工程项目二、界面布局准备工作三、正式界面布局总结 前言 一、创建工程项目 1.选择工程名称和项目保存路径 2.选择QWidget 3.添加保存图片的资源文件: 在工程目录下添加Icon文件夹保存图片: 将文件放入目录中: …...

【Vue3】Vue3 UI 框架 | Element Plus —— 创建并优化表单
安装 # NPM $ npm install element-plus --save // 或者(下载慢切换国内镜像) $ npm install element-plus -S// 可以选择性安装 less npm install less less-loader -D // 可以选择性配置 自动联想src目录Element Plus 的引入和注入 main.ts import…...

如何基于 ACK Serverless 快速部署 AI 推理服务
作者:元毅 随着 AI 浪潮的到来,各种 AI 应用层出不穷,众所周知 AI 应用对 GPU 资源强烈依赖,但 GPU 很昂贵,如何降低 GPU 资源使用成本成为用户首要问题。而 AI 与 Serverless 技术结合,完全可以达到按需使…...

【奥义】如何用ChatGPT写论文搞模型
目录 你是否曾经在复现科研论文的结果时感到困难重重? 引言 1 打开需要复现的目标文献 2 提取公式定义的语句 3 文章公式、图实现 (1)用python复现目标文献中的公式 (2)用python复现目标文献中的图 4 Copy代码…...

欢迎光临,博客网站
欢迎光临:YUNYE博客~https://yunyeblog.com/更多的文章,供大家参考学习!!!...

通过TightVNC远程访问MacOS
目录 一、下载 TightVNC 下载链接:https://www.tightvnc.com/ 下载后按步骤进行安装,安装完成后安装目录如下: 运行 tvnviewer.exe,输入远程 IP,点击【connect】: 输入密码,点击【OK】后即可远…...

智安网络|网络安全:危机下的创新与合作
随着信息技术的迅猛发展和互联网的普及,我们进入了一个高度网络化的社会。网络在提供便利和连接的同时,也带来了许多安全隐患和挑战。 一、网络安全的危险 **1.数据泄露和隐私侵犯:**网络上的个人和机构数据存在遭受泄露和盗取的风险&#…...

从系统角度,看智能制造|百世慧®
7月31日我们结束了智能制造专题第二期“电池智能制造质量管理应用及案例分享”的线上研讨会,有不少朋友没有来得及参加智能制造专题第一期研讨会,同时又工作繁忙。所以!今天就由我百小能为大家快速讲解第一期研讨会——“电池智能制造应用”的…...
Dubbo 与 gRPC、Spring Cloud、Istio 的关系
很多开发者经常会问到 Apache Dubbo 与 Spring Cloud、gRPC 以及一些 Service Mesh 项目如 Istio 的关系,要解释清楚它们的关系并不困难,你只需要跟随这篇文章和 Dubbo 文档做一些更深入的了解,但总的来说,它们之间有些能力是重合…...
【uniapp 中使用uni-popup阻止左滑退出程序】
在uniapp中,可以使用uni-app插件uni-popup提供的阻止左滑退出程序的功能。具体步骤如下: 安装uni-popup插件:在HBuilderX编辑器中,打开manifest.json文件,找到“dependencies”字段,在其后添加:…...

netty学习分享(一)
TCP与UDP TCP 是面向连接的、可靠的流协议,通过三次握手建立连接,通讯完成时要拆除连接。 UDP是面向无连接的通讯协议,UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象 端口号: 端口号用…...

前端跨域问题解决方法
跨域是WEB浏览器专有的同源限制访问策略。(后台接口调用和postman等工具会出现) 跨源资源共享(CORS,或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端…...
html基础面试题 html的元素居中的常用方法(基础知识温习)
html基础面试题 & html的元素居中的常用方法日常温习 1,使用text-align: center;属性: 对于内联元素(如文本或图片),可以将其父元素的text-align属性设置为center。 <div style"text-align: center;&quo…...

VScode如何设置中文教程
前言:打开VSCode软件,可以看到刚刚安装的VSCode软件默认使用的是英文语言环境,但网上都是vscode中文界面教你怎么设置中文,可能不利于小白阅读,所以重装vscode,手摸手从英文变成中文。 设置为中文 打开VS…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...