【Search Insert Position】
https://leetcode.com/problems/search-insert-position/description/
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
You may assume no duplicates in the array.
Here are few examples.
[1,3,5,6]
, 5 → 2
[1,3,5,6]
, 2 → 1
[1,3,5,6]
, 7 → 4
[1,3,5,6]
, 0 → 0
* @function 给定一个有序数组和目标元素,如果目标元素在有序数组中,则返回其位置;如果不在,则返回插入位置
*/
public class Search_Insert_Position {
public static void main(String[] args) {
int[] nums={1,3};
System.out.println(searchInsert(nums,0));
}
public static int searchInsert(int[] nums, int target) {
if(nums==null||nums.length==0)
return -1;
int l=0;
int r=nums.length-1;
while(l<=r){ //必须要这样等号,不然测试用例[1],2输出结果是错误的
int mid=(l+r)/2;
if(nums[mid]==target)
return mid;
if(nums[mid]<target)
l=mid+1;
else
r=mid-1;
}
return l;
}
}
变式一:【Search for a Range】
https://leetcode.com/problems/search-for-a-range/description/
Given an array of integers sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1]
.
For example,
Given [5, 7, 7, 8, 8, 10]
and target value 8,
return [3, 4]
.
* @function 返回目标函数在有序数组中出现的起始位置和结束位置
*/
public class Search_for_a_Range {
public static void main(String[] args) {
int[] array={1,2,3,3,3,3,4,5};
int k=3;
int[] res=searchRange_first(array,k);
System.out.print(res[0]+" "+res[1]);
}
public static int[] searchRange_first(int[] nums, int target) {
int[] res=new int[2];
res[0]=-1;
res[1]=-1;
if(nums==null||nums.length==0)
return res;
res[0]=GetFirstK(nums , target, 0, nums.length-1);
res[1]=GetLastK(nums , target, 0, nums.length-1);
return res;
}
public static int GetFirstK(int [] array , int k, int start, int end) {
while(start<=end){
int mid=(start+end)/2;
if(array[mid]<k){
start=mid+1;
}
else if(array[mid]>k){
end=mid-1;
}
else{
if(mid-1>=0 && array[mid-1]==k){ //中间位置的前一个数也为k的话,则仍在前半部分找第一个k
end=mid-1;
}
else{
return mid;
}
}
}
return -1;
}
public static int GetLastK(int [] array , int k, int start, int end) {
while(start<=end){
int mid=(start+end)/2;
if(array[mid]<k){
start=mid+1;
}
else if(array[mid]>k){
end=mid-1;
}
else{
if(mid+1<array.length && array[mid+1]==k){ //中间位置的后一个数也为k的话,则仍在后半部分找最后一个k
start=mid+1;
}
else{
return mid;
}
}
}
return -1;
}
}
变式二:剑指offer 面试题38【数字在排序数组中出现的次数】
思路:就是变式一的思路,变式一求的是范围,这个求的是个数,范围知道了,个数也就知道了
* @function 数字在排序数组中出现的次数:循环写法,下一个版本是递归写法
*/
public class GetNumberOfK {
public static void main(String[] args) {
int[] array={1,2,3,3,3,3,4,5};
int k=3;
System.out.println(getNumberOfK(array,k));
}
public static int getNumberOfK(int [] array , int k) {
if(array==null||array.length==0)
return 0;
int firstK=GetFirstK(array , k, 0, array.length-1);
int lastK=GetLastK(array , k, 0, array.length-1);
if(firstK !=-1 && lastK !=-1){ //这里必须限定,不然该数不存在的情况下也会输出1
return lastK-firstK+1;
}
return 0;
}
public static int GetFirstK(int [] array , int k, int start, int end) {
while(start<=end){
int mid=(start+end)/2;
if(array[mid]<k){
start=mid+1;
}
else if(array[mid]>k){
end=mid-1;
}
else{
if(mid-1>=0 && array[mid-1]==k){ //中间位置的前一个数也为k的话,则仍在前半部分找第一个k
end=mid-1;
}
else{
return mid;
}
}
}
return -1;
}
public static int GetLastK(int [] array , int k, int start, int end) {
while(start<=end){
int mid=(start+end)/2;
if(array[mid]<k){
start=mid+1;
}
else if(array[mid]>k){
end=mid-1;
}
else{
if(mid+1<array.length && array[mid+1]==k){ //中间位置的后一个数也为k的话,则仍在后半部分找最后一个k
start=mid+1;
}
else{
return mid;
}
}
}
return -1;
}
}
* @function 数字在排序数组中出现的次数:递归版本
*/
public class GetNumberOfK_2 {
public int GetNumberOfK(int [] array , int k) {
int number=0;
if(array.length==0||array==null)
return 0;
int first=GetFirstK(array,k,0,array.length-1);
int last=GetLastK(array,k,0,array.length-1);
if(first>-1&&last>-1){ //这里必须限定,不然该数不存在的情况下也会输出1
number=last-first+1;
}
return number;
}
public int GetFirstK(int[] array,int k,int start,int end){
if(start>end)
return -1;
int mid=(start+end)/2;
if(k<array[mid]){
end=mid-1;
}
else if(k>array[mid]){
start=mid+1;
}
else if(k==array[mid]){
if((mid-1>=0 && k!=array[mid-1] ) || mid==0){ //这里需要对边界进行处理,不然会抛出空指针异常
return mid;
}
else
end=mid-1;
}
return GetFirstK(array,k,start,end);
}
public int GetLastK(int[] array,int k,int start,int end){
if(start>end)
return -1;
int mid=(start+end)/2;
if(k<array[mid]){
end=mid-1;
mid=(start+end)/2;
}
else if(k>array[mid]){
start=mid+1;
mid=(start+end)/2;
}
else if(k==array[mid]){
if((mid<end && k!=array[mid+1] )||mid==end){ //这里需要对边界进行处理,不然会抛出空指针异常
return mid;
}
else
start=mid+1;
}
return GetLastK(array,k,start,end);
}
}