树型中序迭代器

相信很多小伙伴在面试中都会遇到面试手撕题,然后当时可能会大脑有一些宕机,但在事后却宛若诸葛亮一般奇妙的相出了最优解哈哈哈。没错就是我,面试中只想出了暴力的想法,最优解只有一点点头绪。当面试过后再去想一下确实会文思泉涌。
算法题是这样的:有两棵树,判断他们中序遍历的结果是否一致。
那好家伙,0.1s想出最暴力的方法,直接给他一个中序遍历并存储结果,后面一个边遍历边校验即可。(但是复杂度有点高)
有没有更好的方法?有的兄弟,有的。🤓🤞
那不如我们来给他优雅的做一个中序迭代器,这样每次我们都可以边走边比较,那效率不嘎嘎快吗?当然我们还得考虑说树的节点树不同的问题,那这个好整,如果一个树还能遍历,另外一个树已经无法遍历了,那不就铁定不一样吗!
好的,如下就是我花费大量脑细胞做出来的一个中序迭代器(自己测了一下,确实没问题哈,如果有问题跟我说一声) 总共有两个版本 第二个版本更好

/**
 * ELEGANT
 * TODO 做一个树形遍历器(弥补面试的遗憾)
 */
class TreeNode {
    public int value;
    public TreeNode left;
    public TreeNode right;
    public TreeNode father;
    // flag表示为是否遍历过
    public Boolean flag;

    public TreeNode(int value, TreeNode left, TreeNode right){
        this.value = value;
        this.left = left;
        this.right = right;
        flag = Boolean.FALSE;
    }

    public void setFather(TreeNode father){
        this.father = father;
    }
}

/**
 * 树的遍历器
 */
class Iterator{

    public TreeNode cur;

    public Iterator(TreeNode cur){
        // 落地先找最左边
        this.cur = findLeft(cur);
    }

    /**
     * 一股脑找最左边
     * @param cur
     * @return
     */
    private TreeNode findLeft(TreeNode cur){
        if (cur == null){
            return null;
        }

        while (cur.left != null){
            cur = cur.left;
        }
        return cur;
    }

    public boolean hasNext(){
        return cur != null;
    }

    /**
     * 遍历
     * @return
     */
    public TreeNode next(){
        TreeNode resp = cur;
        // 表示该节点已经访问
        cur.flag = true;

        // 看能不能往右边走
        if (cur.right != null && !cur.right.flag){
            cur = cur.right;
            // 一直找左边
            cur = findLeft(cur);
        }else {
            // 走到这的话只能往上走
            cur = cur.father;
            while (cur != null && cur.flag){
                cur = cur.father;
            }
        }
        return resp;
    }
}
public class TreeIterator {
    public static void main(String[] args) {
        TreeNode root = buildTree();

        Iterator iterator = new Iterator(root);

        while (iterator.hasNext()){
            TreeNode next = iterator.next();
            System.out.println(next.value);
        }
    }

    /**
     * 构建树
     * @return
     */
    private static TreeNode buildTree(){
        TreeNode r6 = new TreeNode(5, null, null);
        TreeNode r5 = new TreeNode(4, null, null);
        TreeNode r4 = new TreeNode(9, null, null);
        TreeNode r3 = new TreeNode(6, r4, null);
        TreeNode r2 = new TreeNode(8,r5,r6);
        TreeNode r1 = new TreeNode(7, null,r3);
        TreeNode root = new TreeNode(10,r1,r2);

        r1.setFather(root);
        r2.setFather(root);
        r3.setFather(r1);
        r5.setFather(r2);
        r6.setFather(r2);
        r4.setFather(r3);
        root.setFather(null);
        return root;
    }

    // TODO 判断两个树的中序遍历是否相同
    // 时间复杂度 O(Min(t1.size,t2.size)) 且运气好的话 直接匹配到当前项不同就直接return
    public static boolean isSame(TreeNode t1,TreeNode t2){
        // 获取他们的迭代器
        Iterator iterator1 = new Iterator(t1);
        Iterator iterator2 = new Iterator(t2);

        while (iterator1.hasNext() && iterator2.hasNext()){
            TreeNode next1 = iterator1.next();
            TreeNode next2 = iterator2.next();

            if (next1.value != next2.value){
                return false;
            }
        }

        return iterator1.hasNext() == iterator2.hasNext();
    }
}

🤔 又有一个更优雅的版本 减少了内存消耗

/**
 * TODO 做一个树形遍历器(弥补面试的遗憾)
 */
class TreeNode {
    public int value;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(int value, TreeNode left, TreeNode right){
        this.value = value;
        this.left = left;
        this.right = right;
    }
}

/**
 * 树的遍历器
 */
class Iterator{

    public Stack<TreeNode> stack = new Stack<>();
    public Iterator(TreeNode cur){
        // 落地先找最左边
        findLeft(cur);
    }

    /**
     * 一股脑找最左边
     * @param cur
     * @return
     */
    private voidfindLeft(TreeNode cur){
        if (cur == null){
            return;
        }

        while (cur.left != null){
            stack.add(cur);
            cur = cur.left;
        }
        stack.add(cur);
    }

    public boolean hasNext(){
        return !stack.isEmpty();
    }

    /**
     * 遍历
     * @return
     */
    public TreeNode next(){
        TreeNode resp = stack.pop();

        // 看能不能往右边走
        if (resp.right != null){
            // 一直找左边
            findLeft(resp.right);
        }
        return resp;
    }
}
public class TreeIterator2 {
        public static void main(String[] args) {
        TreeNode root = buildTree();

        Iterator iterator = new Iterator(root);

        while (iterator.hasNext()){
            TreeNode next = iterator.next();
            System.out.println(next.value);
        }
    }

    /**
     * 构建树
     * @return
     */
    private static TreeNode buildTree(){
        TreeNode r6 = new TreeNode(5, null, null);
        TreeNode r5 = new TreeNode(4, null, null);
        TreeNode r4 = new TreeNode(9, null, null);
        TreeNode r3 = new TreeNode(6, r4, null);
        TreeNode r2 = new TreeNode(8,r5,r6);
        TreeNode r1 = new TreeNode(7, null,r3);
        TreeNode root = new TreeNode(10,r1,r2);
        return root;
    }

    // TODO 判断两个树的中序遍历是否相同
    // 时间复杂度 O(Min(t1.size,t2.size)) 且运气好的话 直接匹配到当前项不同就直接return
    public static boolean isSame(TreeNode t1,TreeNode t2){
        // 获取他们的迭代器
        Iterator iterator1 = new Iterator(t1);
        Iterator iterator2 = new Iterator(t2);

        while (iterator1.hasNext() && iterator2.hasNext()){
            TreeNode next1 = iterator1.next();
            TreeNode next2 = iterator2.next();

            if (next1.value != next2.value){
                return false;
            }
        }

        return iterator1.hasNext() == iterator2.hasNext();
    }
}

posted @ 2025-04-03 15:27  ayu0v0  阅读(12)  评论(0)    收藏  举报