Convert Sorted List to Binary Search Tree

https://oj.leetcode.com/problems/convert-sorted-list-to-binary-search-tree/

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

解题思路:

首先,这题与 Convert Sorted Array to Binary Search Tree 很类似,可以用递归的方法来解。难度在于,List和Array的不同,不能直接获取节点的下标,以及计算这段list的中点,也不能比较他们start和end下标的大小,以便在start>end的时候合理退出。所以需要取得midNode,同时还要获得midNode的前一个节点。每次递归进入方法的时候,需要对于只有一个节点,和只有两个节点的情况,分别处理,否则就会出错。

/**

 * Definition for singly-linked list.

 * public class ListNode {

 *     int val;

 *     ListNode next;

 *     ListNode(int x) { val = x; next = null; }

 * }

 */

/**

 * Definition for binary tree

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

public class Solution {

    public TreeNode sortedListToBST(ListNode head) {

        if(head == null){

            return null;

        }

        

        ListNode end = head;

        while(end.next != null){

            end = end.next;

        }

        return sortedListToBSTHelper(head, end);

    }

    

    public TreeNode sortedListToBSTHelper(ListNode head, ListNode end){

        //nodeNum == 0,只有一个节点的情况

        if(head == end){

            return new TreeNode(head.val);

        }

        

        int nodeNum = 0;

        ListNode tempNode = head;

        while(tempNode != end){

            tempNode = tempNode.next;

            nodeNum++;

        }

        

        //nodeNum == 1,只有两个节点的情况

        if(nodeNum == 1){

            TreeNode root = new TreeNode(head.val);

            root.right = sortedListToBSTHelper(head.next, end);

            return root;

        }

        

        //nodeNum > 2的情况

        TreeNode preMidNode = head;

        for(int i = 0; i < nodeNum / 2 - 1; i++){

            preMidNode = preMidNode.next;

        }

        

        ListNode midNode = preMidNode.next;

        

        TreeNode root = new TreeNode(midNode.val);

        root.left = sortedListToBSTHelper(head, preMidNode);

        root.right = sortedListToBSTHelper(midNode.next, end);

        return root;

    }

}

后来在网上看到一个左闭右开的方法,类似于二分查找,在 Find Minimum in Rotated Sorted Array 和 Search Insert Position 问题里提到过这个问题。那么右边界只要取midNode就可以了,不必取得他的钱一个节点。同时,调用递归方法的时候,也必须为sortedListToBSTHelper(head, null);而不能是sortedListToBSTHelper(head, end)。

还要注意,计算列表节点数量的方法也发生了变化,因为end已经是一个开放的区间。

这样避免了preMidNode节点和start的判断问题,代码简单了。

/**

 * Definition for singly-linked list.

 * public class ListNode {

 *     int val;

 *     ListNode next;

 *     ListNode(int x) { val = x; next = null; }

 * }

 */

/**

 * Definition for binary tree

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

public class Solution {

    public TreeNode sortedListToBST(ListNode head) {

        if(head == null){

            return null;

        }

        

        return sortedListToBSTHelper(head, null);

    }

    

    public TreeNode sortedListToBSTHelper(ListNode head, ListNode end){

        if(head == end){

            return null;

        }

        //nodeNum == 0,只有一个节点的情况

        if(head.next == end){

            return new TreeNode(head.val);

        }

        

        int nodeNum = 0;

        ListNode tempNode = head;

        while(tempNode.next != end){

            tempNode = tempNode.next;

            nodeNum++;

        }

        

        //nodeNum == 1,只有两个节点的情况,可以省略

        //左闭右开的方法下面已经涵盖

        // if(nodeNum == 1){

        //     TreeNode root = new TreeNode(head.val);

        //     root.right = sortedListToBSTHelper(head.next, end);

        //     return root;

        // }

        

        //nodeNum > 2的情况

        ListNode midNode = head;

        for(int i = 0; i < nodeNum / 2; i++){

            midNode = midNode.next;

        }

        

        TreeNode root = new TreeNode(midNode.val);

        root.left = sortedListToBSTHelper(head, midNode);

        root.right = sortedListToBSTHelper(midNode.next, end);

        return root;

    }

}

 把取得中间节点作为一个方法拿出来,refactor代码。

/**

 * Definition for singly-linked list.

 * public class ListNode {

 *     int val;

 *     ListNode next;

 *     ListNode(int x) { val = x; next = null; }

 * }

 */

