# 基础知识

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) {
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

int indexSearch(int *array, int left, int right) {
if (left > right) {
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.

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

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

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 矩阵搜索

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;
}

## 6 Range search

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;
}

## 7 Search a 2D Matrix

https://leetcode.com/problems/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]
]
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int left = 0;
int right = matrix.size() * matrix[0].size() - 1;

while (left <= right) {

int middle = left + ((right - left) >> 1);
int row = middle / matrix[0].size();
int col = middle % matrix[0].size();

if (target == matrix[row][col]) {
return true;
} else if (target < matrix[row][col]) {
right = middle - 1;
} else {
left = middle + 1;
}

}

return false;
}
};

## 8 Find Peak Element

https://leetcode.com/problems/find-peak-element/

A PEAK element is an element that is greater than its neighbors.

Given an input array where num[i] ≠ num[i+1], find a peak element and return its index.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

You may imagine that num[-1] = num[n] = -∞.

For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

class Solution {
public:
int findPeakElement(vector<int>& nums) {
int len = nums.size();
if (len == 1) {
return 0;
}

if (nums[0] > nums[1]) {
return 0;
}

if (nums[len - 1] > nums[len - 2]) {
return len - 1;
}

int left = 1;
int right = len - 2;
int mid;
// 只要没有都排除完，就继续循环
while (left <= right) {
mid = left + ((right - left) >> 1);
if (nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1])
{
return mid;
} else if (nums[mid] > nums[mid + 1]) { // 降序
right = mid - 1;
} else if (nums[mid] < nums[mid + 1]) { // 升序
left = mid + 1;
}
}
}
};

## 9 Remove Duplicates from Sorted Array

http://www.lintcode.com/en/problem/remove-duplicates-from-sorted-array/

class Solution {
public:
/**
* @param A: a list of integers
* @return : return an integer
*/
int removeDuplicates(vector<int> &nums) {
int len = nums.size();
if (len <= 1) {
return len;
}

int fast = 1;
int slow = 0;
while (fast < len) {
if (nums[slow] != nums[fast]) {
nums[++slow] = nums[fast];
}
++fast;
}
return slow + 1;
}
};

## 10 Remove Duplicates from Sorted Array II

http://www.lintcode.com/zh-cn/problem/remove-duplicates-from-sorted-array-ii/

class Solution {
public:
/**
* @param A: a list of integers
* @return : return an integer
*/
int removeDuplicates(vector<int> &nums) {
int len = nums.size();
if (len <= 1) {
return len;
}

int fast = 1;
int slow = 0;
int dup;
/**
* 思路：在没有重复时，以及重复一次时，数组需要刷新
*/
while (fast < len) {
if (nums[slow] != nums[fast]) {
nums[++slow] = nums[fast];
dup = 0;
} else {
++dup;
if (dup < 2) {
nums[++slow] = nums[fast];
}
}
++fast;
}

return slow + 1;
}
};

## 11 求两个排序数组的交集

Intersection of 2 sorted array

example

array1: [2 3 4 6]
array2: [3 6 9 10]
return [3,6]

Algorithm Intersection(arr1[], arr2[]):
For Intersection of two arrays, print the element only if the element is present in both arrays.
1) Use two index variables i and j, initial values i = 0, j = 0
2) If arr1[i] is smaller than arr2[j] then increment i.
3) If arr1[i] is greater than arr2[j] then increment j.
4) If both are same then print any of them and increment both i and j.

Time Complexity: O(m+n)

#include <iostream>
#include <vector>
using namespace std;

// 求两个排序数组的交集
vector<int> findIntersection(const vector<int> &A, const vector<int> &B) {
vector<int> res;

int len1 = A.size();
int len2 = B.size();
int i = 0;
int j = 0;

while (i < len1 && j < len2) {
if (A[i] == B[j]) {
res.push_back(A[i]);
i++;
j++;
} else if (A[i] < B[j]) {
i++;
} else {
j++;
}
}

return res;
}

