牛客网算法学习记录-二分搜索
2016-05-26 19:57
211 查看
定义局部最小的概念。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]是局部最小。
给定无序数组arr,已知arr中任意两个相邻的数都不相等,写一个函数,只需返回arr中任意一个局部最小出现的位置即可。
题意就是存在一个极小值,找到它。
int getLessIndex(vector<int> arr)
{
if(arr.empty())
return -1;
if(arr.size()==1||arr[0]<arr[1])
return 0;
if(arr[arr.size()-1]<arr[arr.size()-2])
return arr.size()-1;
int low=0,high=arr.size()-1,mid,res;
while(low<=high)
{
mid=low+(high-low)/2;
if(arr[mid]<arr[mid+1]&&arr[mid]<arr[mid-1]) //不用担心数组如果是单调递增导致数组越界的情况, 前面已经处理过单侧数组的情况了。
{
res=mid;
break;
}
if(arr[mid]>arr[mid-1])
high=mid-1;
else
low=mid+1;
}
return res;
}
对于一个有序数组arr,再给定一个整数num,请在arr中找到num这个数出现的最左边的位置。
给定一个数组arr及它的大小n,同时给定num。请返回所求位置。若该元素在数组中未出现,请返回-1。
测试样例:
二分搜索:
int findPos(vector<int> arr, int n, int num) {
// write code here
int res = -1;
if( n==1)
return 0;
if( n ==0)
return -1;
int low = 0 ;
int high = arr.size() -1;
int mid ;
while(low<=high){
mid = low + (high - low)/2;
if(arr[mid] == num){
res = mid ;
high = mid -1; //向下移动是因为为升序,找到当前num结点 如果要找到最左边的结点则一定要向下移动。
}
else if(arr[mid]>num){
high = mid - 1;
}
else if (arr[mid]<num){
low = mid +1;
}
}
return res;
}
有一个有序数组arr,其中不含有重复元素,请找到满足arr[i]==i条件的最左的位置。如果所有位置上的数都不满足条件,返回-1。
给定有序数组arr及它的大小n,请返回所求值。
测试样例:
观察到是整形数组,所以元素的增量至少为1,下标差量为1.所以如果arr[0]>n-1 或者arr[n-1]<0存在,则不可能存在arr[i] == i的情况。
假如arr[mid]>mid 那么根据上述条件 high = mid -1 才可能存在 arr[i] ==i
class Find {
public:
int findPos(vector<int> arr, int n) {
// write code here
if(n==0)
return -1;
if(arr[0] > n-1 ||arr[n-1]<0){
return -1;
}
int res=-1;
int low = 0;
int high = n-1;
int mid = low + (high - low)/2;
while(low<=high){ //必须有等于号
if (arr[low] > low || arr[high] < high) {
break;
}
mid = low + (high - low)/2;
if(arr[mid]==mid){
high = mid-1;
res = mid;
}
else if (arr[mid]>mid){
high = mid - 1;
}
else{
low = mid + 1;
}
}
return res;
}
};
6.7
给定一棵完全二叉树的根节点root,返回这棵树的节点个数。如果完全二叉树的节点数为N,请实现时间复杂度低于O(N)的解法。
给定树的根结点root,请返回树的大小。
我有些写不来这种递归函数,参考答案如下。
思路大概是先求二叉树的最大层次,然后分左右子树去看层次是否相同,再根据二叉树结点个数和层次的关系去求解。(可能讲的有些模糊)
如果更快的求一个整数k的n次方。如果两个整数相乘并得到结果的时间复杂度为O(1),得到整数k的N次方的过程请实现时间复杂度为O(logN)的方法。
给定k和n,请返回k的n次方,为了防止溢出,请返回结果Mod 1000000007的值。
测试样例:
思路:将指数部分转换成二进制,那么二进制对应的每位分别为K^1,K^2,K^3...
class QuickPower {
public:
int getPower(int k, int N) {
// write code here
long result = 1;
long k_n = k;
vector<int> binary;
transTenToTwo(binary,N);
for(int i = 0 ;i<binary.size();i++){
if(binary[i] == 1){
result = result *k_n %1000000007;
}
k_n =( k_n *k_n)%1000000007; //防止溢出
}
return result;
}
void transTenToTwo(vector<int> &vec,int num){
while(num>0){
vec.push_back(num%2);
num = num/2;
}
}
};
给定无序数组arr,已知arr中任意两个相邻的数都不相等,写一个函数,只需返回arr中任意一个局部最小出现的位置即可。
题意就是存在一个极小值,找到它。
int getLessIndex(vector<int> arr)
{
if(arr.empty())
return -1;
if(arr.size()==1||arr[0]<arr[1])
return 0;
if(arr[arr.size()-1]<arr[arr.size()-2])
return arr.size()-1;
int low=0,high=arr.size()-1,mid,res;
while(low<=high)
{
mid=low+(high-low)/2;
if(arr[mid]<arr[mid+1]&&arr[mid]<arr[mid-1]) //不用担心数组如果是单调递增导致数组越界的情况, 前面已经处理过单侧数组的情况了。
{
res=mid;
break;
}
if(arr[mid]>arr[mid-1])
high=mid-1;
else
low=mid+1;
}
return res;
}
对于一个有序数组arr,再给定一个整数num,请在arr中找到num这个数出现的最左边的位置。
给定一个数组arr及它的大小n,同时给定num。请返回所求位置。若该元素在数组中未出现,请返回-1。
测试样例:
[1,2,3,3,4],5,3
返回:2
二分搜索:
int findPos(vector<int> arr, int n, int num) {
// write code here
int res = -1;
if( n==1)
return 0;
if( n ==0)
return -1;
int low = 0 ;
int high = arr.size() -1;
int mid ;
while(low<=high){
mid = low + (high - low)/2;
if(arr[mid] == num){
res = mid ;
high = mid -1; //向下移动是因为为升序,找到当前num结点 如果要找到最左边的结点则一定要向下移动。
}
else if(arr[mid]>num){
high = mid - 1;
}
else if (arr[mid]<num){
low = mid +1;
}
}
return res;
}
有一个有序数组arr,其中不含有重复元素,请找到满足arr[i]==i条件的最左的位置。如果所有位置上的数都不满足条件,返回-1。
给定有序数组arr及它的大小n,请返回所求值。
测试样例:
[-1,0,2,3],4
返回:2
观察到是整形数组,所以元素的增量至少为1,下标差量为1.所以如果arr[0]>n-1 或者arr[n-1]<0存在,则不可能存在arr[i] == i的情况。
假如arr[mid]>mid 那么根据上述条件 high = mid -1 才可能存在 arr[i] ==i
class Find {
public:
int findPos(vector<int> arr, int n) {
// write code here
if(n==0)
return -1;
if(arr[0] > n-1 ||arr[n-1]<0){
return -1;
}
int res=-1;
int low = 0;
int high = n-1;
int mid = low + (high - low)/2;
while(low<=high){ //必须有等于号
if (arr[low] > low || arr[high] < high) {
break;
}
mid = low + (high - low)/2;
if(arr[mid]==mid){
high = mid-1;
res = mid;
}
else if (arr[mid]>mid){
high = mid - 1;
}
else{
low = mid + 1;
}
}
return res;
}
};
6.7
给定一棵完全二叉树的根节点root,返回这棵树的节点个数。如果完全二叉树的节点数为N,请实现时间复杂度低于O(N)的解法。
给定树的根结点root,请返回树的大小。
我有些写不来这种递归函数,参考答案如下。
思路大概是先求二叉树的最大层次,然后分左右子树去看层次是否相同,再根据二叉树结点个数和层次的关系去求解。(可能讲的有些模糊)
如果更快的求一个整数k的n次方。如果两个整数相乘并得到结果的时间复杂度为O(1),得到整数k的N次方的过程请实现时间复杂度为O(logN)的方法。
给定k和n,请返回k的n次方,为了防止溢出,请返回结果Mod 1000000007的值。
测试样例:
2,3
返回:8
思路:将指数部分转换成二进制,那么二进制对应的每位分别为K^1,K^2,K^3...
class QuickPower {
public:
int getPower(int k, int N) {
// write code here
long result = 1;
long k_n = k;
vector<int> binary;
transTenToTwo(binary,N);
for(int i = 0 ;i<binary.size();i++){
if(binary[i] == 1){
result = result *k_n %1000000007;
}
k_n =( k_n *k_n)%1000000007; //防止溢出
}
return result;
}
void transTenToTwo(vector<int> &vec,int num){
while(num>0){
vec.push_back(num%2);
num = num/2;
}
}
};
相关文章推荐
- FastBoot BootLoader Recovery 模式解释
- 数据结构 第十章 内部排序简介
- C#函数式编程之标准高阶函数
- LeetCode OJ 59. Spiral Matrix II
- 第二阶段团队项目冲刺站立会议(三)
- PAT 1009 Product of Polynomials
- BZOJ 3698(XWW的难题-上下界网络流+经典建模)
- mybatis系列-06-输入映射
- 关于mac的硬件时间获取
- 第二阶段站立会议04
- mysql的存储引擎如何选择
- PAT 1009 Product of Polynomials
- Excel 导入到Datatable 中,再使用常规方法写入数据库
- js 去掉字符串前后空格
- [Java]工厂模式
- malloc函数详解
- 如何用OpenCV训练自己的分类器
- 实习入职第六天:Android里面的src和background的区别是什么样子的
- 多线程同步几个例子(买票程序的synchronized)
- ASP.NET基本对象的认识