二分查找
1. 在排序数组中查找元素的第一个和最后一个位置
代码实现:
/** * Note: The returned array must be malloced, assume caller calls free(). */ int binarySearch(int *nums, int numsSize, int target) { int l = 0, r = numsSize - 1; while (l <= r) { int mid = (l + r) >> 1; if (nums[mid] == target) { return mid; } else if (nums[mid] > target) { r = mid - 1; } else if (nums[mid] < target) { l = mid + 1; } } return -1; } int* searchRange(int *nums, int numsSize, int target, int *returnSize) { int *res = malloc(sizeof(int) * 2); memset(res, -1, sizeof(int) * 2); *returnSize = 2; if (nums == NULL || numsSize < 1) { return res; } int ind = binarySearch(nums, numsSize, target); if (ind == -1) { return res; } int i, j; for (i = ind - 1; i >= 0; i--) { if (nums[i] != target) { break; } } res[0] = i + 1; for (j = ind + 1; j < numsSize; j++) { if (nums[j] != target) { break; } } res[1] = j - 1; return res; }
2. 搜索插入位置
代码实现:
/* 函数功能:返回有n个元素的数组arr中,找等于key或者第一个比key大的数的下标 */ int binary_search_v1(int *arr, int n, int key) { int head = 0, tail = n - 1, mid; // 左闭右闭 while (head <= tail) { mid = (head + tail) >> 1; if (key > arr[mid]) { head = mid + 1; } else if (key < arr[mid]) { tail = mid - 1; } else if (key == arr[mid]) { return mid; } } return head; } int binary_search_v2(int *arr, int n, int key) { int head = 0, tail = n, mid; // 左闭右开 while (head < tail) { mid = (head + tail) >> 1; if (key > arr[mid]) { head = mid + 1; } else if (key < arr[mid]) { tail = mid; } else if (key == arr[mid]) { return mid; } } return head; } int binary_search_v3(int *arr, int l, int n, int key) { int head = l, tail = n; // 左闭右开 int mid = (head + tail) >> 1; if (head >= tail) { return head; } if (key > arr[mid]) { head = mid + 1; } else if (key < arr[mid]) { tail = mid; } else if (key == arr[mid]) { return mid; } return binary_search_v3(arr, head, tail, key); } int searchInsert(int *nums, int numsSize, int target) { return binary_search_v1(nums, numsSize, target); // return binary_search_v2(nums, numsSize, target); // return binary_search_v3(nums, 0, numsSize, target); }
3. 二分查找
代码实现:
/* 最基本的二分查找 前提:待查找序列是有序的 时间复杂度:O(logn) 以2为底的对数 */ int binary_search_v1(int *arr, int n, int key) { int head = 0, tail = n - 1, mid; // 左闭右闭 while (head <= tail) { mid = (head + tail) >> 1; // 右移 if (arr[mid] == key) { // 找到了 return mid; } if (arr[mid] < key) { // 未找到 head = mid + 1; } else { tail = mid - 1; } } return -1; // 没找到,返回-1 } int binary_search_v2(int *arr, int n, int key) { int head = 0, tail = n, mid; // 左闭右开 while (head < tail) { mid = (head + tail) >> 1; // 右移 if (arr[mid] == key) { // 找到了 return mid; } if (arr[mid] < key) { // 未找到 head = mid + 1; } else { tail = mid; } } return -1; // 没找到,返回-1 } // 递归版本 int binary_search_v3(int *arr, int i, int n, int key) { int head = i, tail = n - 1, mid; // 左闭右闭 // 失败出口 if (head > tail) { return -1; } mid = (head + tail) >> 1; if (arr[mid] == key) { // 找到了 return mid; // 返回待查找数的下标 } if (arr[mid] < key) { // 未找到 head = mid + 1; } else { tail = mid - 1; } return binary_search_v3(arr, head, tail + 1, key); } int search(int *nums, int numsSize, int target) { return binary_search_v1(nums, numsSize, target); // return binary_search_v2(nums, numsSize, target); // return binary_search_v3(nums, 0, numsSize, target); }
4. 寻找比目标字母大的最小字母
代码实现:
int binary_search(char *arr, int n, char key) { int head = 0, tail = n - 1, mid; // 左闭右闭 while (head <= tail) { mid = (head + tail) >> 1; // 右移 if (arr[mid] == key) { // 找到了 return mid; } if (arr[mid] < key) { // 未找到 head = mid + 1; } else { tail = mid - 1; } } return -1; // 没找到,返回-1 } char nextGreatestLetter(char *letters, int lettersSize, char target) { for (char i = target + 1; i <= 'z'; i++) { int ind = binary_search(letters, lettersSize, i); if (ind != -1) { return letters[ind]; } } return letters[0]; }
5.