【LeetCode每日一题合集】2023.9.4-2023.9.10(⭐二叉树的重建二分答案拓扑排序)

news2025/4/17 5:13:17

文章目录

  • 449. 序列化和反序列化二叉搜索树⭐⭐⭐⭐⭐(二叉树的重建)
    • 解法
    • 相关题目——297. 二叉树的序列化与反序列化⭐⭐⭐⭐⭐
      • 解法——深度优先搜索
  • 2605. 从两个数字数组里生成最小数字
    • 哈希表分情况讨论
    • 位运算表示集合,分情况讨论🐂(用位运算表示集合)
  • 1123. 最深叶节点的最近公共祖先
    • 解法1——dfs找深度,再往上找公共祖先
    • 解法2——一次dfs🐂(⭐要学习这个思路)
  • 2594. 修车的最少时间
    • 解法——二分查找答案(⭐)
    • 二分查找优化——使用哈希表统计各个能力人数
  • 2651. 计算列车到站时间(超简单取模题目)
  • 207. 课程表(拓扑排序)
    • 解法1——bfs拓扑排序
    • 解法2——dfs拓扑排序
  • 210. 课程表 II(求拓扑序列)

449. 序列化和反序列化二叉搜索树⭐⭐⭐⭐⭐(二叉树的重建)

https://leetcode.cn/problems/serialize-and-deserialize-bst/?envType=daily-question&envId=2023-09-04

在这里插入图片描述
提示:
树中节点数范围是 [0, 10^4]
0 <= Node.val <= 10^4
题目数据 保证 输入的树是一棵二叉搜索树。

解法

  • 给定一颗二叉树的先序遍历和中序遍历可以恢复这颗二叉树
  • 给定一颗二叉树的后序遍历和中序遍历可以恢复这棵二叉树
  • 由于二叉搜索树的中序遍历是有序的,因此给定一颗二叉树的先序遍历(或后续遍历),相当于有了中序遍历和先序遍历(或后续遍历),因此只要有先序遍历(或后序遍历)就可以恢复二叉搜索树

