二分查找的巧妙运用(C++)
来源:互联网 发布:电子音乐制作软件 编辑:程序博客网 时间:2024/05/16 09:08
一、二分查找
1、查找无序数组中的任意一个局部最小值
局部最小值:arr长度为1时,arr[0]是局部最小。arr的长度为N(N>1)时,如果arr[0]<arr[1],那么arr[0]是局部最小;如果arr[N-1]<arr[N-2],那么arr[N-1]是局部最小;如果0<i<N-1,既有arr[i]<arr[i-1]又有arr[i]<arr[i+1],那么arr[i]是局部最小。
解法:二分查找。先查看左右两边是不是局部最小。都不是则局部最小一定在中间,于是查看mid处是不是,若不是则局部最小要么在其左边要么在其右边,判断出在左边还是在右边,继续二分查找即可。
class
Solution {
public
:
int
getLessIndex(vector<
int
> arr) {
int
length = arr.size();
if
(length ==
0
)
return
-
1
;
if
(length ==
1
)
return
0
;
if
(arr[
0
] < arr[
1
])
return
0
;
if
(arr[length-
1
] < arr[length-
2
])
return
length-
1
;
int
start =
0
,end = length-
1
;
int
mid = (start+end)/
2
;
while
(
1
) {
if
(arr[mid] < arr[mid+
1
] && arr[mid] < arr[mid-
1
])
return
mid;
else
if
(arr[mid] > arr[mid-
1
]) {
end = mid;
mid = (start+end)/
2
;
}
else
{
start = mid;
mid = (start+end)/
2
;
}
}
}
};
2、对于一个有序数组arr,再给定一个整数num,请在arr中找到num这个数出现的最左边的位置
解法:二分查找。要注意当arr[mid]大于或等于num时都要转向左半部查找。查找停止条件很重要。
class
LeftMostAppearance {
public
:
int
findPos(vector<
int
> arr,
int
n,
int
num) {
int
res = -
1
;
int
start =
0
,end = n-
1
;
int
mid = (start+end)/
2
;
while
(start <= end) {
if
(arr[mid] < num) {
start = mid+
1
;
}
else
if
(arr[mid] == num) {
res = mid;
end = mid-
1
;
}
else
{
end = mid-
1
;
}
mid = (start+end)/
2
;
}
return
res;
}
};
有序循环数组:1,2,3,4,5 2,3,4,5,1 3,4,5,1,2 4,5,1,2,3 5,1,2,3,4
解法:①判断最左和最右的关系。确定数组是有序的还是循环过的。
②判断最左和中间的关系。确定最小值位于左半部还是右半部。
③最左大于中间,在左半部,end = mid;最左小于或等于中间,在右半部,但是start的更新不同,小于时 start=mid,等于时start=mid+1.
int getMin(vector<int> arr, int n) {
if (n == 0) {
return -1;
}
int start = 0,end = n-1;
int mid = start + (end-start)/2;
if (arr[start] < arr[end]) {
return arr[start];
}
else if (arr[start] > arr[end]) {
while (start != end) {
if (arr[start] > arr[mid]) {
end = mid;
}
else if(arr[start] < arr[mid]){
start = mid;
}
else {
start = mid+1;
}
mid = start + (end-start)/2;
}
return arr[start];
}
else {
int min = arr[start];
for (int i = 0;i < n;i++) {
if (arr[i] < min)
min = arr[i];
}
return min;
}
}
};
解法:直接判断mid是否满足,arr[mid] >= mid都说明只有左半部有可能出现满足条件的元素,arr[mid] < mid说明只有右半部有可能。
5、统计完全二叉树的结点总数
class
Find {
public
:
int
findPos(vector<
int
> arr,
int
n) {
int
res = -
1
;
if
(n ==
0
)
return
res;
int
start =
0
,end = n-
1
;
int
mid = -1
;
if
(arr[start] == start)
return
start;
while
(start <= end) {
mid = start + (end-start)/
2
if
(arr[mid] == mid) {
res = mid;
end = mid-1;
}
else
if
(arr[mid] > mid)
end = mid-1;
else
start = mid +
1
;
}
return
res;
}
};
要求:时间复杂度低于O(N)。
解法:二分查找。
①先遍历到二叉树左子树最左边的结点和右子树最左边的结点,统计左右子树的深度。
②若左右子树深度相同,说明左子树是满二叉树,若左子树深度大于右子树深度,说明右子树是满二叉树。
③递归地进行上述过程。
class
CountNodes {
public
:
int
count(TreeNode* root) {
if
(!root)
return
0
;
int
leftDepth =
0
,rightDepth =
0
;
TreeNode *leftL = root,*rightL = root;
while
(leftL || rightL) {
if
(leftL) {
leftDepth++;
leftL = leftL->left;
}
if
(rightL) {
rightDepth++;
if
(rightL == root)
rightL = rightL->right;
else
rightL = rightL->left;
}
}
if
(leftDepth == rightDepth) {
return
count(root->right) + pow(
2
,leftDepth-
1
);
}
else
return
count(root->left) + pow(
2
,rightDepth-
1
);
}
};
6、快速幂算法
要求:求整数k的N次方的过程请实现时间复杂度为O(logN)的方法。
解法:N的二进制表示完美地划分了求幂的过程,二进制有多少位基数base就计算多少次,每一次求base都等于上一次的base的平方,将二进制中为1的位对应的基数base乘起来就是最后的结果。
class
QuickPower {
public
:
int
getPower(
int
k,
int
N) {
long
res=
1
;
long
base=k;
while
(N){
if
(N&
1
)
res=res*base%
1000000007
;
base=base*base%
1000000007
;
N>>=
1
;
}
return
res;
}
};
7、矩阵的快速幂
应用:计算斐波那契数列。
http://www.cnblogs.com/vongang/archive/2012/04/01/2429015.html
推荐博文:
二叉树相关练习题(C++)
经典排序算法的C++实现
与字符串有关的一些典型问题的C++解法
一些可以用动态规划(DP)算法解决的问题(C++)
排列组合相关笔试面试题(C++)
与概率相关的算法题C++解法(附证明过程)
位运算在算法题中的使用(C++)
链表相关练习题(C++)
用实例讲解栈和队列(C++)
一些智力题的C++解法
1 0
- 二分查找的巧妙运用(C++)
- HOJ 2615 Pie ---------------二分查找的运用
- hdu 4970(数组的巧妙运用)
- 数组的巧妙运用
- 【编程珠玑】第二章 二分查找的巧妙应用
- 【编程珠玑】第二章 二分查找的巧妙应用
- 二分查找(c)
- 二分查找(c & c++)
- C语言实现折半查找(二分查找)的算法
- 【C/C++】折半查找(二分查找)
- Site指令的巧妙运用
- 位运算的巧妙运用
- 巧妙的运用Floyd算法
- 位运算的巧妙运用
- android权重的巧妙运用
- 三元表达式的巧妙运用
- 线性查找,二分查找(C语言版)
- C语言 折半查找(二分查找)
- s3c6410中断处理
- SGU 126 Boxes(数论)
- Apkplug 模块化开发介绍
- Matrix Game(尼姆博弈)
- 二叉树中序遍历(递归+非递归)
- 二分查找的巧妙运用(C++)
- Python条件语句
- JavaScript核心对象参考手册-------window对象
- Ping过程 原理 详解(图)
- 物联网开源平台KAA
- php魔术常量,魔术方法
- 遗传算法优化BP神经网络
- Android webview 地图不显示
- Pku oj 1218 THE DRUNK JAILER(开灯问题)