[算法专题] 二分搜索&排序数组 – Acjx

基础知识

二分非递归写法:

int binary_search(const int a[], const int size, const int val) {
int lower = 0;
int upper = size-1;
/* invariant: if a[i]==val for any i, then lower <= i <= upper */
while (lower <= upper) {
int i = lower + (upper-lower)>>1;
if (val == a[i]) {
return i;
} else if (val < a[i]) {
upper = i-1;
} else { /* val > a[i] */
lower = i+1;
}
}
return -1;
}

二分递归写法

int binarySearch(int *array, int left, int right, int value) {
if (left > right) {
// value not found
return -1;
}

int mid = left + (right – left) / 2;
if (array[mid] == value) {
return mid;
} else if (array[mid] < value) {
return binarySearch(array, mid + 1, right, value);
} else {
return binarySearch(array, left, mid – 1, value);
}
}

刷题

1 Find a Fixed Point in a given array

http://www.geeksforgeeks.org/find-a-fixed-point-in-a-given-array/

Given an array of n distinct integers sorted in ascending order, write a function that returns a Fixed Point in the array, if there is any Fixed Point present in array, else returns -1. Fixed Point in an array is an index i such that arr[i] is equal to i. Note that integers in array can be negative.

Examples:

Input: arr[] = {-10, -5, 0, 3, 7}
Output: 3 // arr[3] == 3

Input: arr[] = {0, 2, 5, 8, 17}
Output: 0 // arr[0] == 0
Input: arr[] = {-10, -5, 3, 4, 7, 9}
Output: -1 // No Fixed Point

image

来看代码:

int indexSearch(int *array, int left, int right) {
if (left > right) {
// value not found
return -1;
}

int mid = right – (right – left) / 2;
if (array[mid] == mid) {
return mid;
} else if (array[mid] < mid) {
return indexSearch(array, mid + 1, right);
} else {
return indexSearch(array, left, mid – 1);
}
}

2 Search Insert Position

https://leetcode.com/problems/search-insert-position/

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0

/**
* 假设sorted array为:a b c d e f g
* 如果以下方式进行二分排除,假设排除了d e f g,可以一定保证target不再[d,g]中,但是在不在[a,c]中其实并不能保证
*
* 因此当left <= right时,有target不在[最左边元素,left左边相邻的元素]与[right右边相邻的元素, 最右边元素]中,分析以下情况:
*
* 1.
* 当left往右越过right时,排除了right以及right左边的元素,同时target本身就不在[right右边相邻的元素即现在的left, 最右边元素]中,
* 因此有nums[right] < target < nums[left]
*
* 2.
* 当right往左越过left时,排除了left以及left右边的元素,同时target本身就不在[最左边元素,left左边相邻的元素即现在的right]中,
* 因此有nums[right] < target < nums[left]
*
* 综上:
* 当right < left时,可以得知:target不在[左边元素,right]和[left,右边元素]中,因此必然有nums[right] < target < nums[left]
*/

class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() – 1;
while (left <= right) {
int middle = left + ((right – left) >> 1);
if (target == nums[middle]) {
return middle;
} else if (target < nums[middle]) {
right = middle – 1;
} else {
left = middle + 1;
}
}

// 注意:当right < left退出循环时,一定可以保证nums[right] < target < nums[left]
// 边界条件,当right = -1时,有target < nums[left] = nums[0]
// 边界条件,当left = nums.size()时,有nums[nums.size() – 1] = nums[right] > target
return right + 1;
}
};

3 Search in Rotated Sorted Array

https://leetcode.com/problems/search-in-rotated-sorted-array/

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

image

思路:

1. 经过rotate,有序数组分割成两个有序数组。

2. 二分后,[left,middle)和(middle,end]必然有一个是有序的。我们可以通过其中的一个有序数组来排除元素。

现在假设[left,middle)这个区间中元素是有序,如果key在[left,middle)这个区间中,则可将(middle,end]的元素均排除;如果key不在[left,middle)这个区间中,则可将[left,middle)排除。

3. 其实不难发现,只要middle有一边的元素是有序的,即可使用二分。

class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() – 1;
while (left <= right) {
int middle = left + ((right – left) >> 1);
if (target == nums[middle]) {
return middle;
}

// 左半部分有序
if (nums[left] <= nums[middle]) {
if (nums[left] <= target && target < nums[middle]) {
right = middle – 1;
} else {
left = middle + 1;
}
}

// 右半部分有序
if (nums[middle] < nums[right]) {
if (nums[middle] < target && target <= nums[right]) {
left = middle + 1;
} else {
right = middle – 1;
}
}
}

return -1;
}
};

4 Sqrt(x)

https://leetcode.com/problems/sqrtx/

Implement int sqrt(int x).

Compute and return the square root of x.

class Solution {
public:
int mySqrt(int x) {

if (x == 0) {
return x;
}

int left = 1;
int right = x;

while (left <= right) {
int middle = left + ((right – left) >> 1);

if (middle == x / middle) {
return middle;
} else if (middle < x/middle) {
left = middle + 1;
} else {
right = middle – 1;
}
}

return right;
}
};

以下为浮点数版本:

double mySqrtHelper(double x, double lowBound, double highBound) {
double precision = 0.00001;
double sqrt = lowBound / 2 + highBound / 2;
if (abs(sqrt * sqrt – x) < precision) {
return sqrt;
} else if (sqrt * sqrt – x > 0) {
return mySqrtHelper(x, lowBound, sqrt);
} else {
return mySqrtHelper(x, sqrt, highBound);
}
}

double mySqrt(double x) {
if (x < 0)
return ERROR;

if (x == 0) {
return 0;
}

if (x == 1) {
return 1;
}

if (x < 1) {
return mySqrtHelper(x, x, 1);
} else {
return mySqrtHelper(x, 1, x);
}
}

5 矩阵搜索

image

bool isElementInMatrix(int **matrix, int M, int N, int target) {
int row = 0;
int column = N – 1;

while (row < M && column >= 0) {
if (matrix[row][column] == target) {
return true;
} else if (matrix[row][column] < target) {
row++;
} else {
column–;
}
}
return false;
}

复杂度O(m+n)。

6 Range search

image

void searchRangeHelper(int array[], int left, int right, int target, int &begin, int &end) {
if (left > right) {
return;
}

int mid = right – (right – left) / 2;
if (array[mid] == target) {
if (mid < begin || begin == -1) {
begin = mid;
}
if (mid > end) {
end = mid;
}
searchRangeHelper(array, left, mid – 1, target, begin, end);
searchRangeHelper(array, mid + 1, right, target, begin, end);
}
else if (array[mid] < target) {
searchRangeHelper(array, mid + 1, right, target, begin, end);
}
else {
searchRangeHelper(array, left, mid – 1, target, begin, end);
}
}

vector<int> searchRange(int A[], int n, int target) {
int begin = -1, end = -1;

searchRangeHelper(A, 0, n – 1, target, begin, end);

vector<int> ans;
ans.push_back(begin);
ans.push_back(end);
return ans;
}

(未完待续)

 

本文链接:[算法专题] 二分搜索&排序数组,转载请注明。



You must enable javascript to see captcha here!

Copyright © All Rights Reserved · Green Hope Theme by Sivan & schiy · Proudly powered by WordPress

无觅相关文章插件,快速提升流量