【LeetCode】二分法相關

題目一:二分搜索


給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target  ,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。

鏈接:https://leetcode-cn.com/problems/binary-search/

思路:


這個是最常規的二分法的問題,不斷地縮小搜索範圍來找到最終的值。以下代碼可以作爲此類題目的模板。

代碼:


class Solution {
    public int search(int[] nums, int target) {
        int left = 0;
        int right = nums.length;
        
        while(left < right) {
            int mid = (left + right) >>> 1;
            if(target == nums[mid]) {
                return mid;
            } else if(target < nums[mid]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }
}

題目二:搜索插入位置


給定一個排序數組和一個目標值,在數組中找到目標值,並返回其索引。如果目標值不存在於數組中,返回它將會被按順序插入的位置。

你可以假設數組中無重複元素。

鏈接:https://leetcode-cn.com/problems/search-insert-position/

思路:


思路基本就是二分查找的思路,差別就在於如果沒有找到目標值,返回的是插入的位置。

代碼:


class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0;
        int right = nums.length;
        
        while(left < right) {  
            int mid = (left + right) >>> 1;
            if(target == nums[mid]) {
                return mid;
            } else if(target < nums[mid]) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    }
}

題目三:X的平方根


實現 int sqrt(int x) 函數。

計算並返回 x 的平方根,其中 x 是非負整數。

由於返回類型是整數,結果只保留整數的部分,小數部分將被捨去。

鏈接:https://leetcode-cn.com/problems/sqrtx/

思路:


X的平方根一定在0~X之間,我們可以採用二分法來解決這個問題。注意這道題要使用long類型,因爲int型的數據平方之後可能超過int型數據的表示範圍。具體到代碼裏,這道題目與前兩道題目的不同點在於判定條件。於此類似的問題不同點可以看作是做判斷的那一步驟不同,思想大同小異。

還有幾點要注意:求中間的數:最好使用mid = (left + right) >>> 1(左中位數)或者mid = (left + right + 1) >>> 1(右中位數),區分左右中位數的原因是在某些情況下,選擇默認的左中位數,會進入死循環,因此這裏要具體情況具體分析。while語句的判定條件:最好使用left < right,因爲這樣可以在while循環結束後,不用去考慮left和right的情況,基本是left==right的情況,纔會跳出循環。

代碼:


class Solution {
    public int mySqrt(int x) {
        if(x == 0) {
            return 0;
        }
        long left = 1;
        long right = x;
        
        while(left < right) {
            //進入右中位數
            long mid = (left + right + 1) >>> 1;
            
            long square = mid * mid;
            if(square > x) {
                right = mid - 1;
            } else {
                left = mid;
            }
        }
        return (int)left;
    }
}

題目四:有效的完全平方數


給定一個正整數 num,編寫一個函數,如果 num 是一個完全平方數,則返回 True,否則返回 False。

說明:不要使用任何內置的庫函數,如  sqrt。

鏈接:https://leetcode-cn.com/problems/valid-perfect-square/

思路:


思路與上一題基本一致。要注意一點,跳出while循環之後,要對left(right)的數據進行處理,不然會漏掉那個數據。

代碼:


class Solution {
    public boolean isPerfectSquare(int num) {
        if(num == 0 || num == 1) {
            return true;
        }
        
        long left = 1;
        long right = num / 2;
        
        while(left < right) {
            long mid = (left + right) >>> 1;
            long square = mid * mid;
            if(square == num) {
                return true;
            } else if(square > num) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        if(left * left == num) {
            return true;
        }
        return false;
    }
}

題目五:Pow(x, n)


實現 pow(xn) ,即計算 x 的 n 次冪函數。

鏈接:https://leetcode-cn.com/problems/powx-n/

思路:


採用二分遞歸的思想,2^{n} = (2^{\frac{n}{2}})^{2},不斷的計算2^{\frac{n}{2}},使用遞歸求出結果。

代碼:


class Solution {
    public double myPow(double x, int n) {
        if(n == 1) {
            return x;
        }
        if(n == -1) {
            return 1 / x;
        }
        if(n == 0) {
            return 1;
        }
        double temp = myPow(x, n / 2);
        double rest = myPow(x, n % 2);
        double ans = temp * temp * rest;
        return ans;
    }
}

參考資料:


https://www.liwei.party/2019/06/19/leetcode-solution-new/search-insert-position/

後續更新細節。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章