小记——一次刷题的错误归纳及总结(有序链表转换二叉搜索树)

给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。

示例:

给定的有序链表: [-10, -3, 0, 5, 9],
一个可能的答案是:[0, -3, 9, -10, null, 5], 它可以表示下面这个高度平衡二叉搜索树:

   0
 /   \
-3    9
/     /
-10   5

题目来源于力扣,题目为109. 有序链表转换二叉搜索树。
这里直接po上我的错误代码以及费劲力气找到的原因,吸取教训。

public class ListNode {
    int val;
    ListNode next;

    ListNode() {
    }

    ListNode(int val) {
        this.val = val;
    }

    ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}
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;
    }
}
package Day4_有序链表转换二叉搜索树;

public class Solution {public TreeNode sortedListToBST(ListNode head) {
    if(head == null) return null;
    TreeNode originalNode = new TreeNode(head.val);
    TreeNode treeNode = null;
    head = head.next;
    // 将所有节点初步构成一棵有序二叉树
    while(head != null){
        treeNode = new TreeNode(head.val);
        System.out.println("即将放入值:" + head.val);
        putTreeNode(originalNode, treeNode);
        head = head.next;
    }
    getBalancedTree(originalNode);
    return originalNode;
}

    // 将树设置为平衡二叉树
    public void getBalancedTree(TreeNode originalNode){
        if(originalNode == null) return;
        getBalancedTree(originalNode.left);
        getBalancedTree(originalNode.right);
        int flag = isBalanced(originalNode);
        if(flag == 0){
            return;
        }else if(flag == 1){
            originalNode.right.left = originalNode;
            originalNode = originalNode.right;
        }else{
            originalNode.left.right = originalNode;
            originalNode = originalNode.left;
        }
    }

    // 判断以传入节点开始的树是否为一棵二叉树
    public int isBalanced(TreeNode originalNode){
        if(originalNode == null){
            return 0;
        }else{
            int leftDepth = getTreeDepth(originalNode.left, 0);
            int rightDepth = getTreeDepth(originalNode.right, 0);
            int result = leftDepth - rightDepth;
            if(result * result <= 1){
                return 0;
            }else{
                if(result < 0){ // 右边比左边长,需进行左旋
                    return 1;
                }else{  // 左边比右边长,需进行右旋
                    return -1;
                }
            }
        }
    }

    // 传入根结点,获取根结点开始的树的最大深度(即左右子树中较深的那个)
    public int getTreeDepth(TreeNode originalNode, int depth){
        if(originalNode == null){
            return depth + 0;

        }else{
            System.out.println(originalNode.val);
            int leftDepth = getTreeDepth(originalNode.left, depth + 1);
            int rightDepth = getTreeDepth(originalNode.right, depth + 1);
            return leftDepth > rightDepth ? leftDepth : rightDepth;
        }
    }

    // 将节点按照"左子节点均小于父节点,右子节点均大于等于父节点"的方式放入二叉树
    public void putTreeNode(TreeNode originalNode, TreeNode treeNode){
        if(treeNode.val >= originalNode.val){
            if(originalNode.right != null){
                putTreeNode(originalNode.right, treeNode);
            }else {
                System.out.println(originalNode.val + "的右边放" + treeNode.val);
                originalNode.right = treeNode;
            }
        }else{
            if(originalNode.left != null){
                putTreeNode(originalNode.left, treeNode);
            }else{
                System.out.println(originalNode.val + "的左边放" + treeNode.val);
                originalNode.left = treeNode;
            }
        }
    }
}
public class doMain {
    public static void main(String[] args) {
        ListNode headNode = new ListNode(-10);
        ListNode nextNode = null, listNode = null;
        nextNode = headNode;
        int[] a = {-3,0,5,9};
        for(int i = 0; i < a.length; i++){
            listNode = new ListNode(a[i]);
            nextNode.next = listNode;
            nextNode = nextNode.next;
        }
        Solution solution = new Solution();
        TreeNode treeNode = solution.sortedListToBST(headNode);
    }
}

报错提示:栈溢出,在执行getTreeDepth时陷入死循环
在这里插入图片描述
报错原因:

  • 在getBalancedTree方法中,当找到第一个非平衡点时,进行相应处理的代码有问题,代码如下。
		if(flag == 0){
            return;
        }else if(flag == 1){
            originalNode.right.left = originalNode;
            originalNode = originalNode.right;
        }else{
            originalNode.left.right = originalNode;
            originalNode = originalNode.left;
        }
     * 简单说就是:没有进行正确的左旋和右旋的时候
     * 比如有 -3 0 5 9 这几个节点构成的二叉树(左小右大)
     * 此时第一个非平衡点是 0,需要进行左旋
     * 你的原左旋处理是:仅仅将 5 的左节点指向0。
     * 但是你没有考虑到0的右节点还是指向 5
     * 而且 -3 这个节点的右节点 要指向 5, 需要设置父节点,然后0的时候父节点是 -3,这样来操作 -3 的子节点
     * originalNode = originalNode.right;这一句代码实际上没有任何作用
     * 因为originalNode它并不是树上的那个点,它仅仅保存了指向某节点的地址而已。
     * 对它进行赋值,那就是让它指向一个新的地方,不会对原来指向的节点有影响。

个人做题思路:

  1. 个人的思路是首先直接构建一棵二叉搜索树(左大右小的原则),
  2. 然后再按后序遍历,找到第一个非平衡点,进行平衡处理。
  3. 处理方式如上,但其实本题有一个条件——有序链表我没有用上,实际上可以通过有序链表来依次找出中位数构建二叉树。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值