/**

 * Definition for binary tree

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

public class Solution {

    public TreeNode sortedListToBST(ListNode head) {

        if(head == null){

            return null;

        }

        

        return sortedListToBSTHelper(head, null);

    }

    

    public TreeNode sortedListToBSTHelper(ListNode head, ListNode end){

        if(head == end){

            return null;

        }

        //nodeNum == 0,只有一个节点的情况

        if(head.next == end){

            return new TreeNode(head.val);

        }

        

        ListNode midNode = getMidNode(head, end);

        TreeNode root = new TreeNode(midNode.val);

        root.left = sortedListToBSTHelper(head, midNode);

        root.right = sortedListToBSTHelper(midNode.next, end);

        return root;

    }

    

    public ListNode getMidNode(ListNode head, ListNode end){

        int nodeNum = 0;

        ListNode tempNode = head;

        while(tempNode.next != end){

            tempNode = tempNode.next;

            nodeNum++;

        }

    

        ListNode midNode = head;

        for(int i = 0; i < nodeNum / 2; i++){

            midNode = midNode.next;

        }

        return midNode;

    }

}

 利用快慢指针的方法,找一个链表中点,可以写成下面的方法。

public ListNode getMidNode(ListNode head, ListNode end){

        ListNode quickNode = head;

        ListNode slowNode = head;

        while(quickNode != end && quickNode.next != end){

            quickNode = quickNode.next.next;

            slowNode = slowNode.next;

        }

        return slowNode;

    }

}

或者下面的形式,更容易理解一些。

public ListNode getMidNode(ListNode head, ListNode end){

        ListNode quickNode = head;

        ListNode slowNode = head;

        while(quickNode.next != end){

            quickNode = quickNode.next;

            if(quickNode.next != end){

                quickNode = quickNode.next;

                slowNode = slowNode.next;

            }

        }

        return slowNode;

    }

}

 同样下面的方法也是对的,想想为什么循环终止的条件,quickNode != end 和 quickNode.next != end都可以?

    public ListNode getMidNode(ListNode head, ListNode end){

        ListNode quickNode = head;

        ListNode slowNode = head;

        while(quickNode != end){

            quickNode = quickNode.next;

            if(quickNode != end){

                quickNode = quickNode.next;

                slowNode = slowNode.next;

            }

        }

        return slowNode;

    }

因为1-2-3-4这样的数列,下面两种BST都是平衡的。

        3                                         2

      /   \                                     /    \

    2      4                                 1       3

 /                                                       \

1                                                         4

update 2015/05/16:

二刷

/**

 * Definition for singly-linked list.

 * public class ListNode {

 *     int val;

 *     ListNode next;

 *     ListNode(int x) { val = x; }

 * }

 */

/**

 * Definition for a binary tree node.

 * public class TreeNode {

 *     int val;

 *     TreeNode left;

 *     TreeNode right;

 *     TreeNode(int x) { val = x; }

 * }

 */

public class Solution {

    public TreeNode sortedListToBST(ListNode head) {

        return sortedListToBSTHelper(head, null);

    }

    

    public TreeNode sortedListToBSTHelper(ListNode head, ListNode tail) {

        if(head == tail) {

            return null;

        }

        ListNode midNode = getMidNode(head, tail);

        TreeNode root = new TreeNode(midNode.val);

        root.left = sortedListToBSTHelper(head, midNode);

        root.right = sortedListToBSTHelper(midNode.next, tail);

        return root;

    }

    

    public ListNode getMidNode(ListNode head, ListNode tail) {

        ListNode fast = head;

        ListNode slow = head;

        while(fast != tail) {

            fast = fast.next;

            if(fast != tail) {

                fast = fast.next;

                slow = slow.next;

            }

        }

        return slow;

    }

}

 

你可能感兴趣的:(Binary search)