题目描述
给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树。本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
解法一:分治
/**
* Definition for singly-linked list.
* 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; }
* }
*/
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
public TreeNode sortedListToBST(ListNode head) {
// 用null代替最后一个节点。又是一个小细节
return getTree(head,null);
}
/*
找到单链表中点的方式,比找到长度再遍历时间复杂度要低
*/
public ListNode getmin(ListNode left,ListNode right){
ListNode fast = left;
ListNode slow = left;
while(fast != right && fast.next != right){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
public TreeNode getTree(ListNode left,ListNode right){
if(left == right){
return null;
}
ListNode min = getmin(left,right);
TreeNode node = new TreeNode(min.val);
node.left = getTree(left,min);
node.right = getTree(min.next,right);
return node;
}
}
解法二:分治加中序遍历
较上一个方法,优化了找链表中点的时间。只需要找一次链表的长度,用一个全局变量记录链表当前位置,用中序遍历的方式建树
/**
* Definition for singly-linked list.
* 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; }
* }
*/
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
ListNode globalNode;
public TreeNode sortedListToBST(ListNode head) {
globalNode = head;
int len = getlen(head);
return buildTree(0,len - 1);
}
public int getlen(ListNode head){
int len = 0;
while(head != null){
len++;
head = head.next;
}
return len;
}
public TreeNode buildTree(int left,int right){
if(left > right){
return null;
}
int min = (left + right) / 2;
TreeNode node = new TreeNode();
node.left = buildTree(left,min - 1);
node.val = globalNode.val;
globalNode = globalNode.next;
node.right = buildTree(min + 1, right);
return node;
}
}
解法三:dfs
这里dfs的思路有点像树转数组的思路,就是index2为左节点,index2+1为右子树,但这里这个只相当于一个占位符,结点值是按链表顺序来的,index并不代表树结点与链表结点的对应关系
/**
* Definition for singly-linked list.
* 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; }
* }
*/
/**
* Definition for a binary tree node.
* 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;
* }
* }
*/
class Solution {
ListNode globalNode;
public TreeNode sortedListToBST(ListNode head) {
globalNode = head;
int len = getlen(head);
return dfs(1,len);
}
public int getlen(ListNode head){
int len = 0;
while(head != null){
len++;
head = head.next;
}
return len;
}
public TreeNode dfs(int index,int len){
if(index > len){
return null;
}
TreeNode node = new TreeNode();
node.left = dfs(index * 2,len);
node.val = globalNode.val;
globalNode = globalNode.next;
node.right = dfs(index * 2 + 1,len);
return node;
}
}