二叉搜索树定义就是每个节点的左子节点值比它小,右子节点值比他大,也就是说它的中序序列是按顺序排列的。
它的最大特点是可以比较快地插入和删除节点而保持排序,由于这个特点就可以用它存储一些需要多次插入或删除元素并保持顺序的集合。
显然在二叉搜索树中查找一个元素是很容易的,插入元素也一样,而删除元素要相对难一些。
删除二叉搜索树中的节点
首先当然是搜索这个结点,不妨假设这个结点就是根节点。
假如此时根节点的任一子节点为空,只要不空的子节点作为新的根节点就行了。
假如两子树都不为空,新的根节点可以来自任意一边。不妨令左节点为新的根节点。
此时,假如原左节点没有右子树,删除就已经完成了,因为它的左子树必然小于新的跟和右子树。
假如原左节点有右子树,那么需要将它的根节点(它的子树还连着)重新插入整个树中。
public class Solution {
public TreeNode DeleteNode(TreeNode root, int key) {
if(root==null)
return null;
if(root.val==key)
return delete(root);
else if(key<root.val)
root.left=DeleteNode(root.left,key);
else
root.right=DeleteNode(root.right,key);
return root;
}
public TreeNode delete(TreeNode root)
{
if(root==null||(root.left==null&&root.right==null))
return null;
if(root.left!=null&&root.right==null)
return root.left;
if(root.left==null&&root.right!=null)
return root.right;
TreeNode temp=new TreeNode();
temp=root.left;
if(temp.right==null)
temp.right=root.right;
else
temp.right=InsertIntoBST(root.right,temp.right);
return temp;
}
public TreeNode InsertIntoBST(TreeNode root, TreeNode t) {
if(root==null)
return t;
if(t.val<root.val)
root.left=InsertIntoBST(root.left,t);
else if(t.val>root.val)
root.right=InsertIntoBST(root.right,t);
return root;
}
}
C#中性质比较接近二叉搜索树的类是SortedList(或者SortedList<TKey,TValue> 类)
在SortedList添加和删除元素时,它会根据key值,自动进行升序排序
注意,它既不能通过sortedlist[key]这种方法访问,也不能通过sortedlist[i],但是利用上图中的方法可以用索引和键值访问。
存在重复元素 III
给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] – nums[j]) <= t ,同时又满足 abs(i – j) <= k 。如果存在则返回 true,不存在返回 false。
这道题如果用双循环显然是会超时的。可以优化的地方主要在第二重循环中,其中有两个,第一是在第二重循环中,前后两次循环是有k-1个元素被重复遍历,如何在前一次中就把这些元素的信息利用起来;第二,在第二重循环中做的工作时搜索是否有符合范围的元素,乱序序列中必须完全遍历,而在顺序遍历中就可以使用二分查找,提高效率。
综上,可以将每次的k-1个元素储存在SortedList中,然后二分法查找元素,下一次循环则删除头一个元素插入下一个元素。
public class Solution {
public bool ContainsNearbyAlmostDuplicate(int[] nums, int k, int t) {
if(k==0||nums.Length<2)
return false;
SortedList list=new SortedList();
list.Add(nums[0],0);
for(int i=1;i<k;i++)
{
if(search(list,0,list.Count-1,nums[i],t))
return true;
list.Add(nums[i],i);
}
for(int i=k;i<nums.Length;i++)
{
if(search(list,0,list.Count-1,nums[i],t))
return true;
list.Remove(nums[i-k]);
list.Add(nums[i],i);
}
return false;
}
public bool search(SortedList list,int start,int end,int next,int t)
{
if(start>end)
return false;
if(inRange((int)list.GetKey((end+start)/2),t,next))
return true;
if(next>(int)list.GetKey((end+start)/2))
return search(list,(end+start)/2+1,end,next,t);
else
return search(list,start,(end+start)/2-1,next,t);
}
public bool inRange(int range,int t,int num)
{
if((long)range-t<=num&&num<=(long)range+t)
return true;
return false;
}
}
将有序数组转换为二叉搜索树
给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
高度平衡二叉树,本质就是一个顺序序列的二分查找过程
public class Solution {
public TreeNode SortedArrayToBST(int[] nums) {
return erfen(nums,0,nums.Length-1);
}
public TreeNode erfen(int[] nums,int start,int end)
{
if(start>end)
return null;
TreeNode temp=new TreeNode();
temp.val=nums[(start+end)/2];
temp.left=erfen(nums,start,(start+end)/2-1);
temp.right=erfen(nums,(start+end)/2+1,end);
return temp;
}
}