题目描述:
Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
读题:
1.列表是递增排序的
2.高度平衡的二叉树
知识储备:
BST(二叉搜索树)
1. 所有非叶子结点至多拥有两个儿子(left和right)
2. 所有结点存储一个关键字;
3. 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树
解题思路:
1.将数组的中间元素作为根节点,比他小的值放在left,比他大的值放在right,分成两部分后,将新的子节点视为根节点,依次递归。
遇到的问题:
当用以下代码提交时,出现了超时的问题,在执行一个数据量很大的测试用例,时间为9ms。
if (begin <= end){
///执行语句
} else {
return null;
}
当修改了return null的位置后
if (begin <= end){
///执行语句
}
return null;
执行时间变为7ms。
一点小小的变化却在时间复杂度上造成了不小的影响。
根据查到的资料:
如果基本操作就是比较,那么一条if 语句的计数为1
如果比较不是基本操作,相对基本操作,比较的时间可以忽略,那么只需要对基本操作计数
if 语句中,不执行基本操作的不计数,执行的计数。
虽然大部分人在计算时间复杂度时,并没有留意这一点点时间,然而事实表明还是有差别的,那这个差别到底在哪呢?
我认为这要从汇编语言的原理上讲,
在多分支结构中,if/else采用cmp xxx,1 jnz xxx、cmp xxx,2 jnz xxx、cmp xxx,3 jnz xxx…的方式实现的。
因此第1段代码在执行if语句时,首先执行判断,若不符合条件,则跳转到下一条else的位置继续执行return null语句。
与第2段代码相比,执行判断后,若不符合条件,则结束if语句,再顺序执行return null语句。
因此二者的区别应是在于第1段代码多了一个跳转指令,所以多了少许的执行时间。
提交代码:
/**
* 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) {
HashMap<Integer,TreeNode> map = new HashMap<Integer,TreeNode>();
int count = 0;
ListNode i = head;
while (i != null) {
map.put(count, new TreeNode(i.val));
i = i.next;
count++;
}
return buildT(map,0,count-1);
}
public TreeNode buildT(HashMap<Integer,TreeNode> map, int begin, int end) {
if (begin <= end){
int mid = (begin + end) / 2;
TreeNode t = map.get(mid);
t.left = buildT(map,begin,mid-1);
t.right = buildT(map,mid+1,end);
return t;
}
return null;
}
}