当前位置: 首页 > news >正文

算法随笔(一)

一、油车最远距离

每辆车每跑 1 公里消耗 1 升油,油箱容量 12 升;车与车之间可随时无损互相加油,被“弃置”的车不必返回。问最远能让一辆车开多远。

思路

让多辆车一起走,在合适的位置把其中一辆的油“喂”给其他车,使剩下的车都满箱,然后把这辆空车留在原地不再前进。

当有 m 辆车一起走时,总耗油是 m 升/公里。要凑到正好“淘汰”1 辆(即净消耗一个满箱 C升),应走\frac{C}{m}公里。依次减少车数,直到只剩 1 辆独自前进。

当我们这C=12升、一共四辆车

  1. 4 车同行 12/4=3 公里,在 3 公里处把油分给其余三辆使其满箱,留下一辆空车停下。

  2. 3 车再走 12/3=41 公里,到 7 公里处再淘汰一辆。

  3. 2 车再走 12/2=6 公里,到 13 公里处再淘汰一辆。

  4. 剩下 1 车最后在13公里处再独走 12/1=12公里。

所以最后的公里数是25公里

这里有一个一般化结论

这种题应该不好用程序穷尽,让这些车能返回补油就是一个小学奥数题,没想到小学奥数题都是这种程度了吗?

二、基于父节点关联的扁平节点列表,构建树形结构并实现可视化打印

一个ArrayList<TreeNode>,每个节点仅存储「自身 ID」和「父节点 ID」(无直接子节点列表),节点结构如下:

// 核心节点结构(仅含父子关联必要字段)
class TreeNode {private String id;       // 节点唯一标识private String parentId; // 父节点ID(根节点为null)private String name;     // 节点名称(用于打印展示)// 构造器、getter、toString略
}

列表长这样

        List<TreeNode> nodes = new ArrayList<>();nodes.add(new TreeNode("1", null, "技术部"));       // 根节点:技术部(无父节点)nodes.add(new TreeNode("2", "1", "前端组"));        // 技术部的子节点:前端组nodes.add(new TreeNode("3", "1", "后端组"));        // 技术部的子节点:后端组nodes.add(new TreeNode("4", "2", "PC前端组"));     // 前端组的子节点:PC前端组nodes.add(new TreeNode("5", "2", "移动端组"));     // 前端组的子节点:移动端组nodes.add(new TreeNode("6", "3", "Java组"));       // 后端组的子节点:Java组nodes.add(new TreeNode("7", "3", "大数据组"));     // 后端组的子节点:大数据组nodes.add(new TreeNode("8", null, "产品部"));       // 根节点:产品部(无父节点)nodes.add(new TreeNode("9", "8", "产品设计组"));   // 产品部的子节点:产品设计组

要求输出入下

=== 部门层级(空格缩进) ===
技术部前端组PC前端组移动端组后端组Java组大数据组
产品部产品设计组

思路

