1. 程式人生 > 實用技巧 >【LeetCode/LintCode】 題解丨大廠演算法面試模板:二分查詢

【LeetCode/LintCode】 題解丨大廠演算法面試模板:二分查詢

給定一個排序的整數陣列(升序)和一個要查詢的整數​target​,用​O(logn)​的時間查詢到target第一次出現的下標(從0開始),如果target不存在於陣列中,返回​-1​。

線上評測地址:

LintCode 領釦

樣例 1:

輸入:[1,4,4,5,7,7,8,9,9,10],1
輸出: 0
        
樣例解釋: 
第一次出現在第0個位置。

樣例 2:

輸入: [1, 2, 3, 3, 4, 5, 10],3
輸出: 2
        
樣例解釋: 
第一次出現在第2個位置

樣例 3:

輸入: [1, 2, 3, 3, 4, 5, 10],6
輸出: -1
        
樣例解釋: 
沒有出現過6, 返回-1

解題思路

題目提到,給定的陣列已經排序,若從小到大遍歷陣列查詢target,則時間複雜度為O(n)O(n),n為陣列長度。需要用一個O(logn)O(logn)的時間複雜度去完成本題,那麼需要用到二分查詢。

二分查詢常用於查詢有序陣列中目標數target的位置,用​left​和​right​記錄target所在的區間端點,每次將區間的中間位置值和target作比較,然後移動區間端點。

演算法流程

  • 將區間賦值為整個陣列區間(left = 0, right = n - 1),取中間位置mid
  • 若​a[mid]​ < target,則將區間縮小到原區間的右區間(left = mid + 1)
  • 若​a[mid]​ >= target,則將區間縮小至原區間的左區間(right = mid)
  • 若left >= right 時,若​a[right]​ = target則返回right, 否則返回-1

複雜度分析

  • 時間複雜度:O(logn)
  • 每次查詢都將區間縮小至原來長度的一半,可見查詢的最多次數為logn
  • 空間複雜度:O(1)
  • 查詢不需要開闢新的非常數級空間,只需在原陣列基礎上進行查詢即可

程式碼

public class Solution {
    /**
     * @param nums: The integer array.
     * @param target: Target to find.
     * @return: The first position of target. Position starts from 0.
     */
    public int binarySearch(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        int mid;

        while (left < right) {
            //得到中間位置
            mid = (right + left) / 2;
            if (nums[mid] < target) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }

        if (nums[right] == target) {
            return right;
        }

        return -1;
    }
}

更多題解參考:

九章演算法 - 幫助更多中國人找到好工作,矽谷頂尖IT企業工程師實時線上授課為你傳授面試技巧