leecodecode【区间DP+树形DP】【2026.6.10打卡-java版本】

发布时间:2026/6/11 3:44:59

leecodecode【区间DP+树形DP】【2026.6.10打卡-java版本】 最长回文子序列要点两个for维护区间class Solution { public int longestPalindromeSubseq(String s) { char[] c s.toCharArray(); int n s.length(); int[][] f new int[n][n]; for(int i n-1; i0; i--){ f[i][i] 1; for(int j i1; j n; j){ f[i][j] c[i] c[j] ? f[i1][j-1] 2 : Math.max(f[i1][j], f[i][j-1]); } } return f[0][n-1]; } }多边形三角剖分的最低得分要点困难class Solution { public int minScoreTriangulation(int[] v) { int n v.length; int[][] f new int[n][n]; for (int i n - 3; i 0; i--) { for (int j i 2; j n; j) { f[i][j] Integer.MAX_VALUE; for (int k i 1; k j; k) { f[i][j] Math.min(f[i][j], f[i][k] f[k][j] v[i] * v[j] * v[k]); } } } return f[0][n - 1]; } }二叉树的直径要点leftright/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val val; * this.left left; * this.right right; * } * } */ class Solution { //dfs int ans 1; public int diameterOfBinaryTree(TreeNode root) { //int ans 1; depth(root); return ans - 1; } public int depth(TreeNode root){ if(root null){ return 0; } int left depth(root.left); int right depth(root.right); ans Math.max(ans, leftright1); return Math.max(left, right) 1; } }二叉树中的最大路径和要点加上root。val/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode() {} * TreeNode(int val) { this.val val; } * TreeNode(int val, TreeNode left, TreeNode right) { * this.val val; * this.left left; * this.right right; * } * } */ class Solution { int ans Integer.MIN_VALUE; public int maxPathSum(TreeNode root) { dfs(root); return ans; } public int dfs(TreeNode root){ if(root null){ return 0; } int left dfs(root.left); int right dfs(root.right); ans Math.max(leftrightroot.val , ans); return Math.max(root.valMath.max(left, right), 0); } }相邻字符不同的最长路径要点多叉树class Solution { private ListInteger[] g; private char[] s; private int ans; public int longestPath(int[] parent, String s) { this.s s.toCharArray(); int n parent.length; g new ArrayList[n]; Arrays.setAll(g, e - new ArrayList()); for (int i 1; i n; i) { g[parent[i]].add(i); } dfs(0); return ans 1; } private int dfs(int x) { int maxLen 0; for (int y : g[x]) { int len dfs(y) 1; if (s[y] ! s[x]) { ans Math.max(ans, maxLen len); maxLen Math.max(maxLen, len); } } return maxLen; } }随机知识核心题**你觉得怎么保证消息不丢RabbitMQ 为此提供了哪些机制面试官为什么这么问消息丢失是生产事故。我问这个是要你从生产端、Broker 端、消费端三个环节完整阐述每个环节都说到关键机制。能说全说明你至少有排查过问题的意识。希望听到怎样的回答生产端Producer → Broker开启Publisher Confirm机制。生产者发消息后等待 Broker 返回确认没收到就重发。Broker 端队列持久化durable true。消息持久化deliveryMode 2。注意持久化也不是绝对不丢毕竟刚写完缓存还没刷盘可能宕机。更可靠可用镜像队列Mirror Queue。消费端Broker → Consumer关闭自动 ACK采用手动确认basicAck。处理成功才确认失败则basicNack或basicReject消息重回队列或进入死信。总结至少要提到Confirm 持久化 手动 ACK三者组合才能做到消息可靠传递。候选人好的这是一个生产环境中非常关键的问题。消息丢失可能发生在三个环节生产端到 Broker、Broker 自身、Broker 到消费端。要保证消息不丢就必须在每个环节都做好防护形成闭环。第一生产端防止发送时消息丢失。Producer 把消息发送给 Broker 的过程中可能因为网络抖动或 Broker 宕机导致消息没有送达。RabbitMQ 提供了Publisher Confirm发布确认机制来解决这个问题。开启 Confirm 模式后生产者每发一条消息Broker 收到并持久化后会返回一个 ACK 告诉生产者“我收到了”。如果消息投递失败比如找不到指定的交换机Broker 会返回 NACK或者在一定时间内没有任何回应。生产端代码需要处理这两种情况收到 ACK 就继续发下一条收到 NACK 或超时就重发这条消息。Confirm 是异步的可以批量确认性能比事务机制好得多是生产环境的标配。第二Broker 端防止消息在存储时丢失。消息到了 Broker 之后如果 Broker 突然宕机重启内存中的消息会全部丢失。所以 RabbitMQ 提供了持久化能力但持久化不是单一开关需要同时满足两个条件队列持久化声明队列时设置durable true。这样即使 Broker 重启队列本身不会被删除积压的消息还在。消息持久化发送消息时设置deliveryMode 2消息属性标记为持久化。这样消息会被写入磁盘而不是只存在内存里。但注意持久化也不是绝对安全。RabbitMQ 并不是每收到一条消息就立刻刷盘而是间隔一段时间批量写入如果在刷盘间隔内 Broker 宕机最近几条消息仍然可能丢失。所以有了更进一步的方案——镜像队列。镜像队列把队列数据同步到集群中的多个节点上。消息写入主节点后同步复制到从节点。主节点宕机从节点自动接管消息不会丢。代价是性能下降和网络开销增加。现在更推荐的是Quorum Queue仲裁队列基于 Raft 协议保证多数节点一致比老式镜像队列更可靠。第三消费端防止处理时消息丢失。Broker 把消息投递给消费者如果消费者刚收到消息还没处理就挂了消息也会丢。所以 RabbitMQ 在消费端提供了手动 ACK 机制。默认是自动 ACK消息投递给消费者Broker 立刻删掉消息。消费者宕机导致消息没处理完这条消息就永丢了。生产上必须关掉自动 ACK开启手动确认消费者处理完业务逻辑后调用basicAck告诉 Broker 可以安全删除消息。如果业务处理失败调basicNack或basicReject让消息重新入队或进入死信队列排队后续处理。手动 ACK 是整个可靠性链的最后一道防线处理成功才确认失败就重试或补偿。第四用具体场景串联。用户注册为例注册成功后触发发短信。注册成功要保证短信至少投递一次。用的是Confirm 持久化 手动 ACK的组合。生产者先发消息到 Broker用 Publisher Confirm 确认消息已送达消息和队列都持久化防止重启丢失。消费端关掉自动 ACK手动确认。如果消费端拿到消息后调短信服务失败可以有两种处理方式一是返回 NACK 把消息重新入队等待重试需要做好幂等处理二是超过重试上限后将消息转存到死信队列后续人工或定时任务补偿处理避免无限制重试对系统的冲击。同时为了防止消息积压可以配合死信队列加上监控告警当积压超过阈值时能立刻发现并人工介入。总结一句话保证消息不丢需要在生产端用 Publisher Confirm、Broker 端用持久化和镜像/仲裁队列、消费端用手动 ACK三者组合形成可靠传输闭环。另外还有两个重要补充一是声明 Exchange 和 Queue 时开启持久化并通过管理界面确认 D 标识已经生效因为切换配置后若不重建队列旧的队列属性不会自动变化需要物理删除再重新声明二是即使消息不会丢失也可能会重复服务链路必须实现幂等结合业务唯一键或消费记录去重表来保证数据的最终一致性。碎碎念后续会更新每天学习的八股和算法 题开始准备秋招的第31天。努力连续更新100天以后每天就按秋招项目【javaagent】科研必做项目算法八股锻炼身体来总结。总结得多动脑子1.算法要系统过一遍【灵神】23/27【早上】1h2.秋招项目【java】开始实际看业务1/6无【agent】还在学整理cc无3.科研要跑一下【下午】3h【晚上】3h4.检测项目也得总结文档无1h6.背八股无7.锻炼身体1h反思得用脑子多想不能老依靠ai————————————————

相关新闻