# 九章算法题解记录【二】二分查找及逆序数组相关

8 篇文章 0 订阅

public class 二分查找模板 {
int binarySearch(int[] nums, int start, int end, int target){

// 错误输入条件
if (nums.length == 0 || start > end)
return -1;
// int start = 0, end = len - 1;   //当函数参数不包括start, end时
while (start + 1 < end) { //注意这里是start+1，是<不是<=
int mid = start + (end - start) / 2;
// 注意： =, <, > 三种情况，mid 不+1也不-1
if (nums[mid] == target) {
// 寻找最后一个重复元素位置
// start = mid;
// 寻找第一个重复元素位置
// end = mid;
// 注释掉return  之后在while之后进行判断 if
return mid;
} else if (nums[mid] < target) {
start = mid;
} else {
end = mid;
}
}
// 注意，循环结束后，单独处理start和end
if (nums[start] == target) {
return start;
}
if (nums[end] == target) {
return end;
}
return -1;
}
}



1 Search for a range http://www.lintcode.com/problem/search-for-a-range/

public class Solution {
/**
* @param A: an integer sorted array
* @param target: an integer to be inserted
* @return: a list of length 2, [index1, index2]
*/
public int[] searchRange(int[] A, int target) {
if (A == null) return null;
if (A.length == 0) return new int[]{-1, -1};
int start = searchForStart(A, target);
int end = searchForEnd(A, target);
return new int[]{start, end};
}

private int searchForStart(int[] nums, int target){
int start = 0, end = nums.length - 1;
if (nums.length == 0 || start > end)
return -1;
// int start = 0, end = len - 1;   //当函数参数不包括start, end时
while (start + 1 < end) { //注意这里是start+1，是<不是<=
int mid = start + (end - start) / 2;
// 注意： =, <, > 三种情况，mid 不+1也不-1
if (nums[mid] == target) {
end = mid;
} else if (nums[mid] < target) {
start = mid;
} else {
end = mid;
}
}
if (nums[start] == target) {
return start;
}
if (nums[end] == target) {
return end;
}
return -1;
}
private int searchForEnd(int[] nums, int target){
int start = 0, end = nums.length - 1;
if (nums.length == 0 || start > end)
return -1;
// int start = 0, end = len - 1;   //当函数参数不包括start, end时
while (start + 1 < end) { //注意这里是start+1，是<不是<=
int mid = start + (end - start) / 2;
// 注意： =, <, > 三种情况，mid 不+1也不-1
if (nums[mid] == target) {
start = mid;
} else if (nums[mid] < target) {
start = mid;
} else {
end = mid;
}
}
if (nums[end] == target) {
return end;
}
if (nums[start] == target) {
return start;
}
return -1;
}
}


2 Search Insert Position https://www.lintcode.com/problem/search-insert-position/ easy

public class Solution {
/**
* @param A: an integer sorted array
* @param target: an integer to be inserted
* @return: An integer
*/
public int searchInsert(int[] A, int target) {
int start = 0, end = A.length - 1;
if (A.length == 0)
return 0;
//int start = 0, end = len - 1;   //当函数参数不包括start, end时
while (start + 1 < end) { //注意这里是start+1，是<不是<=
int mid = start + (end - start) / 2;
// 注意： =, <, > 三种情况，mid 不+1也不-1
if (A[mid] == target) {
return mid;
} else if (A[mid] < target) {
start = mid;
} else {
end = mid;
}
}
if (A[start] >= target) {
return start;
}
if (A[end] >= target) {
return end;
} else{
return end + 1;
}
}
}


3 Search in a 2D Matrix

public class Solution {
/**
* @param matrix: matrix, a list of lists of integers
* @param target: An integer
* @return: a boolean, indicate whether matrix contains target
*/
public boolean searchMatrix(int[][] matrix, int target) {
// 错误输入条件
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return false;
}
int rows = matrix.length;
int cols = matrix[0].length;
int start = 0, end = rows * cols - 1;   //当函数参数不包括start, end时
while (start + 1 < end) { //注意这里是start+1，是<不是<=
int mid = start + (end - start) / 2;
// 注意： =, <, > 三种情况，mid 不+1也不-1
if (matrix[mid / cols][mid % cols] == target) {
return true;
} else if (matrix[mid / cols][mid % cols] < target) {
start = mid;
} else {
end = mid;
}
}
// 注意，循环结束后，单独处理start和end ,第一个先看start 最后一个先看end
if (matrix[start / cols][start % cols] == target) {
return true;
}
if (matrix[end / cols][end % cols] == target) {
return true;
}
return false;
}
}


4 Search a 2D Matrix II

public class Solution {
/**
* @param matrix: A list of lists of integers
* @param target: An integer you want to search in matrix
* @return: An integer indicate the total occurrence of target in the given matrix
*/
public int searchMatrix(int[][] matrix, int target) {
// 剑指offer原题哈,从右上开始找
if (matrix == null || matrix.length == 0) {
return 0;
}
if (matrix[0] == null || matrix[0].length == 0) {
return 0;
}
int rows = matrix.length;
int cols = matrix[0].length;
int res = 0;
int i = 0, j = cols - 1;
while (i <= rows - 1 && j >= 0) {
if (matrix[i][j] == target){
res ++;
i++;
} else if (matrix[i][j] > target) {
j--;
} else {
i++;
}
}
return res;
}
}


