LeetCode每日一题(20200818)

原题地址

思考过程

需要将链表转成高度平衡的二叉搜索树,找到链表的中间节点,作为二叉树的根,前部分作为左节点,后部分作为右节点。然后递归,直到链表长度为1或者为空时,可以返回确定的二叉树
可以使用快慢双指针,找到链表的中间节点,后部分链表和前部分链表的长度
前部分链表可以从head开始构建链表(已知长度),然后再翻转

 

代码实现:

链表翻转:(LeetCode有原题

从链表头head开始构建链表

代码如下:

private ListNode reverse(ListNode head) {
        ListNode l1 = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode tem = new ListNode(curr.val);
            tem.next = l1;
            l1 = tem;
            curr = curr.next;
        }
        return l1;
    }

链表转二叉树,代码如下:

public TreeNode sortedListToBST(ListNode head) {
        if (head == null) {
            return null;
        }
        if (head.next == null) {
            return new TreeNode(head.val);
        }
        ListNode tem = head;
        ListNode right = head;
        int len = 0, leftLen, rightPosition = 0;
        while (tem != null) {
            tem = tem.next;
            len++;
            if (tem != null) {
                tem = tem.next;
                len++;
            }
            right = right.next;
            rightPosition++;
        }
        leftLen = len - 1 - (len-rightPosition);

        tem = head;
        int p = 0;
        int value = -1;
        ListNode left = null;
        while (tem != null) {

            if (p < leftLen) {
                ListNode l = new ListNode(tem.val);
                l.next = left;
                left = l;
            }

            if (p == rightPosition - 1) {
                value = tem.val;
            }
            tem = tem.next;
            p++;
        }

        left = reverse(left);
        return new TreeNode(value, sortedListToBST(left), sortedListToBST(right));

    }

执行结果:

性能明显不够好。

 

算法复杂度分析

时间复杂度:O(n²),其中 n是链表的节点个数。

空间复杂度:O(n),其中 n 是链表的节点个数。

 

查看官方提供的解法

分治思想和我个人解题思路差不多,找中间节点,也同样使用的是快慢双指针思路,但是在代码实现上,效率更好,更简洁。

代码如下:

 public TreeNode sortedListToBST(ListNode head) {
        return buildTree(head, null);
    }

    public TreeNode buildTree(ListNode left, ListNode right) {
        if (left == right) {
            return null;
        }
        ListNode mid = getMedian(left, right);
        TreeNode root = new TreeNode(mid.val);
        root.left = buildTree(left, mid);
        root.right = buildTree(mid.next, right);
        return root;
    }

    public ListNode getMedian(ListNode left, ListNode right) {
        ListNode fast = left;
        ListNode slow = left;
        while (fast != right && fast.next != right) {
            fast = fast.next;
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }

其他解答:

 public TreeNode sortedListToBST3(ListNode head) {
        //边界条件的判断
        if (head == null)
            return null;
        if (head.next == null)
            return new TreeNode(head.val);
        //这里通过快慢指针找到链表的中间结点slow,pre就是中间
        //结点slow的前一个结点
        ListNode slow = head, fast = head, pre = null;
        while (fast != null && fast.next != null) {
            pre = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        //链表断开为两部分,一部分是node的左子节点,一部分是node
        //的右子节点
        pre.next = null;
        //node就是当前节点
        TreeNode node = new TreeNode(slow.val);
        //从head节点到pre节点是node左子树的节点
        node.left = sortedListToBST3(head);
        //从slow.next到链表的末尾是node的右子树的结点
        node.right = sortedListToBST3(slow.next);
        return node;
    }

思路是一致的,找前链表的方式比较高效,代码比较简洁,值得借鉴。

 

总结:

读完题后,马上想到解题思路,但是在代码实现时卡住了(如何找到前部分链表),对链表的操作还是不太熟练。另外,算法复杂度分析时,也卡住了。所以在链表操作,代码实现,算法复杂度分析上,还有待提高

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值