leetcode
leetcode 2351 ~ 2400
从 Rope 树中提取第 K 个字符

从 Rope 树中提取第 K 个字符

难度:

标签:

题目描述

代码结果

运行时间: 46 ms, 内存: 26.7 MB


/*
题目思路:
使用Java Stream处理Rope树需要先将Rope树转换为字符串,然后使用Stream进行操作。
可以定义一个辅助函数,将Rope树中的所有字符拼接成一个完整的字符串,之后利用Stream获取第K个字符。
*/

import java.util.stream.IntStream;

// Rope树节点的定义
class RopeNode {
    String data;
    int weight;
    RopeNode left, right;
    
    RopeNode(String data) {
        this.data = data;
        this.weight = data.length();
        this.left = this.right = null;
    }
    
    RopeNode(int weight, RopeNode left, RopeNode right) {
        this.weight = weight;
        this.left = left;
        this.right = right;
        this.data = null;
    }
}

// Rope树类的定义
class RopeTree {
    RopeNode root;
    
    public RopeTree(RopeNode root) {
        this.root = root;
    }
    
    public char getKthCharacter(int k) {
        StringBuilder sb = new StringBuilder();
        buildString(root, sb);
        return IntStream.range(0, sb.length())
                        .mapToObj(sb::charAt)
                        .skip(k - 1)
                        .findFirst()
                        .orElseThrow(() -> new IllegalArgumentException("K exceeds the total number of characters in the Rope tree."));
    }
    
    private void buildString(RopeNode node, StringBuilder sb) {
        if (node == null) return;
        if (node.data != null) sb.append(node.data);
        buildString(node.left, sb);
        buildString(node.right, sb);
    }
}

解释

方法:

题解的思路是使用深度优先搜索(DFS)来遍历Rope树,并在遍历过程中逐步构建字符串。Rope树是一种二叉树,其中每个节点包含一个长度值、一个字符串值和可能的左右子节点。在DFS过程中,首先检查当前节点是否为空,如果为空则返回长度为0和空字符串。接着,如果当前节点的长度为0(意味着它可能是一个叶节点),则直接返回该节点的值。对于非叶节点,先递归处理左子树。如果左子树的长度大于或等于k,说明第k个字符位于左子树中,因此可以返回左子树的结果。如果不是,再递归处理右子树,并将左右子树的结果合并返回。最终,从合并后的结果中取出第k个字符。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在定义RopeTreeNode时,`len`属性具体代表什么含义?是当前节点字符串的长度,还是包括所有子节点的总长度?
`len`属性在RopeTreeNode中代表的是该节点以及其所有子节点组成的字符串的总长度。这样设计使得我们可以快速获取子树中字符串的长度,便于在进行诸如查找子字符串位置等操作时提供效率。
🦆
题解中对于节点长度为0的处理逻辑是直接返回节点值,这是否意味着长度为0的节点总是叶节点?如果非叶节点的长度属性也为0,这会如何影响算法的结果?
在题解中,如果一个节点的长度为0被视为叶节点,并直接返回其值,这实际上是基于一个假设,即叶节点不会有子节点,其长度自然是0。如果一个非叶节点的长度错误地设置为0,这将导致算法错误地处理这些节点,因为它会忽略其子节点的存在和内容,从而影响最终结果。正确的做法是确保非叶节点的长度应该是其所有子节点字符串长度的总和。
🦆
在递归处理左子树后,如果`k`大于`left_len`,题解选择继续递归右子树并合并结果。如何确保这种处理不会导致重复计算或遗漏部分字符?
题解中通过首先递归左子树,并检查`k`是否小于或等于`left_len`来确定是否找到所需字符。如果不是,即`k`大于`left_len`,则减去`left_len`并对右子树进行递归,这样可以确保不会遗漏或重复计算字符。具体来说,右子树的递归应该是基于新的索引`k - left_len`,这样可以直接定位到右子树中正确的字符位置。这种方法确保了处理的精确性和效率。

相关问题