5 Find Peak Element

public class Solution {
/**
* @param A: An integers array.
* @return: return any of peek positions.
*/
public int findPeak(int[] A) {
if (A == null || A.length < 3) {
return 0;
}
int start = 1, end = A.length - 2;
while (start + 1 < end){
int mid = start + (end - start) / 2;
if (A[mid] > A[mid + 1] && A[mid] > A[mid - 1]){
return mid;
} else if (A[mid] > A[mid - 1] && A[mid] < A[mid] + 1) {
start = mid;
} else {
end = mid;
}
}
if (start >= 1 && A[start] > A[start - 1] && A[start] > A[start + 1]){
return start;
}
if (end >= 1 && A[end] > A[end - 1] && A[end] > A[end + 1]){
return end;
}
return -1;
}
}


1 Find Minimum in Rotated Sorted Array https://www.lintcode.com/problem/find-minimum-in-rotated-sorted-array/description

public class Solution {
/**
* @param nums: a rotated sorted array
* @return: the minimum number in the array
*/
public int findMin(int[] nums) {
if (nums == null || nums.length == 0) {
return -1;
}

int start = 0, end = nums.length - 1;
int target = nums[nums.length - 1];

// find the first element <= target
while (start + 1 < end) {    		//用来控制区间大小
int mid = start + (end - start) / 2;
if (nums[mid] <= target) { 		//如果mid位置上的数字小于等于最右端的数字时，区间向左移动
end = mid;
} else {
start = mid;
}
}
return Math.min(nums[start],nums[end]);  //最终返回start和end位置上较小的数字即可

}
}


2 Find Minimum in Rotated Sorted Array II https://www.lintcode.com/problem/find-minimum-in-rotated-sorted-array-ii/

public int findMin(int[] num) {
//  这道题目在面试中不会让写完整的程序
//  只需要知道最坏情况下 [1,1,1....,1] 里有一个0
//  这种情况使得时间复杂度必须是 O(n)
//  因此写一个for循环就好了。
//  如果你觉得，不是每个情况都是最坏情况，你想用二分法解决不是最坏情况的情况，那你就写一个二分吧。
//  反正面试考的不是你在这个题上会不会用二分法。这个题的考点是你想不想得到最坏情况。
int min = num[0];
for (int i = 1; i < num.length; i++) {
if (num[i] < min)
min = num[i];
}
return min;
}


3 Search in Rotated Sorted Array http://www.lintcode.com/problem/search-in-rotated-sorted-array/

public class Solution {
/**
* @param A: an integer rotated sorted array
* @param target: an integer to be searched
* @return: an integer
*/
public int search(int[] A, int target) {
if (A == null || A.length == 0) {
return -1;
}

int start = 0, end = A.length - 1;

while (start + 1 < end) {    		//用来控制区间大小
int mid = start + (end - start) / 2;
if (A[mid] == target) {
return mid;
}
if (A[start] < A[mid]) {
// situation 1, red line
if (A[start] <= target && target <= A[mid]) {
end = mid;
} else {
start = mid;
}
} else {
// situation 2, green line
if (A[mid] <= target && target <= A[end]) {
start = mid;
} else {
end = mid;
}
}
}

if (A[start] == target) {
return start;
}
if (A[end] == target) {
return end;
}
return -1;

}
}


4 Search in Rotated Sorted Array II http://www.lintcode.com/problem/search-in-rotated-sorted-array-ii/

public class Solution {
// 这个问题在面试中不会让实现完整程序
// 只需要举出能够最坏情况的数据是 [1,1,1,1... 1] 里有一个0即可。
// 在这种情况下是无法使用二分法的，复杂度是O(n)
// 因此写个for循环最坏也是O(n)，那就写个for循环就好了
//  如果你觉得，不是每个情况都是最坏情况，你想用二分法解决不是最坏情况的情况，那你就写一个二分吧。
//  反正面试考的不是你在这个题上会不会用二分法。这个题的考点是你想不想得到最坏情况。
public boolean search(int[] A, int target) {
for (int i = 0; i < A.length; i ++) {
if (A[i] == target) {
return true;
}
}
return false;
}
}


Median Kth 有序数组
5 Median of Two Sorted Arrays http://www.lintcode.com/problem/median-of-two-sorted-arrays/