思路总结:
编码——将二叉搜索树的后序遍历结果保存在列表中,将列表转成字符串。
解码——使用split将列表转成字符串数组,将字符串数组解析到栈中,使用栈重建后序遍历二叉树。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {
    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        postOrder(root, list);  // 后序遍历,结果放入list
        String str = list.toString();
        return str.substring(1, str.length() - 1);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if (data.isEmpty()) return null;
        // 这里用", "分割是因为Java的toString方法对列表会生成类似[1, 2, 3]的结果
        String[] arr = data.split(", ");
        // 将String转成int存入栈中
        Deque<Integer> stk = new ArrayDeque<>();
        int len = arr.length;
        for (int i = 0; i < len; ++i) {
            stk.push(Integer.parseInt(arr[i]));
        }
        return construct(Integer.MIN_VALUE, Integer.MAX_VALUE, stk);
    }

    // 后序遍历
    void postOrder(TreeNode root, List<Integer> ls) {
        if (root == null) return;
        postOrder(root.left, ls);
        postOrder(root.right, ls);
        ls.add(root.val);
    }

    TreeNode construct(int lower, int upper, Deque<Integer> stk) {
        if (stk.isEmpty() || stk.peek() < lower || stk.peek() > upper) return null;
        int val = stk.pop();        // 取出最后一个节点作为根节点
        TreeNode root = new TreeNode(val);
        root.right = construct(val, upper, stk);    // 重建右子树
        root.left = construct(lower, val, stk);     // 重建左子树
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// String tree = ser.serialize(root);
// TreeNode ans = deser.deserialize(tree);
// return ans;

相关题目——297. 二叉树的序列化与反序列化⭐⭐⭐⭐⭐

https://leetcode.cn/problems/serialize-and-deserialize-binary-tree/

在这里插入图片描述

提示:
树中结点数在范围 [0, 10^4] 内
-1000 <= Node.val <= 1000

解法——深度优先搜索

https://leetcode.cn/problems/serialize-and-deserialize-binary-tree/solutions/290065/er-cha-shu-de-xu-lie-hua-yu-fan-xu-lie-hua-by-le-2/

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        return enCode(root, "");        // 存储前序遍历的结果
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        String[] arr = data.split(",");
        List<String> ls = new LinkedList<String>(Arrays.asList(arr));
        return deCode(ls);
    }

    // 
    public String enCode(TreeNode root, String str) {
        if (root == null) {
            str += "None,";         // 使用None
        } else {
            str += str.valueOf(root.val) + ",";
            str = enCode(root.left, str);
            str = enCode(root.right, str);
        }
        return str;
    }

    // 前序遍历重建
    public TreeNode deCode(List<String> ls) {
        if (ls.get(0).equals("None")) {
            ls.remove(0);
            return null;
        }

        TreeNode root = new TreeNode(Integer.valueOf(ls.get(0)));
        ls.remove(0);
        root.left = deCode(ls);
        root.right = deCode(ls);
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// TreeNode ans = deser.deserialize(ser.serialize(root));

总结一下这种题目的套路——
把二叉树用前序遍历或者后序遍历存成字符串,(如果不是搜索树的话需要用 None 表示空节点)。
重建的时候通过 split 将各个节点变成 列表或者数组的形式存储下来,同样按照前序遍历或者后序遍历重建二叉树即可。

2605. 从两个数字数组里生成最小数字

https://leetcode.cn/problems/form-smallest-number-from-two-digit-arrays/description/?envType=daily-question&envId=2023-09-05

在这里插入图片描述

提示:
1 <= nums1.length, nums2.length <= 9
1 <= nums1[i], nums2[i] <= 9
每个数组中,元素 互不相同 。

哈希表分情况讨论

class Solution {
    public int minNumber(int[] nums1, int[] nums2) {
        int ans = 99, a = 10, b = 10;
        Set<Integer> s = new HashSet<>();
        for (int num: nums1) {
            s.add(num);
            a = Math.min(a, num);
        }
        for (int num: nums2) {
            if (s.contains(num)) ans = Math.min(ans, num);
            b = Math.min(b, num);
        }
        // 如果有交集 直接返回
        if (ans != 99) return ans;
        // 没有交集,返回 a * 10 + b
        if (a > b) {
            int t = a;
            a = b;
            b = t;
        }
        return 10 * a + b;
    }
}

位运算表示集合,分情况讨论🐂(用位运算表示集合)

class Solution {
    public int minNumber(int[] nums1, int[] nums2) {
        int mask1 = 0, mask2 = 0;
        for (int x: nums1) mask1 |= 1 << x;
        for (int x: nums2) mask2 |= 1 << x;
        // 检查是否有交集
        int m = mask1 & mask2;
        if (m > 0) return Integer.numberOfTrailingZeros(m);
        // 如果没有交集
        int x = Integer.numberOfTrailingZeros(mask1), y = Integer.numberOfTrailingZeros(mask2);
        return Math.min(x * 10 + y, y * 10 + x);
    }
}

1123. 最深叶节点的最近公共祖先

https://leetcode.cn/problems/lowest-common-ancestor-of-deepest-leaves/?envType=daily-question&envId=2023-09-06

在这里插入图片描述

提示:
树中的节点数将在 [1, 1000] 的范围内。
0 <= Node.val <= 1000
每个节点的值都是 独一无二 的。

解法1——dfs找深度,再往上找公共祖先

/**
 * 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 {
    Queue<TreeNode> q = new LinkedList<>();
    Map<TreeNode, TreeNode> m = new HashMap<>();
    int d = 0;

    public TreeNode lcaDeepestLeaves(TreeNode root) {
        dfs(root, 0);
        while (q.size() != 1) {
            int sz = q.size();
            Set<TreeNode> s = new HashSet<>();
            for (int i = 0; i < sz; ++i) {
                s.add(m.get(q.poll()));
            }
            for (TreeNode t: s) {
                q.offer(t);
            }
        }
        return q.poll();
    }

    public void dfs(TreeNode root, int t) {
        if (root.left == null && root.right == null) {
            if (t > d) {
                q.clear();
                d = t;
            }
            if (t == d) q.offer(root);
        }
        else {
            if (root.left != null) {
                m.put(root.left, root);
                dfs(root.left, t + 1);
            }
            if (root.right != null) {
                m.put(root.right, root);
                dfs(root.right, t + 1);
            }
        }
    }
}

解法2——一次dfs🐂(⭐要学习这个思路)

https://leetcode.cn/problems/lowest-common-ancestor-of-deepest-leaves/solutions/488055/liang-chong-si-lu-yi-chong-qian-xu-bian-li-yi-chon/?envType=daily-question&envId=2023-09-06在这里插入图片描述

class Solution {
    TreeNode res = null;	// 答案
    int pre = 0;		// 更新最大深度

    public TreeNode lcaDeepestLeaves(TreeNode root) {
        dfs(root, 1);
        return res;
    }

    int dfs(TreeNode node, int d) {
        if (node == null) return d;
        int l = dfs(node.left, d + 1), r = dfs(node.right, d + 1);
        if (l == r && l >= pre) {
            res = node;
            pre = l;
        }
        return Math.max(l, r);
    }
}

2594. 修车的最少时间

https://leetcode.cn/problems/minimum-time-to-repair-cars/?envType=daily-question&envId=2023-09-07

在这里插入图片描述

提示:
1 <= ranks.length <= 10^5
1 <= ranks[i] <= 100
1 <= cars <= 10^6

解法——二分查找答案(⭐)

class Solution {
    public long repairCars(int[] ranks, int cars) {
        Arrays.sort(ranks);
        long l = ranks[0], r = (long)ranks[0] * cars * cars;
        while (l < r) {
            long mid = l + r >> 1;
            if (check(mid, ranks, cars)) r = mid;
            else l = mid + 1;
        }
        return l;
    }

    public boolean check(long k, int[] ranks, int cars) {
        for (int r: ranks) {
            cars -= Math.floor(Math.sqrt((double)(k / r)));
        }
        return cars <= 0;
    }
}

二分查找优化——使用哈希表统计各个能力人数

能力值相同的人,在 t 分钟内修好的车的个数是一样的。

根据数据范围,ranks 中至多有 100 个不同的数字,我们可以统计 ranks 中每个数字的出现次数,这样每次二分至多循环 100 次。

class Solution {
    public long repairCars(int[] ranks, int cars) {
        int[] cnt = new int[101];
        int minR = ranks[0];
        for (int r: ranks) {
            cnt[r]++;
            minR = Math.min(minR, r);
        }
        long l = 0, r = (long)minR * cars * cars;
        while (l < r) {
            long mid = l + r >> 1;
            if (check(mid, cars, cnt, minR)) r = mid;
            else l = mid + 1;
        }
        return l;
    }

    public boolean check(long k, int cars, int[] cnt, int minR) {
        for (int r = minR; r <= 100; ++r) {
            cars -= Math.floor(Math.sqrt(k / r)) * cnt[r];
        }
        return cars <= 0;
    }
}

2651. 计算列车到站时间(超简单取模题目)

https://leetcode.cn/problems/calculate-delayed-arrival-time/?envType=daily-question&envId=2023-09-08

在这里插入图片描述

提示:
1 <= arrivaltime < 24
1 <= delayedTime <= 24

class Solution {
    public int findDelayedArrivalTime(int arrivalTime, int delayedTime) {
        return (arrivalTime + delayedTime) % 24;
    }
}

207. 课程表(拓扑排序)

https://leetcode.cn/problems/course-schedule/?envType=daily-question&envId=2023-09-09

在这里插入图片描述

提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
0 <= ai, bi < numCourses
prerequisites[i] 中的所有课程对 互不相同

解法1——bfs拓扑排序

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        List<Integer>[] g = new ArrayList[numCourses];
        Arrays.setAll(g, e -> new ArrayList<>());
        int[] in = new int[numCourses];
        for (int[] p: prerequisites) {
            g[p[0]].add(p[1]);
            in[p[1]]++;
        }
        int cnt = numCourses;
        Queue<Integer> q = new LinkedList<>();
        for (int i = 0; i < numCourses; ++i) {
            if (in[i] == 0) {
                q.offer(i);
                cnt--;
            }
        }

        while (!q.isEmpty()) {
            int cur = q.poll();
            for (int nt: g[cur]) {
                if (--in[nt] == 0) {
                    q.offer(nt);
                    cnt--;
                }
            }
        }
        return cnt == 0;
    }
}

解法2——dfs拓扑排序

class Solution {
    List<Integer>[] g;
    boolean[] st;
    int[] in;
    int sum = 0;

    public boolean canFinish(int numCourses, int[][] prerequisites) {
        g = new ArrayList[numCourses];
        Arrays.setAll(g, e -> new ArrayList<Integer>());
        in = new int[numCourses];
        st = new boolean[numCourses];
        for (int[] prerequisity: prerequisites) {
            g[prerequisity[0]].add(prerequisity[1]);
            in[prerequisity[1]]++;
        }
        
        for (int i = 0; i < numCourses; ++i) {
            if (in[i] == 0) {
                dfs(i);
            }
        }

        return sum == numCourses;
    }

    public void dfs(int x) {
        if (st[x]) return;
        ++sum;
        st[x] = true;
        for (int y: g[x]) {
            if (--in[y] == 0) {
                dfs(y);
            }
        }
    }
}

210. 课程表 II(求拓扑序列)

https://leetcode.cn/problems/course-schedule-ii/?envType=daily-question&envId=2023-09-10

在这里插入图片描述
提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= numCourses * (numCourses - 1)
prerequisites[i].length == 2
0 <= ai, bi < numCourses
ai != bi
所有[ai, bi] 互不相同

class Solution {
    List<Integer>[] g;
    List<Integer> ans = new ArrayList();
    int[] in;

    public int[] findOrder(int numCourses, int[][] prerequisites) {
        g = new ArrayList[numCourses];
        Arrays.setAll(g, e -> new ArrayList<Integer>());
        in = new int[numCourses];
        for (int[] prerequisity: prerequisites) {
            g[prerequisity[1]].add(prerequisity[0]);
            in[prerequisity[0]]++;
        }
        
        Queue<Integer> q = new LinkedList<Integer>();
        for (int i = 0; i < numCourses; ++i) {
            if (in[i] == 0) {
                q.offer(i);
                ans.add(i);
            }
        }
        while (!q.isEmpty()) {
            int x = q.poll();
            for (int y: g[x]) {
                if (--in[y] == 0) {
                    ans.add(y);
                    q.offer(y);
                }
            } 
        }

        if (ans.size() == numCourses) return ans.stream().mapToInt(Integer::intValue).toArray();
        else return new int[]{};
    }
}

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

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

相关文章

Day60|单调栈part03:84.柱状图中最大的矩形

柱状图中最大的矩形 leetcode链接&#xff1a;力扣题目链接 视频链接&#xff1a;单调栈&#xff0c;又一次经典来袭&#xff01; LeetCode&#xff1a;84.柱状图中最大的矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;…

【多线程】线程安全的单例模式

线程安全的单例模式 饿汉模式懒汉模式单线程版多线程版多线程版(改进) 单例模式能保证某个类在程序中只存在 唯一 一份实例, 而不会创建出多个实例&#xff0c;从而节约了资源并实现数据共享。 比如 JDBC 中的 DataSource 实例就只需要一个. 单例模式具体的实现方式, 分成 “饿…

Unity3D URP 仿蜘蛛侠风格化BloomAO

Unity3D URP 仿蜘蛛侠风格化Bloom&AO BloomBloom效果流程&#xff1a;制作控制面板VolumeComponent.CSCustom Renderer FeatherCustom Renderer PassBloom ShaderComposite Shader 完善Custom Feather风格化AO 总结 本篇文章介绍在URP中如何进行风格化后处理&#xff0c;使…

【MATLAB第74期】#源码分享 | 基于MATLAB的ARX-ARMAX线性自回归移动平均外生模型(结合最小二乘思路)

【MATLAB第74期】#源码分享 | 基于MATLAB的ARX-ARMAX线性自回归移动平均外生模型&#xff08;结合最小二乘思路&#xff09; 根据ARX预测输出和实际输出的误差向量&#xff0c;采用ARMAX算法结合ARX误差建模&#xff0c;对预测值进一步细化。通过将误差描述为白噪声的移动平均…

Spring事务管理: 构建稳健的数据库事务处理

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

C++算法 —— 动态规划(4)子数组

文章目录 1、动规思路简介2、最大子数组和3、环形子数组的最大和4、乘积最大子数组5、乘积为正数的最长子数组长度6、等差数列划分7、最长湍流子数组8、单词拆分9、环绕字符串中唯一的子字符串 每一种算法都最好看完第一篇再去找要看的博客&#xff0c;因为这样会帮你梳理好思路…

商城系统优化

1、DB、模板的渲染速度&#xff08;thymeleaf&#xff09;、静态资源、日志、JVM 数据库的优化&#xff08;参照数据库优化课程&#xff09;使用索引&#xff0c;减少数据库的交互次数、缓存 thymeleaf使用缓存 静态资源&#xff1a;放到nginx中&#xff0c;实现动静分离 2、…

【数学】ABC 319 E

E - Bus Stops 题意&#xff1a; 思路&#xff1a; 感觉思路比较简单 首先注意到每个询问的范围是1e9&#xff0c;不难想到答案一定存在某个循环节&#xff0c;最后一定是要 %T的 那么问题就在于找到这个循环节是什么 猜想循环节为lcm(p1, p2, p3, ....) 用小数据验证 n…

一篇博客教会您SpringMVC文件上传、下载,多文件上传及工具jrebel的使用

目录 一.文件上传 二.文件下载 三.多文件上传 四&#xff0c;jrebel的介绍 前言&#xff1a; 我们之前已经实现了SpringMVC的增删改查&#xff0c;今天这一篇博客教会您SpringMVC文件上传、下载&#xff0c;多文件上传及工具jrebel的使用&#xff0c;希望这篇博客能够给正在…

二、Spark 调度系统

目录 Spark 调度系统DAGSchedulerSchedulerBackendTaskSchedulerExecutorBackendSpark 任务调度流程 Spark 调度系统 分布式计算的精髓&#xff0c;在于如何把抽象的计算图&#xff0c;转化为实实在在的分布式计算任务&#xff0c;然后以并行计算的方式交付执行。 Spark调度系…

Mojo安装使用初体验

一个声称比python块68000倍的语言 蹭个热度&#xff0c;安装试试 系统配置要求&#xff1a; 不支持Windows系统 配置要求: 系统&#xff1a;Ubuntu 20.04/22.04 LTSCPU&#xff1a;x86-64 CPU (with SSE4.2 or newer)内存&#xff1a;8 GiB memoryPython 3.8 - 3.10g or cla…

华为云云耀云服务器L实例评测 | 分分钟完成打地鼠小游戏部署

前言 在上篇文章【华为云云耀云服务器L实例评测 | 快速部署MySQL使用指南】中&#xff0c;我们已经用【华为云云耀云服务器L实例】在命令行窗口内完成了MySQL的部署并简单使用。但是后台有小伙伴跟我留言说&#xff0c;能不能用【华为云云耀云服务器L实例】来实现个简单的小游…

车载诊断数据库——诊断问卷调查表与CDD关联关系

车载诊断数据库——诊断问卷调查表与CDD关联关系 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生…

超级电容-电池-超级电容混合储能系统能量管理simulink仿真建模模型

建立混合储能系统模型 在Simulink中&#xff0c;首先需要建立一个超级电容和蓄电池并联的混合储能系统模型。其中&#xff0c;超级电容和蓄电池的荷电状态&#xff08;SOC&#xff09;需要根据实际情况进行管理。荷电状态可以通过对电池和超级电容的电压、电流等进行测量&…

说透 Nacos 一致性协议

1 Nacos ⼀致性协议 1.1 为什么 Nacos 需要⼀致性协议 Nacos尽可能减少用户部署以及运维成本&#xff0c;做到用户只需要⼀个程序包&#xff0c;就快速单机模式启动 Nacos 或集群模式启动 Nacos。而 Nacos 是⼀个需要存储数据的组件&#xff0c;为实现目标&#xff0c;就要在…

透视俄乌网络战之二:Conti勒索软件集团(上)

透视俄乌网络战之一&#xff1a;数据擦除软件 Conti勒索软件集团&#xff08;上&#xff09; 1. Conti简介2. 组织架构3. 核心成员4. 招募途径5. 工作薪酬6. 未来计划参考 1. Conti简介 Conti于2019年首次被发现&#xff0c;现已成为网络世界中最危险的勒索软件之一&#xff0…

汇川PLC学习Day3:轴控代码编写、用户程序结构说明与任务配置示例、

汇川PLC学习Day3&#xff1a;轴控代码编写、用户程序结构说明、任务配置示例 一、新建轴与轴控代码编写 1. 新建轴 (1)新建一个轴 &#xff08;2&#xff09;将轴名字更新为实际名字 可以后面实例化后再更改&#xff0c;汇川可以在更新名字时同步更新其他编写的代码名字&a…

GStreamer时钟同步

播放复杂媒体时&#xff0c;每个audio和video sample必须在特定时间按特定顺序播放。为此&#xff0c;GStreamer提供了一种同步机制&#xff0c;通过使用 GstClock object、buffer timestamps和SEGMENT event来实现&#xff1a; &#xff08;1&#xff09;GstClock&#xff1a;…

Java中如何获取一个字符串是什么类型

Java中如何获取一个字符串是什么类型&#xff1f; 在Java中&#xff0c;您可以使用一些方法来确定一个字符串的类型。下面是一些常用的方法&#xff1a; 使用正则表达式&#xff1a;您可以使用正则表达式来匹配字符串是否符合特定的模式或格式&#xff0c;以确定其类型。例如&…