二叉树查找元素的位置(含有重复元素,且元素个数是不确定的)
代码解析
package 在排序数组中查找第一个元素与最后一个元素;
public class Solution {
public int[] searchRange(int[] nums, int target) {
int[] result =new int[2];
result[0] = findFirstLeft2(nums,target);
result[1] = findFirstRight2(nums,target);
return result;
}
/*
* 查找第一个与最后一个元素,说明排序数组是含有重复元素的(原来的二叉树是不含相同元素的)
* 所以这里要做一些小的调整
* */
//正常不包含重复元素时利用二分查找法查找元素
public static int findFirstLeft(int[] nums, int target){
int left = 0;
int right = nums.length-1;
while (left <= right){
int mid = left+(right-left+1)/2;
//比较目标值和中间值的大小;
if(nums[mid] > target){
//说明目标值在mid的左边,缩小范围
right = mid-1;
}else if(nums[mid] < target){
left = mid+1;
}else {
return mid;
}
}
return -1;
}
//包含相同元素,则要判断该元素是首元素还是末元素。
public static int findFirstLeft2(int[] nums , int target){
int left = 0;
int right = nums.length-1;
while (left <= right){
int mid = left+(right-left+1)/2;
//比较目标值和中间值的大小;
if(nums[mid] > target){
//说明目标值在mid的左边,缩小范围
right = mid-1;
}else if(nums[mid] < target){
left = mid+1;
}else {
//因为该数组是按照升序排序的,所以只要判断该元素
//前一个元素是否相同,就知道该元素是第一个还是第二个
if(mid == 0 || nums[mid] != nums[mid-1]){//mid == 0是防止mid-1超出数组范围。
//说明mid就是第一个元素
return mid;
}else {
//说明该元素前面还有相同的元素,但是具体有几个,我们不秦楚
//所以我们不能直接返回前一个元素的位置,而是缩小范围,继续找第一个元素。
right = mid-1;
}
}
}
return -1;
}
//查找最后一个元素的位置
public static int findFirstRight2(int[] nums , int target){
int left = 0;
int right = nums.length-1;
while (left <= right){
int mid = left+(right-left+1)/2;
//比较目标值和中间值的大小;
if(nums[mid] > target){
//说明目标值在mid的左边,缩小范围
right = mid-1;
}else if(nums[mid] < target){
left = mid+1;
}else {
//因为该数组是按照升序排序的,所以只要判断该元素
//前一个元素是否相同,就知道该元素是第一个还是第二个
if(mid == nums.length-1 || nums[mid] != nums[mid+1]){//如果mid为最后一个元素,就不存在下一个元素了
//说明mid就是第一个元素
return mid;
}else {
//说明该元素前面还有相同的元素,但是具体有几个,我们不秦楚
//所以我们不能直接返回前一个元素的位置,而是缩小范围,继续找第一个元素。
left = mid+1;
}
}
}
return -1;
}
}
代码解读
相比于传统的二叉树查找,多了一步判断元素是第一元素还是最后元素的操作。代码中都有解析。
复杂度分析
时间复杂度:O(logn)
空间复杂度:O(1)