1. 程式人生 > >LeetCode刷題Easy篇尋找元素插入位置

LeetCode刷題Easy篇尋找元素插入位置

題目

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.

Example 1:

Input: [1,3,5,6], 5
Output: 2

Example 2:

Input: [1,3,5,6], 2
Output: 1

Example 3:

Input: [1,3,5,6], 7
Output: 4

Example 4:

Input: [1,3,5,6], 0
Output: 0

我的嘗試

分析一下:有序陣列,給定一個數值,如果存在返回索引,不存在返回插入位置,假設沒有重複元素

我的程式碼實現了,但是在leetcode上除錯了很多次,發現忽略了很多情況:

1. 只有兩個元素

2 小於第一個元素,大於最後一個元素。

3. 小於等於,不一樣,如果小於當前元素,插入i-1,如果等於,插入i

class Solution {
    public int searchInsert(int[] nums, int target) {
         if (target<=nums[0]){
            return  0;
        }
        if (target>nums[nums.length-1]){
            return nums.length;
        }
        if(target==nums[nums.length-1]){
            return nums.length-1;
        }
       for(int i=1;i<nums.length-1;i++){
            if (nums[i]>=target){
                return i;
            }
           if (nums[i]<target&&nums[i+1]>=target){
               return i+1;
           }

       }
       return 1;

        
        
    }
}

優化解法

1.折半查詢

1.1 遞迴形式

剛開始發現類似插入排序,但是不是排序,沒有想起來用折半查詢,看了leetcode的其他方法,恍然大悟,下面用折半查詢實現一下:

 public static  int binarySearch(int[] nums,int start,int end,int target) {
       if (start>end){
           return  -1;
       }
       int mid=(start+end)/2;
       int key=nums[mid];
       if (key==target){
           return  mid;
       }
       if (key<target){
           binarySearch(nums,mid+1,end,target);
       }
       else{
           binarySearch(nums,0,mid-1,target);
       }
       return -1;

    }

寫完後,發現執行不對,注意最後我寫了return -1,邏輯對,但是返回結果始終都是-1,這個語句有問題。修改一下:

 public static  int binarySearch(int[] nums,int start,int end,int target) {
       if (start>end){
           return  -1;
       }
       int mid=(start+end)/2;
       int key=nums[mid];

       if (key<target){
           binarySearch(nums,mid+1,end,target);
       }
       if(key>target){
           binarySearch(nums,0,mid-1,target);
       }
       return mid;

    }

雖然mid等於1,但是最後輸出確實2,我debug發現退出遞迴時,外層mid一直髮生變化,遞迴究竟發生了什麼???經過debug,你會發現,其實mid計算出相等後,返回上層是,會執行return mid,這個時候mid值就會發生變化,所以出現錯誤。

其實我沒有理解遞迴的本質,遞迴通過反覆呼叫,關鍵是把深層次的結果層層返回。所以遞迴的呼叫語句前面必定會有return語句,否則遞迴運算的結果無法返回。我上面的程式碼就是,mid最終結果正確,但是沒有返回。修改後如下:

  public static  int binarySearch(int[] nums,int start,int end,int target) {
       if (start>end){
           return  -1;
       }
       int mid=(start+end)/2;
       int key=nums[mid];

       if(key==target){
           return  mid;
       }

       if (key<target){
           return  binarySearch(nums,mid+1,end,target);
       }
        return binarySearch(nums,0,mid-1,target);
    }

針對本題目,如果找到返回就可以,如果沒有找到,返回start索引就是要插入的位置,修改如下:

 if (start>end){
           //如果沒有找到返回插入位置
           return  start;
       }
       int mid=(start+end)/2;
       int key=nums[mid];

       if(key==target){
           return  mid;
       }

       if (key<target){
           return  binarySearch(nums,mid+1,end,target);
       }
        return binarySearch(nums,0,mid-1,target);

1.2 非遞迴形式

 public static  int binarySearch(int[] nums,int start,int end,int target) {
        int mid=0;
        while(start<=end){
            mid=(start+end)/2;
            if (nums[mid]==target){
                return  mid;
            }
            if (nums[mid]<target){
                start=mid+1;
            }
            else {
                end=mid-1;
            }
        }
        return  mid;

    }

2 兩個指標迭代

看到有人提出兩個指標迭代方法,類似於快速排序,其實就是一次快速排序,左邊都比自己小,右邊都比自己大,嘗試一下:

   public static  int quickSearch(int[] nums,int start,int end,int target) {
       while (start<=end){
           while (start<=end&&nums[start]<target){
               start++;
           }
           while (start<=end&&nums[start]>target){
               end--;
           }
           if (start<end){
               swap(nums,start,end);
           }
       }
       return start;
    }


    private static void  swap(int[] nums,int p,int q){
        int tmp=nums[p];
        nums[p]=nums[q];
        nums[q]=tmp;
    }