109. 有序链表转换二叉搜索树

171 阅读1分钟

题目介绍

力扣109题:leetcode-cn.com/problems/co…

image.png

方法一

先将链表转为List集合,然后后续操作跟之前的[108. 将有序数组转换为二叉搜索树]类似。代码如下:

class Solution {
    public TreeNode sortedListToBST(ListNode head) {
        if(head == null) {
            return null;
        }
        //先求出链表的长度
        List<Integer> data = getList(head);   
        return resolveToBST(data,0,data.size() - 1);
    }

    /**
     * 递归方法
     */
     public TreeNode resolveToBST(List<Integer> data,int left,int right) {
        if(left > right) {
            return null;
        }
        int mid =  (right + left) / 2;
        TreeNode root = new TreeNode(data.get(mid));   
        root.left = resolveToBST(data , left , mid - 1);
        root.right = resolveToBST(data , mid + 1 , right);
        return root; 
     }

    /**
     * 先求出链表的节点数量
     */
     public List<Integer> getList(ListNode head) {
         List<Integer> data = new ArrayList<>();
         ListNode temp = head;
         while(temp != null) {
            data.add(temp.val);
            temp=temp.next;
         }
         return data;
     }
}

方法二:快慢指针

寻找链表的中间点有个小技巧:

  • 快慢指针起初都指向头结点,分别一次走两步和一步,当快指针走到尾节点时,慢指针正好走到链表的中间。断成两个链表,分而治之。

  • 为了断开,我们需要保存慢指针的前一个节点,因为单向链表的结点没有前驱指针。

image.png

代码如下:

class Solution {
    public TreeNode sortedListToBST(ListNode head) {
      if(head == null)return null;
      if(head.next == null)return new TreeNode(head.val);

      ListNode slow = head, fast = head, pre = head;
      while(fast != null && fast.next != null){
        pre = slow;
        slow = slow.next;
        fast = fast.next.next;
      }
      
      ListNode right = slow.next;
      pre.next = null;
      TreeNode root = new TreeNode(slow.val);
      root.left = sortedListToBST(head);
      root.right = sortedListToBST(right);

      return root;
    }   
}