LeetCode刷题笔记第35题
题目描述:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
解题思路:
最直接的想法就是使用二分查找,如果有序数组中含有与target值相等的元素,直接返回对应的索引值;如果没有则在查找完毕之后,返回对应的左游标值。还有一种解法是直接遍历有序数组,遍历进行的条件是数组当前访问值小于target值同时遍历游标小于数组长度,遍历结束后,对应的遍历游标值就是应该要返回的值。
第一种解法:二分查找
时间复杂度为:O(logn)
我在评论中看到关于计算mid值的争议,有人说直接mid = (left + right) / 2是不安全的,可能会溢出,所以一种比较安全的写法是 mid = left + (right - left) / 2; 就好比是超过10就会发生溢出,现在有两个值,一个为6,一个为8,如果直接计算,则6+8=14>10,会发生溢出,但是通过mid = left + (right - left) / 2公式进行计算 mid = 6 + (8-6)/2,就避免了这个问题,挺有道理,所以借鉴了。
public int searchInsert(int[] nums, int target) { if (nums.length == 0 || (target < nums[0])) return 0; if (target > nums[nums.length-1]) return nums.length; if (nums.length == 1){ if (target>nums[0]) return 1; else return 0; } int left = 0; int right = nums.length - 1; int mid = (left + right) / 2; while (left <= right){ if (nums[mid] == target) return mid; else if (nums[mid] > target){ right = mid - 1; }else { left = mid + 1; } mid = (right + left) / 2; } return mid + 1; }
第一种解法续:对二分查找的改进,减少循环次数
这是我在题解的评论中看到有人提供的解法,思路可以借鉴,虽然运行速度并没有我的快,哈哈哈哈
public int searchInsert3(int[] nums,int target){ int lo=0,hi=nums.length; while(lo<hi-1){ int mid=(lo+hi)>>1; if(target<nums[mid]) hi=mid; else lo=mid; } return target<=nums[lo]? lo:++lo; }
第二种解法:暴力遍历
超级简短,时间复杂度为O(n)
public int searchInsert2(int[] nums, int target) { int i; for(i=0;i<nums.length&&nums[i]<target;i++); return i; }