LeetCode 03 二分查詢

2022-07-24 04:42:11 字數 3848 閱讀 2732

注意:二分查詢中關於mid的選取

while(left <= right) 和 while(left < right) 的區別

while(left < right)表示在區間中還剩下乙個元素的時候,停止迴圈

來自 leetcode @liweiwei1419 對於二分搜尋編碼的建議在迴圈體內考慮如何縮減待搜尋區間,也可以認為是在待搜尋區間裡排除一定不存在目標元素的區間;

根據中間數被分到左邊和右邊區間,來調整取中間數的行為;

如何縮小待搜尋區間

退出迴圈的時候,根據題意看是否需要單獨判斷最後剩下的那個數是不是目標元素。

邊界設定的兩種寫法:

使用二分查詢的要點

69. x 的平方根(簡單)

**

public int mysqrt(int x) 

if (x < 4)

int left = 2;

int right = x / 2;

int mid = 0;

while (left <= right) else if (temp > x) else

}return (long)mid * (long)mid > x ? mid - 1 : mid;

}

注意:34. 在排序陣列中查詢元素的第乙個和最後乙個位置(中等)

那麼能不能通過調整二分查詢的一些策略,找到我們需要的位置呢?

**

public int searchrange(int nums, int target) ;

}if (nums.length <= 1) : new int ;

}int res = new int;

int left = 0;

int right = nums.length - 1;

// 找到第一次出現的位置

while (left < right) else

}res[0] = nums[right] != target ? -1 : right;

if (res[0] == -1) ;

}// 找最後一次出現的位置

left = right;

right = nums.length - 1;

while (left < right) else

}res[1] = nums[left] == target ? left : left - 1;

return res;

}

注意:81. 搜尋旋轉排序陣列 ii(中等)

找到i時間複雜度為o(n),二分查詢時間複雜度為o(log n),總的時間複雜度為o(n)

**

public boolean search(int nums, int target) 

if (nums.length == 1)

int flag = 0;

for (int i = 0; i < nums.length - 1; i++)

}return binarysearch(0, flag, nums, target) || binarysearch(flag + 1, nums.length - 1, nums, target);

}public boolean binarysearch(int left, int right, int nums,int target) else if (nums[mid] < target) else

}return false;

}

改進(來自leetcode官方題解)

時間複雜度 o(log n)

實現

public boolean search(int nums, int target) 

if (nums.length == 1)

int left = 0;

int right = nums.length - 1;

while (left <= right)

if (nums[left] == nums[mid]) else if (nums[mid] <= nums[right]) else

} else else }}

return false;

}

要點:如何判斷哪邊有序?

154. 尋找旋轉排序陣列中的最小值 ii(困難)

記這個元素下標為i

參考3.4,制定策略

為什麼要使用right進行判斷而不是使用left

**

public int findmin(int nums) 

int left = 0;

int right = nums.length - 1;

int mid = 0;

while (left < right) else if (nums[right] == nums[mid]) else

}return nums[left];

}

注意540. 有序陣列中的單一元素(中等)

也就是說,

根據這樣的規律,即可推斷出單一元素是在mid的 左邊還是右邊

**

public int singlenonduplicate(int nums) 

if (nums.length == 1 || nums[0] != nums[1])

if (nums[nums.length - 1] != nums[nums.length -2])

int left = 0;

int right = nums.length - 1;

while (left <= right)

if (mid % 2 != 0) else

} else else }}

return 0;

}

注意4. 尋找兩個正序陣列的中位數(困難)

如果對時間複雜度的要求有 log,通常都需要用到二分查詢,這裡我是沒想出來有什麼好方法,後來看了官方題解後恍然大悟

對於某些情況,需要特殊處理

總結

每次縮減陣列之後,k要減去陣列減少的元素個數

**

public double findmediansortedarrays(int nums1, int nums2)  else 

}private int findkth(int nums1, int nums2, int k)

if (index2 == length2)

// 當 k=1 時退出迴圈

if (k == 1)

int half = k / 2;

// 這步操作保證了newindex不會超出陣列長度

int newindex1 = math.min(index1 + half, length1) - 1;

int newindex2 = math.min(index2 + half, length2) - 1;

int pivot1 = nums1[newindex1], pivot2 = nums2[newindex2];

// k要減去每次排除的元素個數

if (pivot1 <= pivot2) else

}}

03二分查詢

整數二分要注意邊界問題 不然特別容易出現死迴圈 二分的本質是邊界問題 1.mid l r 2 2.檢查mid處是否滿足性質 在二分左邊時不需要 1 二分右邊時需要 1 二分必須要保證有解 題目可能無解,我們可以通過最後的邊界來判斷題目是否有解 def main n,m map int,input s...

LeetCode 查詢 二分查詢

給定乙個 n 個元素有序的 公升序 整型陣列 nums 和乙個目標值 target 寫乙個函式搜尋 nums 中的 target,如果目標值存在返回下標,否則返回 1。示例 輸入 nums 1,0,3,5,9,12 target 9 輸出 4 解釋 9 出現在 nums 中並且下標為 4 輸入 nu...

leetcode 二分查詢

leetcode 29 給定兩個整數,被除數dividend和除數divisor。將兩數相除,要求不使用乘法 除法和 mod 運算子。返回被除數dividend除以除數divisor得到的商。演算法設計 用2進製的左移操作,每次對被除數左移1位,比較除數與被除數左移的後的大小關係,並在結果中加上左移...