public class MedianofTwoSortedArrays {
/*
* @param A: An integer array
* @param B: An integer array
* @return: a double whose format is *.5 or *.0
*/
public double findMedianSortedArrays(int[] A, int[] B) {
int n = A.length + B.length;

if (n % 2 == 0) {
return (findKth(A, B, n / 2) + findKth(A, B, n / 2 + 1)) / 2.0;
}

return findKth(A, B, n / 2 + 1);
}

// k is not zero-based, it starts from 1
public int findKth(int[] A, int[] B, int k) {
if (A.length == 0) {
return B[k - 1];
}
if (B.length == 0) {
return A[k - 1];
}

int start = Math.min(A[0], B[0]);
int end = Math.max(A[A.length - 1], B[B.length - 1]);

// find first x that >= k numbers is smaller or equal to x
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (countSmallerOrEqual(A, mid) + countSmallerOrEqual(B, mid) < k) {
start = mid;
} else {
end = mid;
}
}

if (countSmallerOrEqual(A, start) + countSmallerOrEqual(B, start) >= k) {
return start;
}

return end;
}

private int countSmallerOrEqual(int[] arr, int number) {
int start = 0, end = arr.length - 1;

// find first index that arr[index] > number;
while (start + 1 < end) {
int mid = start + (end - start) / 2;
if (arr[mid] <= number) {
start = mid;
} else {
end = mid;
}
}

if (arr[start] > number) {
return start;
}

if (arr[end] > number) {
return end;
}

return arr.length;
}
}



public class Solution {
public double findMedianSortedArrays(int A[], int B[]) {
int n = A.length + B.length;

if (n % 2 == 0) {
return (
findKth(A, 0, B, 0, n / 2) +
findKth(A, 0, B, 0, n / 2 + 1)
) / 2.0;
}

return findKth(A, 0, B, 0, n / 2 + 1);
}

// find kth number of two sorted array
public static int findKth(int[] A, int startOfA,
int[] B, int startOfB,
int k){
if (startOfA >= A.length) {
return B[startOfB + k - 1];
}
if (startOfB >= B.length) {
return A[startOfA + k - 1];
}

if (k == 1) {
return Math.min(A[startOfA], B[startOfB]);
}

int halfKthOfA = startOfA + k / 2 - 1 < A.length
? A[startOfA + k / 2 - 1]
: Integer.MAX_VALUE;
int halfKthOfB = startOfB + k / 2 - 1 < B.length
? B[startOfB + k / 2 - 1]
: Integer.MAX_VALUE;

if (halfKthOfA < halfKthOfB) {
return findKth(A, startOfA + k / 2, B, startOfB, k - k / 2);
} else {
return findKth(A, startOfA, B, startOfB + k / 2, k - k / 2);
}
}
}


Rotated Recover类操作数组的问题，用三段reverse法！
6 Recover Rotated Sorted Array http://www.lintcode.com/problem/recover-rotated-sorted-array/

public class Solution {
/**
* @param nums: The rotated sorted array
* @return: The recovered sorted array
*/
private void reverse(ArrayList<Integer> nums, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
int temp = nums.get(i);
nums.set(i, nums.get(j));
nums.set(j, temp);
}
}

public void recoverRotatedSortedArray(ArrayList<Integer> nums) {
for (int index = 0; index < nums.size() - 1; index++) {
//找到第一个比后面的数大的数，以[4,5,1,2,3]为例，找到5，翻转[4,5]得到[5,4]，翻转[1,2,3]得到[3,2,1]
//最后翻转[5,4,3,2,1]得到[1,2,3,4,5]
if (nums.get(index) > nums.get(index + 1)) {
reverse(nums, 0, index);
reverse(nums, index + 1, nums.size() - 1);
reverse(nums, 0, nums.size() - 1);
return;
}
}
}
}


7 Rotate String http://www.lintcode.com/problem/rotate-string/

public class Solution {
/**
* @param str: an array of char
* @param offset: an integer
* @return: nothing
*/
public void rotateString(char[] str, int offset) {
if (str == null || str.length == 0)
return;

offset = offset % str.length;
reverse(str, 0, str.length - offset - 1);
reverse(str, str.length - offset, str.length - 1);
reverse(str, 0, str.length - 1);
}

private void reverse(char[] str, int start, int end) {
for (int i = start, j = end; i < j; i++, j--) {
char temp = str[i];
str[i] = str[j];
str[j] = temp;
}
}
}


8 Reverse Words in a String http://www.lintcode.com/problem/reverse-words-in-a-string/

public class Solution {
/*
* @param s: A string
* @return: A string
*/
public String reverseWords(String s) {
if (s == null) {
return null;
}
if (s.length() == 0) {
return "";
}
String[] strarr = s.split("\\s+");
reverse(strarr, 0, strarr.length - 1);
return String.join(" ",strarr);

}
private void reverse(String[] strs, int start, int end){
for (int i = start, j = end; i < j; i++, j--) {
String temp = strs[i];
strs[i] = strs[j];
strs[j] = temp;
}
}
}


api调用，注意空格分割是 split("\\s+")

• 0
点赞
• 0
收藏
觉得还不错? 一键收藏
• 打赏
• 0
评论
04-13 1392
03-12 3964
01-10 186
11-16 1755
11-17
01-21 98
08-09
01-06 647
04-24 665
03-12 663
08-19 114
03-31 1068

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

Ach_orite

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。