int main(int argc, const char *argv[]) {
vector<int> A = { 1, 2, 3, 4, 5, 9 };
vector<int> B = { 2, 4, 5, 6, 9 };
vector<int> intersection = findIntersection(A, B);

for (const auto &elem : intersection) {
cout << elem << " ";
}
cout << endl;

system("pause");
}

## 12 求两个排序数组的并集

http://www.geeksforgeeks.org/union-and-intersection-of-two-sorted-arrays-2/

For example, if the input arrays are:
arr1[] = {1, 3, 4, 5, 7}
arr2[] = {2, 3, 5, 6}
Then your program should print Union as {1, 2, 3, 4, 5, 6, 7}

Algorithm Union(arr1[], arr2[]):
For union of two arrays, follow the following merge procedure.
1) Use two index variables i and j, initial values i = 0, j = 0
2) If arr1[i] is smaller than arr2[j] then print arr1[i] and increment i.
3) If arr1[i] is greater than arr2[j] then print arr2[j] and increment j.
4) If both are same then print any of them and increment both i and j.
5) Print remaining elements of the larger array.

Time Complexity: O(m+n)

#include <iostream>
#include <vector>
using namespace std;

// 求两个排序数组的并集
vector<int> findUnion(const vector<int> &A, const vector<int> &B) {
vector<int> res;

int len1 = A.size();
int len2 = B.size();
int i = 0;
int j = 0;

while (i < len1 && j < len2) {
if (A[i] < B[j]) {
res.push_back(A[i]);
i++;
} else if (B[j] < A[i]) {
res.push_back(B[j]);
j++;
} else if (A[i] == B[j]) {
res.push_back(A[i]);
i++;
j++;
}
}

while (i < len1) {
res.push_back(A[i]);
i++;
}

while (j < len2) {
res.push_back(B[j]);
j++;
}

return res;
}

int main(int argc, const char *argv[]) {
vector<int> A = { 1, 2, 3, 4, 5, 9 };
vector<int> B = { 2, 4, 5, 6, 9 };
vector<int> intersection = findUnion(A, B);

for (const auto &elem : intersection) {
cout << elem << " ";
}
cout << endl;

system("pause");
}

## 13 Merge Sorted Array

https://leetcode.com/problems/merge-sorted-array/

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1and nums2 are m and n respectively.

/**
* 注意：两个指针分别指向nums1和nums2的末尾，是为了防止破坏nums1原先的元素
*/
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = m - 1;
int j = n - 1;
int pos = m + n;
while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) {
nums1[--pos] = nums1[i--];
} else if (nums2[j] > nums1[i]) {
nums1[--pos] = nums2[j--];
} else {
nums1[--pos] = nums1[i--];
nums1[--pos] = nums2[j--];
}
}

/*
这句不写也是OK的，因为其实该数组的元素已经在正确的位置上了，不用重复拷贝
while (i >= 0) {
nums1[--pos] = nums1[i--];
}
*/

while (j >= 0) {
nums1[--pos] = nums2[j--];
}
}
};

## 14 Merge k Sorted Lists

https://leetcode.com/problems/merge-sorted-array/

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

/**
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/

struct cmp {
bool operator() (const ListNode *lhs, const ListNode *rhs) {
if (lhs->val < rhs->val) {
return false;
} else {
return true;
}
}
};

class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode *, vector<ListNode *>, cmp> heap;

for (int i = 0; i < lists.size(); i++) {
if (lists[i]) {
heap.push(lists[i]);
}
}

ListNode *dummyNode = new ListNode(0);
ListNode *cur = dummyNode;
while (!heap.empty()) {
cur->next = heap.top();
heap.pop();

cur = cur->next;
if (cur->next) {
heap.push(cur->next);
}
}

return dummyNode->next;
}
};

999

999

999

posted @ 2015-08-04 20:00  Acjx  阅读(1087)  评论(0编辑  收藏  举报