码迷,mamicode.com
首页 > 其他好文 > 详细

Convert Sorted List to Binary Search Tree

时间:2015-03-03 14:57:08      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:

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

Convert Sorted List to Binary Search Tree

标签:

原文地址:http://www.cnblogs.com/NickyYe/p/4310355.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!