算法题--搜索插入位置

96 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

太久碰算法题了,今天突然想起来摸一下,发现一个最简单的查找位置,居然花了很长时间,所以打算写一个文章记录一下,我脑子里的坑。

题目

已知存在一个有序且元素不重复的整型数组和一个目标值,查找目标值在该数组中的位置。如果数组中不存在目标值,则返回目标值在数组中应插入的位置。

示例 1:
有序数组: [1,3,5,7,9] ,目标值:7
输出:3

示例 2:
有序数组: [1,3,5,7,9] ,目标值:2
输出:1

示例 3:
有序数组: [1,3,5,7,9] ,目标值:12
输出:5

示例 4:
有序数组: [1] ,目标值:2
输出:1

示例 5:
有序数组: [1] ,目标值:1
输出:0

技术点要求

  • Java 语言
  • 时间复杂度为 O(log n)

看上去非常简单,是不是,好的,马上开始行动; 我的第一次解法:定义一个index,接收返回值,然后开始判断。因为是有序数组,所以如果他比第一个小,或者比最后一个数大,表示他不在数组里面,位置就是第一个,或者最后一个+1; 然后开始循环数组,如果找到了,index=当前下标,如果没有找到,如果有sortArr[i]<target && sortArr[i+1]>target 也可以,然后index=i+1;

这个思路看上去,没毛病,但是我提交就

image.png 好的,通过思考我发现,在i+1可能出现下标越界。然后我开始修改,那就把循环改一下。一个是0-length,一个是0-length-1;i+1那个放在0-length-1,保证了不越界,0-length就使用找得到的。听上去,也没有问题,然后修改,提交,终于》》》》》失败;

然后我发现,如果数组只有一个数,那么i和i+1就有问题啊!!!!

然后就改成了下面这个鬼样子

public class BinarySearchSolution{
    /**
     * 搜索插入位置
     * @param sortArr  有序不重复数组
     * @param target   目标值
     * @return   目标值在数组中的正确位置
     */
    public static int findIndex(int[] sortArr, int target) {
       //代码编辑区 start 
    int index=-1;
    if(sortArr[0]>target){
        index=0;
    }
    if(sortArr[sortArr.length-1]<target)
    if(sortArr[sortArr.length-1]<target){
        index=sortArr.length;
    }
    for(int i=0;i<sortArr.length;i++){
        if(sortArr[i]==target){
            index=i;
            break;
        }
        if(sortArr.length>1){
            if(sortArr[i]<target && sortArr[i+1]>target){
                index=i+1;
                break;
            }
        }else{
            if(sortArr[0]>target){
                index=0;
            }
            if(sortArr[sortArr.length-1]<target){
                index=sortArr.length;
            }
        }
        
  
     
    }
    return index;

       


       
        //代码编辑区 end
    }
    public static void main(String[] args) {
        int [] sortArr ={1};
        int target = 1 ;
        System.out.println(findIndex(sortArr, target));
    }

}

好家伙,还是不能通过,而且修改后代码非常冗余,也不利于读代码,感觉自己好废物。

于是重新思考: 想到了二分查找:

思路:定义left=0,right=sortArr.length-1,定义mind=(left+right)/2
如果sortArr[mind]=target 输出mind
如果比target小,right=mind-1;
如果比target大,right=mind+1;
int left = 0, right = sortArr.length - 1;
while(left <= right) {
int mid = (left + right) / 2;
if(sortArr[mid] == target) {
return mid;
} else if(sortArr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
System.out.println(left);
return left;
}
终于,它通过了,但是我又怎么会放弃最开始那个解法,于是开始反复修改,分析

分析: 分两种情况,找到和没找到,找到就是返回下标,没有找到就是插入。 如果比第一个小,返回下标0 如果比最后一个大,返回length+1 然后我就开始写代码,先是比第一个小比最后一个大 然后开始循环数组,如果找到一个值等于target,就返回下标 没有就是 如果第i个比target小,第i+1比target大,返回i+1

public class BinarySearchSolution{
   /**
    * 搜索插入位置
    * @param sortArr  有序不重复数组
    * @param target   目标值
    * @return   目标值在数组中的正确位置
    */
   public static int findIndex(int[] sortArr, int target) {
      //代码编辑区 start 
   int index=-1;
   if(sortArr[0]>target){
       index=0;
     }else if(sortArr[sortArr.length-1]<target){
       index=sortArr.length;
      }else{
     for(int i=0;i<sortArr.length;i++){
      if(target==sortArr[i]){
          index=i;
      }else if(sortArr[i]<target && sortArr[i+1]>target){
          index=i+1;
      }
  }
}
  return index;
       //代码编辑区 end
   }
   public static void main(String[] args) {
       int [] sortArr ={1};
       int target = 1 ;
       System.out.println(findIndex(sortArr, target));
   }

}

终于,它也通过了,这里我就添加了一点if else。

然后我就开始百度寻求其他解法

暴力解法
public static int findIndex(int[] sortArr, int target) {
//代码编辑区 start
for(int i=0;i<sortArr.length;i++){
if(sortArr[i]>=target){
return i;
}
}
return sortArr.length;
}\

为啥人家的暴力解法这么简单!!!o no
很清晰的:因为从0开始,所以如果目标值小于第一个数,自然小于全部,然后不管查找还是插入,位置都是i。如果没在小于等于里面,看到大于数组最后一个数;
果然,今天发现算法的优点了,虽然这个属于暴力解法,但是思路和我第一次想的差不多,但是代码非常简练。