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
典型的二分查找,本质是找第一个大于等于target的位置
class Solution {
public:
int searchInsert(int A[], int n, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
if(0 == n || target <= A[0]) return 0;
if(target > A[n-1]) return n;
//find the first element who is greater than target
int left = 0,right = n-1,m = 0;
while(left <= right){
m = left + (right - left)/2;
if(A[m] < target){
left = m+1;
}
else{
right = m-1;
}
}
return left;
}
};
Search for a Range
Given a sorted array of integers, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1]
.
For example,
Given [5, 7, 7, 8, 8, 10]
and target value 8,
return [3, 4]
.
需要找出第一个等于target的位置和最后一个等于target的位置
class Solution {
public:
vector<int> searchRange(int A[], int n, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
vector<int> range(2,-1);
int left(0),right(n-1),m(0);
while(left <= right){
m = left + (right-left)/2;
if(A[m] < target){
left = m + 1;
}
else{
right = m - 1;
}
}
if(A[left] != target){
return range;
}
range[0] = left;
left= 0,right = n - 1;
while(left <= right){
m = left + (right - left) / 2;
if(A[m] > target){
right = m - 1;
}
else{
left = m + 1;
}
}
range[1] = right;
return range;
}
};
另一种类似的代码
class Solution {
public:
vector<int> searchRange(int A[], int n, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
vector<int> range(2,-1);
int left(0),right(n),m(0);
while(left < right){
m = left + (right-left)/2;
if(A[m] < target){
left = m + 1;
}
else{
right = m ;
}
}
if(A[left] != target){
return range;
}
range[0] = left;
left= 0,right = n;
while(left < right){
m = left + (right - left) / 2;
if(A[m] > target){
right = m ;
}
else{
left = m + 1;
}
}
range[1] = right - 1;
return range;
}
};
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.
关键在于确定哪一段是排好序的,然后利用排序特性做二分即可。
class Solution {
public:
bool InRange(int left,int right,int query){
return query >= left && query <= right;
}
int search(int A[], int n, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int left = 0, right = n-1 , m = 0;
while(left <= right){
m = left + (right-left)/2;
if(A[m] == target){
return m;
}
if(A[m] >= A[left]){//left part is sorted
if(InRange(A[left],A[m],target)){//target is in this part
right = m - 1;
}
else{//not in this part
left = m + 1;
}
}
else{//the other part is sorted
if(InRange(A[m],A[right],target)){
left = m + 1;
}
else{
right = m - 1;
}
}
}
return -1;
}
};
扩展:
查找旋转数组最小数字(剑指offer,九度1386)
要注意特例情况
#include <iostream>
#include <vector>
using namespace std;
int getSmallElement(const vector<int>& arr){
int left(0),right(arr.size()-1),m(left);
//if the array is sorted or has only one element , just return
if(left == right || arr[left] < arr[right]) return arr[left];
while(arr[left] >= arr[right] ){
if(right - left == 1){
m = right;
break;
}
m = left + (right-left)/2;
// 特例情况
if (arr[left] == arr[m] && arr[m] == arr[right]) {
// 顺序查找
for (int i = left + 1, min = arr[left]; i <= right; i ++) {
if (arr[i] < min) {
min = arr[i];
m = i;
}
}
break;
}
if(arr[m] >= arr[left]) left = m ;
else if(arr[m] <= arr[right]) right = m;
}
return arr[m];
}
int main()
{
int n;
ios::sync_with_stdio(false);
vector<int> array;
while(cin>>n){
int temp;
array.clear();
for(int i = 0; i < n; ++i){
cin>>temp;
array.push_back(temp);
}
cout<<getSmallElement(array)<<endl;
}
return 0;
}
Search in Rotated Sorted Array II
Follow up for "Search in Rotated Sorted Array":
What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
Write a function to determine if a given target is in the array.
class Solution {
public:
bool search(int A[], int n, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int left(0),right(n-1),m(0);
while(left <= right){
m = left + (right - left) / 2;
if(A[m] == target){
return true;
}
if(A[m] > A[left]){//be careful here is > not >=
if(target >= A[left] && target < A[m]){
right = m - 1;
}
else{
left = m + 1;
}
}
else if(A[m] < A[left]){//be careful the condition is A[m] < A[left] but not A[m] < A[right]
if(target > A[m] && target <= A[right]){
left = m + 1;
}
else{
right = m - 1;
}
}
else{//A[m] == A[left]
left++;
}
}
return false;
}
};
Search a 2D Matrix
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
- Integers in each row are sorted from left to right.
- The first integer of each row is greater than the last integer of the previous row.
For example,
Consider the following matrix:
[ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ]
Given target = 3
, return true
.
这道题在剑指offer也有的。
思路是从右上角开始比较,如果小于target,则可以略去一行向下继续查找,如果大于target,可以略去一列向左继续查找。
class Solution {
public:
bool searchMatrix(vector<vector<int> > &matrix, int target) {
// Note: The Solution object is instantiated only once and is reused by each test case.
//search from the right top corner, every comparition we can cut off one column or row
int rows = matrix.size();
if(0 == rows) return false;
int cols = matrix[0].size();
int x = 0;
int y = cols-1;
while(x < rows && y >= 0){
if(matrix[x][y] == target){
return true;
}
else if(matrix[x][y] > target){
y--;
}
else{
x++;
}
}
return false;
}
};
Median of Two Sorted Arrays
There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
class Solution {
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
// Note: The Solution object is instantiated only once and is reused by each test case.
int total = m + n;
if(0 == total % 2){
return (FindKth(A,m,B,n,total/2) + FindKth(A,m,B,n,total/2+1))/2;
}
else
return FindKth(A,m,B,n,total/2 + 1);
}
double FindKth(int A[],int m ,int B[],int n,int k){
if(m > n) return FindKth(B,n,A,m,k);
if(0 == m) return B[k-1];
if(0 == n) return A[k-1];
if(1 == k) return min(A[0],B[0]);
int Amid = min(k/2,m);
int Bmid = k - Amid;
if(A[Amid-1] < B[Bmid-1])
return FindKth(A+Amid,m-Amid,B,n,k-Amid);
else
return FindKth(A,m,B+Bmid,n-Bmid,k-Bmid);
}
};