剑指offer53题 在排序数组中查找数字



问题一:在排序数组中查找数字

问题描述:

统计一个数字在排序数组中出现的次数。

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: 2

示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: 0

解题思路:

解法一:暴力破解,循环遍历
  遍历数组,统计目标值出现的个数,时间复杂度为O(n),n为数组的长度。

解法二:二分查找,两边扩展
  由于数组是有序的,所以我们可以使用二分法找到目标值target,然后向两边扩散查找进行统计(因为数组是有序的,所以target一定是相邻在一起的),直到与target的值不相等为止。

代码实现:

解法一代码:

public int search(int[] nums, int target) {
    
    
	int count = 0;
	for(int i=0; i<nums.length; i++) {
    
    
		if(nums[i]==target)
			count++;
	}
	return count;
}

解法一提交结果:
在这里插入图片描述

解法二代码:

public static int search2(int[] nums, int target) {
    
    
	int count = 0;
	int l = 0; 
	int r = nums.length-1;
	while(l<=r) {
    
    
		int mind = (l+r)/2;
		if(nums[mind]>target)
			r = mind-1;
		else if(nums[mind]<target)
			l = mind+1;
		else {
    
    
			//找到之后向两边扩展,寻找是否还有目标值
			count++;
			int t = mind+1;
			while(t<nums.length && nums[t++]==target)
				count++;
			t = mind-1;
			while(t>=0 && nums[t--]==target)
				count++;
			break;
		}
	}
	return count;
}

提交结果:
在这里插入图片描述



问题二:有序数组中缺失的数字

问题描述:

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

示例 1:

输入: [0,1,3]
输出: 2

示例 2:

输入: [0,1,2,3,4,5,6,7,9]
输出: 8

解题思路:

解法一:利用数组下标判断
  由于数组是从0开始递增的,所以当第一次出现nums[i]与数组下标i不对应时,那么i就是缺少的值。如果整个数组都对应,那么缺少的就是n,即数组的长度。

解法二:二分法,寻找边界值
  用二分法寻找nums[i]与数组下标i开始不对应的边界,即可找出缺少的值。

代码实现:

解法一代码:

public int missingNumber(int[] nums) {
    
    
	for(int i=0; i<nums.length; i++) {
    
    
	 	if(i!=nums[i]) return i;
	}
	//如果数组是有序递增的,那么缺少的是n,即数组的长度
	return nums.length;
} 

解法一提交结果:
在这里插入图片描述

解法二代码:

public int missingNumber(int[] nums) {
    
    
    int i = 0, j = nums.length - 1;
    while(i <= j) {
    
    
        int m = (i + j) / 2;
        if(nums[m] == m) i = m + 1;
        else j = m - 1;
    }
    return i;
}

解法二提交结果:
在这里插入图片描述
总结:问题二的解法二和解法一相差不大,因为解法一只有再最坏的情况下时间复杂度才是O(n)。nums[i]与数组下标i不相等的情况出现得越靠前解法一的效率就越高,甚至超过解法二。并且解法一再循环遍历的过程中不需要进行计算(相加运算)。从代码上看解法一也更简洁。

猜你喜欢

转载自blog.csdn.net/HC199854/article/details/109326758