我最初的思路是 用一个map 把 每个节点的子节点存储起来,

  • 键(Key):父节点 ID
  • 值(Value):该父节点对应的所有子节点列表(List<TreeNode>

然后用递归的方式也就是树的深度有限遍历打印

但是在做这个算法的时候时间有限,没手搓出来,感觉快了,但是看了AI给的方法,感觉用代码优雅的写出来还是很有难度的。

完整代码加注释

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 树状结构打印工具类(空格缩进版)* 功能:将扁平存储的节点列表(通过parentId关联父子关系)转换为树状结构,* 并仅通过空格缩进的方式在控制台打印层级关系,不使用特殊符号*/
public class TreeSpacePrinter {/*** 树节点实体类* 存储节点的唯一标识、父节点标识及节点名称,用于构建树状结构*/static class TreeNode {private String id;         // 节点唯一ID(用于标识当前节点)private String parentId;   // 父节点ID(用于关联父节点,根节点为null)private String name;       // 节点名称(打印时展示的内容)/*** 构造方法:初始化节点的核心属性* @param id 节点唯一标识* @param parentId 父节点标识(根节点传null)* @param name 节点展示名称*/public TreeNode(String id, String parentId, String name) {this.id = id;this.parentId = parentId;this.name = name;}// Getter方法:供工具类获取节点属性public String getId() { return id; }public String getParentId() { return parentId; }public String getName() { return name; }/*** 重写toString方法:打印节点时直接展示名称* 避免默认打印对象地址,简化输出内容*/@Overridepublic String toString() { return name; }}/*** 构建父节点到子节点的映射关系* 作用:将扁平的节点列表转换为"父节点ID→子节点列表"的映射,* 便于快速查找某个节点的所有子节点,避免多次遍历列表* @param nodeList 原始扁平节点列表* @return 父节点ID为键,对应子节点列表为值的Map*/private static Map<String, List<TreeNode>> buildTreeMap(List<TreeNode> nodeList) {// 初始化Map:键为父节点ID,值为该父节点下的所有子节点Map<String, List<TreeNode>> treeMap = new HashMap<>();// 遍历所有节点,将节点添加到其父节点对应的子列表中for (TreeNode node : nodeList) {// computeIfAbsent:若父节点ID对应的列表不存在,则创建空列表;存在则直接获取// 然后将当前节点添加到该列表中,完成父子关联treeMap.computeIfAbsent(node.getParentId(), k -> new ArrayList<>()).add(node);}return treeMap;}/*** 查找所有根节点* 根节点定义:父节点ID为null,或在节点列表中不存在对应父节点的节点* @param nodeList 原始扁平节点列表* @return 所有根节点组成的列表*/private static List<TreeNode> findRootNodes(List<TreeNode> nodeList) {List<TreeNode> rootNodes = new ArrayList<>();// 提取所有节点的ID到列表,用于快速判断父节点是否存在List<String> allNodeIds = nodeList.stream().map(TreeNode::getId).toList();// 遍历节点,筛选出根节点for (TreeNode node : nodeList) {String parentId = node.getParentId();// 根节点条件:父节点ID为null,或父节点ID不在所有节点ID中(父节点不存在)if (parentId == null || !allNodeIds.contains(parentId)) {rootNodes.add(node);}}return rootNodes;}/*** 递归打印节点及其子节点(核心打印方法)* 通过控制空格缩进量体现节点层级,每层缩进固定数量的空格* @param node 当前需要打印的节点* @param treeMap 父节点到子节点的映射(用于获取当前节点的子节点)* @param depth 当前节点的层级深度(根节点为0,子节点深度+1)*/private static void printNode(TreeNode node, Map<String, List<TreeNode>> treeMap, int depth) {// 计算缩进字符串:每层缩进4个空格(可根据需要修改空格数量调整缩进幅度)String indent = "    ".repeat(depth);// 打印当前节点:缩进+节点名称(缩进量由深度决定,体现层级)System.out.println(indent + node);// 获取当前节点的所有子节点(从映射中根据节点ID查询)List<TreeNode> children = treeMap.get(node.getId());// 若没有子节点,直接返回(递归终止条件)if (children == null || children.isEmpty()) {return;}// 遍历所有子节点,递归打印(子节点深度=当前节点深度+1)for (TreeNode child : children) {printNode(child, treeMap, depth + 1);}}/*** 对外暴露的树状打印入口方法* 封装了树构建、根节点查找和打印的完整流程* @param nodeList 待打印的扁平节点列表*/public static void printTree(List<TreeNode> nodeList) {// 边界处理:若节点列表为空,直接提示if (nodeList == null || nodeList.isEmpty()) {System.out.println("节点列表为空,无需打印");return;}// 1. 构建父节点到子节点的映射Map<String, List<TreeNode>> treeMap = buildTreeMap(nodeList);// 2. 查找所有根节点List<TreeNode> rootNodes = findRootNodes(nodeList);// 3. 从根节点开始打印(根节点深度为0)for (TreeNode root : rootNodes) {printNode(root, treeMap, 0);}}/*** 测试方法:创建示例节点列表并验证打印效果* 模拟实际业务中的层级数据(如部门结构、菜单列表等)*/public static void main(String[] args) {// 1. 构建测试用的扁平节点列表(模拟从数据库查询的结果)List<TreeNode> nodes = new ArrayList<>();nodes.add(new TreeNode("1", null, "技术部"));       // 根节点:技术部(无父节点)nodes.add(new TreeNode("2", "1", "前端组"));        // 技术部的子节点:前端组nodes.add(new TreeNode("3", "1", "后端组"));        // 技术部的子节点:后端组nodes.add(new TreeNode("4", "2", "PC前端组"));     // 前端组的子节点:PC前端组nodes.add(new TreeNode("5", "2", "移动端组"));     // 前端组的子节点:移动端组nodes.add(new TreeNode("6", "3", "Java组"));       // 后端组的子节点:Java组nodes.add(new TreeNode("7", "3", "大数据组"));     // 后端组的子节点:大数据组nodes.add(new TreeNode("8", null, "产品部"));       // 根节点:产品部(无父节点)nodes.add(new TreeNode("9", "8", "产品设计组"));   // 产品部的子节点:产品设计组// 2. 打印提示信息并执行树状打印System.out.println("=== 部门层级结构(空格缩进展示) ===");printTree(nodes);}
}


文章转载自:

http://jViGjRDp.ycwym.cn
http://wNl8LuER.ycwym.cn
http://WCfU4a22.ycwym.cn
http://BGjrczUy.ycwym.cn
http://maMdsdhV.ycwym.cn
http://sbGc92Fh.ycwym.cn
http://aV4SOD5h.ycwym.cn
http://sElu0oit.ycwym.cn
http://BgNfnQip.ycwym.cn
http://sT4d75Zw.ycwym.cn
http://ZksgdbGb.ycwym.cn
http://LuTG9TyF.ycwym.cn
http://bPW5m7iR.ycwym.cn
http://66WgkAoG.ycwym.cn
http://hn0fZSXO.ycwym.cn
http://YtfXn1Ca.ycwym.cn
http://VaeDRhko.ycwym.cn
http://Oan8Hu3p.ycwym.cn
http://dTM5RVr1.ycwym.cn
http://hJvG2kbk.ycwym.cn
http://anEx5xs3.ycwym.cn
http://Fal9nkx2.ycwym.cn
http://WoE3Zgit.ycwym.cn
http://rVxM0fg0.ycwym.cn
http://gJ4QTOri.ycwym.cn
http://5OtgBCz0.ycwym.cn
http://1bkjQY0d.ycwym.cn
http://COYKgd4e.ycwym.cn
http://gX3wFjag.ycwym.cn
http://l3KX0KnX.ycwym.cn
http://www.dtcms.com/a/366170.html

相关文章:

  • Electron 执行python脚本
  • Dubbo(分布式RPC调用和分布式文件储存)
  • 如何简单理解状态机、流程图和时序图
  • 成为一个年薪30W+的FPGA工程师是一种什么体验?
  • 进程与线程详解, IPC通信与RPC通信对比,Linux前台与后台作业
  • 在国企干了 5 年 Java,居然不知道 RPC?这正常吗?
  • VU9P板卡设计方案:基于VU9P的32@ SFP28+4@ QSFP28路光纤交换板卡
  • Zynq开发实践(FPGA之uart发送)
  • 如何在 IntelliJ IDEA 中进行全局替换某个字段(或文本)
  • 案例精述 | 防护即智能 Fortinet赋能英科全栈安全重构实践
  • React学习之路永无止境:下一步,去向何方?
  • C#上位机解决ComboBox下拉框加载卡顿问题探析
  • wpf中资源的使用
  • 【Ubuntu扩容】Ubuntu启动项丢失、增加硬盘相关操作记录贴
  • Dubbo分布式服务框架全解析
  • 十一、容器化 vs 虚拟化-K8s-Kustomize
  • 免费低代码谁更优?斑斑与氚云深度对比,中小企业数字化转型选对平台很关键
  • 热烈庆祝“中国抗战胜利80周年”,织信低代码助力国之重器砥砺前行!
  • vue+elementUI 进行表格行内新增及校验,同行其他输入框数据影响当前输入框校验结果
  • Web与Nginx网站服务
  • VUE中引入tailwindcss样式(用于GemDesgin的页面生成)
  • 英飞凌ASIL-D级无刷电机驱动芯片TLE9189守护汽车安全
  • 新手SEO高效入门实践指南
  • Linux 基础IO-从 “一切皆文件” 到自定义 libc 缓冲区
  • 字符串(1)
  • 关于多Agent协作框架的讨论:以产品经理工作流为例对比Sub Agent与AutoGen
  • 论文阅读:arixv 2024 Adversarial Attacks on Large Language Models in Medicine
  • SpringMVC —— 响应和请求处理
  • 低代码开发平台技术总结
  • Coze源码分析-资源库-删除提示词-后端源码