文章目錄
69.x的平方根
去除x0和x1的情況,然後從1到x進行二分查找
public class Solution {
public int mySqrt(int x) {
if (x == 0 || x == 1) return x;
int left = 1;
int right = x;
while (left <= right) {
int mid = left + (right - left) / 2;//防止越界,用減法或者位運算
// int mid = (right + left) >> 1;
System.out.println(mid);
if (mid > x / mid) right = mid - 1;//除法防止越界
else left = mid + 1;
}
return right;
}
}
牛頓迭代法:
參考題解
class Solution {
public int mySqrt(int x) {
long r = x;
while (r * r > x) {
r = (r + x / r) / 2;
}
return (int)r;
}
}
367.有效的完全平方數
二分查找
class Solution {
public boolean isPerfectSquare(int num) {
if (num == 1) return true;
long left = 2;
long right = num / 2;
while (left <= right) {
long mid = (left + right) >> 1;
if (mid * mid == num) return true;
else if (mid > num / mid) right = mid - 1;
else left = mid + 1;
}
return false;
}
}
牛頓迭代法
迭代求算數平方根,如果算數平方根的平方還是num,說明是完全平方數
class Solution {
public boolean isPerfectSquare(int num) {
if (num == 1) return true;
long x = num;
while (x * x > num) {
x = (x + num / x) / 2;
if (x * x == num) {
return true;
}
}
return false;
}
}
33.搜索旋轉排序數組
二分查找:每次查找必有一邊是有序的!找到有序的一邊,判斷target在不在裏面
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = (left + right) >> 1;
if (target == nums[mid]) return mid;//找到結果
//前半段有序(可能的情況:456123,444123,因爲旋轉前是有序的,所以這個條件一定滿足)
if (nums[left] <= nums[mid]) {
//taget在前半段,mid位置已經判斷了,left位置還需要判斷
if (target < nums[mid] && target >= nums[left]) {
right = mid - 1;
} else {//不在前半段
left = mid + 1;
}
} else {//後半段有序(可能情況:561234)
//target在後半段,mid位置已經判斷了,right位置還需要判斷
if (target > nums[mid] && target <= nums[right]) {
left = mid + 1;
} else {//不在後半段
right = mid - 1;
}
}
}
//沒找到
return -1;
}
}
74.搜索二維矩陣
二分查找:
將二維數組當成一維進行查找
public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;
int m = matrix.length;
int n = matrix[0].length;
int left = 0;
int right = m * n - 1;
while (left <= right) {
int mid = (left + right) >>> 1;
if (target == matrix[mid / n][mid % n]) return true;
if (target > matrix[mid / n][mid % n]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
}
}
右上角爲起點的查找,查找狀態樹是一棵二叉搜索樹
public class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;
int m = matrix.length;
int n = matrix[0].length;
int i = 0;
int j = n - 1;
while (i < m && j >= 0) {
if (matrix[i][j] == target) return true;
else if ( target>matrix[i][j]) i++;
else j--;
}
return false;
}
}
153.尋找旋轉排序數組中的最小值
如果nums[left] <= nums[right]
說明這一段有序,且是我們選擇的包含拐點的部分
如果沒有序,二分查詢無序部分
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
if (nums[left] <= nums[right]) {
return nums[left];
}
int mid = (left + right) >> 1;
//有序在左邊,就去右邊查找
if (nums[mid] >= nums[left]) {
left = mid + 1;
} else {
right = mid;
}
}
return nums[left];
}
}
class Solution {
public int findMin(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = (left + right) >> 1;
//後半段無序
if (nums[mid] > nums[right]) {
left = mid + 1;
} else {
right = mid;
}
}
return nums[left];
}
}
744.尋找比目標字母大的最小字母
題意:給定一個循環有序的字符數組 letters 和一個字符 target,要求找出 letters 中大於 target 的最小字符,如果
找不到就返回第 1 個字符。
public class Solution {
public char nextGreatestLetter(char[] letters, char target) {
int left = 0;
int right = letters.length - 1;
while (left <= right) {
int mid = (left + right) >> 1;
if (letters[mid] <= target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left < letters.length ? letters[left] : letters[0];
}
}
540.有序數組中的單一元素
針對偶數位的二分查找
計算中點,如果中點下標爲奇數,讓其減1,保證mid是每一組兩個數的開頭
比較mid下標值和mid+1下標值,如果相同說明這個數有兩個,left右移兩位,否則這個位置及之前出現了1個數的,將right設置爲mid
public class Solution {
public int singleNonDuplicate(int[] nums) {
int left = 0;
int right = nums.length - 1;
while (left < right) {
int mid = (left + right) >> 1;
if (mid % 2 == 1) {
mid--;//保證查找區間大小保持奇數,保證mid是一組的開始
}
if (nums[mid] == nums[mid + 1]) {
left = mid + 2;
} else {
right = mid;
}
}
return nums[left];
}
}
278.第一個錯誤的版本
二分查找,如果查找節點是錯誤版本,則第一個錯誤點在當前節點及之前;如果查找節點不是錯誤版本,則第一個錯誤點在當前節點之後
public class Solution extends VersionControl {
public int firstBadVersion(int n) {
int left = 1;
int right = n;
while (left < right) {
int mid = (left + right) >>> 1;
if (isBadVersion(mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}
34.在排序數組中查找元素的第一個和最後一個位置
通過二分查找找到target,然後移動兩個指針找到左右邊界
public class Solution {
public int[] searchRange(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = (left + right) >>> 1;
if (nums[mid] == target) {
int l = mid;//左邊界
int r = mid;//右邊界
while (l - 1 >= 0 && nums[l] == nums[l - 1]) {
l--;
}
while (r + 1 < nums.length && nums[r] == nums[r + 1]) {
r++;
}
return new int[]{l, r};
} else if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return new int[]{-1, -1};
}
}