根据题意要找的是平方小于x且最接近的数。如此可以想到用二分法查找
完整代码如下:
public static int mySqrt(int x) {
int start = 0;
int end = x;
while (start <= end) {
int temp = (start + end) / 2;
Long sum = (long)temp * temp;
if(sum == x) return temp;
else if(sum > x) {
end = temp - 1;
}
else {
start = temp + 1;
}
}
return (start + end) / 2;
}
按顺序排列来查找就可以用二分查找
public static boolean searchMatrix(int[][] matrix, int target) {
int startRow = 0;
int endRow = matrix.length - 1;
int targetRow = 0;
int startCol = 0;
int endCol = matrix[0].length - 1;
while (startRow <= endRow) {
int mid = (startRow + endRow) / 2;
if(matrix[mid][startCol] > target){
endRow = mid - 1;
}else if(matrix[mid][endCol] < target){
startRow = mid + 1;
}else {
if(matrix[mid][startCol] == target || matrix[mid][endCol] == target) return true;
targetRow = mid;
break;
}
}
while (startCol <= endCol) {
int mid = (startCol + endCol) / 2;
if(matrix[targetRow][mid] == target) return true;
else if(matrix[targetRow][mid] < target) startCol = mid + 1;
else endCol = mid - 1;
}
return false;
}
读题可知,该数组是由单向递增的数组转置而来。
所以当取mid将数组分成两段的时候至少有一段是有序的。
则可一开始进行判断mid在左还在右
if(mid_num >= nums[0]) flag = true;//左半边
else flag = false;//右半边
当然有可能会有三个数相等的情况如:
1,1,1,1,1,1,1,1,2,1
此时则需要进行另一种讨论
直接缩小范围进行下一轮的查询
if (nums[left] == nums[mid] && nums[right] == nums[mid]){
left++;
right--;
continue;
}
对于能够分出左右两段的数组
if(target < nums[mid] && target > nums[left] && flag){//target 落在左边
right = mid - 1;
continue;
} else if (target > nums[mid] && target < nums[right] && !flag) {//落在右边
left = mid + 1;
continue;
}else { //在外
if(flag) left = mid + 1;
else right = mid - 1;
}
完整代码如下:
public static boolean search(int[] nums, int target) {
boolean flag;//标记mid 在左半边 还是右半边
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
int mid_num = nums[mid];
if(mid_num == target || nums[left] == target || nums[right] == target) return true;
if (nums[left] == nums[mid] && nums[right] == nums[mid]){
left++;
right--;
continue;
}
if(mid_num >= nums[0]) flag = true;//左半边
else flag = false;//右半边
if(target < nums[mid] && target > nums[left] && flag){//target 落在左边
right = mid - 1;
continue;
} else if (target > nums[mid] && target < nums[right] && !flag) {//落在右边
left = mid + 1;
continue;
}else { //在外
if(flag) left = mid + 1;
else right = mid - 1;
}
}
return false;
}