程式碼隨想錄演算法訓練營第一天 | 704. 二分查詢、27. 移除元素

12点不睡觉还想干啥?發表於2024-07-03

704. 二分查詢

這個之前有寫過,最重要的就是把握住要去搜尋的區間的形式,包括左閉右閉以及左閉右開兩種

class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length;
        while(left < right){  // 左閉右開的版本,結果儲存在[left, right)中,因此如果最終left >= right,就意味著沒有找到結果
            int mid = (left + right) / 2;
            if(nums[mid] > target) { right = mid; }  // 結果在區間[left, mid)
            else if(nums[mid] == target){ return mid; }  
            else{ left = mid + 1; }  // 結果在區間[mid + 1, right)
        }
        return -1;
    }
}

class Solution {
    public int search(int[] nums, int target) {
        int left = 0, right = nums.length - 1;
        while(left <= right){  // 左閉右閉的版本,結果儲存在[left, right]中,只有left > right,意味著沒有找到結果
            int mid = (left + right) / 2;
            if(nums[mid] > target) { right = mid - 1; }
            else if(nums[mid] == target){ return mid; }
            else{ left = mid + 1; }
        }
        return -1;
    }
}

34. 在排序陣列中查詢元素的第一個和最後一個位置

思想還是二分查詢,但分為兩個步驟,分別去找最左邊的和最右邊的。二分查詢我覺得還是先以一種方法去做吧,比如就只用左閉右閉的方式,這樣可以避免自己混亂。

class Solution {
    public int[] searchRange(int[] nums, int target) {
        return new int[] {findLeft(nums, target), findRight(nums, target)};
    }

    public int findLeft(int[] nums, int target){
        int left = 0, right = nums.length - 1;
        int ans = -1;
        while(left <= right){
            int mid = left + (right - left) / 2;
            if(nums[mid] < target) { left = mid + 1; }
            else if(nums[mid] == target) { 
                ans = mid;
                right = mid - 1;  // 找到target後,因為要找最左邊的,所以搜尋空間向左壓縮
            }else{
                right = mid - 1;
            }
        }
        return ans;
    }

    public int findRight(int[] nums, int target){
        int left = 0, right = nums.length - 1;
        int ans = -1;
        while(left <= right){
            int mid = left + (right - left) / 2;
            if(nums[mid] < target) { left = mid + 1; }
            else if(nums[mid] == target) { 
                ans = mid;
                left = mid + 1;  // 同理,向右壓縮搜尋區間
            }else{
                right = mid - 1;
            }
        }
        return ans;
    }
}

27. 移除元素

我的直觀想法就是每遇見一個等於val的元素,就將其換到陣列的末尾,此時換過來的元素還沒有判斷,因此left不動,但換到結尾的元素一定要被刪除,因此right--;遇見不等於val的,不需要交換,left++即可;最終left會停止在陣列最後一個合法元素的下一個元素,其下標剛好為最終陣列的長度

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

今天這些題自己之前有做過,所以做起來還算得心應手,沒有完全忘掉。但還是一點,剛開始二分查詢就先記得用左閉右閉的方法去做,其實基本上大部分的題就套用模板,不要給自己增添別的負擔最好。

相關文章