[剑指Offer]53-在排序数组中查找数字(二分查找)
题目一 数字在排序数组中出现的个数
题目描述
统计一个数字在排序数组中出现的次数。
解决思路
写两个二分查找分别找第一个和最后一个该数字,然后可直接出计算有几个该数字。时间复杂度为O(logn)。
这里使用二分查找的递归写法,形式可以写得更简洁(见书)。
当输入不符合规则返回-1。注意形参len表示原始数组的长度,在此题目中是必要的。注意特殊输入的处理。
代码
#include <iostream>
using namespace std;
int findFirstK(int* num,int len,int k,int beg,int end){
if(beg>end){
return -1;
}
int midIndex=(beg+end)/2;
int midNum=num[midIndex];
if(k<midNum){
return findFirstK(num, len, k, beg, midIndex-1);
}
else if(k>midNum){
return findFirstK(num, len, k, midIndex+1, end);
}
else{
if(midIndex==0||(midIndex>0&&num[midIndex-1]!=k)){
return midIndex;
}
else{
return findFirstK(num, len, k, beg, midIndex-1);
}
}
}
int findLastK(int*num,int len,int k,int beg,int end){
if(beg>end){
return -1;
}
int midIndex=(beg+end)/2;
int midNum=num[midIndex];
if(k<midNum){
return findLastK(num, len, k, beg, midIndex-1);
}
else if(k>midNum){
return findFirstK(num, len, k, midIndex+1, end);
}
else{
if(midIndex==len-1||(midIndex<len-1&&num[midIndex+1]!=k)){//此处需要原始数组的长度len
return midIndex;
}
else{
return findLastK(num, len, k, midIndex+1, end);
}
}
}
int getKCnt(int *num,int len,int k,int beg,int end){
if(num==nullptr||len<0){
return -1;
}
int cnt = 0;
int fistKIndex=findFirstK(num, len, k, beg, end);
int lastKIndex=findLastK(num, len, k, beg, end);
if(fistKIndex!=-1&&lastKIndex!=-1){
cnt=lastKIndex-fistKIndex+1;
}
return cnt;
}
int main(int argc, const char * argv[]) {
int num[]={1,2,3,4,4,4,5,6};
int len=sizeof(num)/sizeof(int);
int k=4;
int kCnt=getKCnt(num, len, k, 0, len-1);
cout<<"The count of K is:"<<kCnt<<endl;
return 0;
}
题目二 0-n-1中缺失的数字
题目描述
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0-n-1之内。在范围0-n-1内的n个数字中有且只有一个数字不在该数组中,找出这个数字。
解决思路
用二分查找找到数组中第一个树枝和下标不相等的下标,即是缺失数字。时间复杂度为O(logn)。
这里使用递归写法,使用循环写法形式更简洁。
相关知识
当数组不是有序时,可以利用数字0-n-1之和n*(n-1)/2减去 遍历数组得到的数组元素之和,即是缺失数字。由于遍历数组时间复杂度为O(logn),所以总时间复杂度为O(logn)。
代码
#include <iostream>
using namespace std;
int findMissNum(int* num,int beg,int end){
if(num==nullptr||end-beg<0){
return -1;
}
int midIndex=(beg+end)/2;
int midNum=num[midIndex];
if(midNum==midIndex){
return findMissNum(num, midIndex+1, end);
}
else if(midNum>midIndex){
if(midIndex==0||num[midIndex-1]==midIndex-1){//注意
return midIndex;
}
else{
return findMissNum(num, beg, midIndex-1);
}
}
else{
return -1;
}
}
int main(){
// int num[]={0,1,2,3,4,6,7};
int num[]={1};
int missNum=findMissNum(num, 0, sizeof(num)/sizeof(int)-1);
cout<<"The missing number is:"<<missNum<<endl;
return 0;
}
题目三 数组中数值和下标相等的元素
题目描述
假设一个单调递增数组里的每个元素都是整数且唯一。找出数组中任意一个数值等于其下标的元素。
解决思路
二分查找。时间复杂度为O(logn)。
关于细节很好的
这里使用循环写法。
二分查找的细节 第一个ok,第二、三个还需仔细理解。
参考链接 https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-zhao-xiang-jie-by-labuladong/





C++代码
#include <iostream>
using namespace std;
int findK(int* num,int len){
if(num==nullptr||len<=0){
return -1;
}
int l=0;
int r=len-1;
while(l<=r){
int midIndex=(l+r)>>1;
int midNum=num[midIndex];
if(midNum==midIndex){
return midNum;
}
else if(midNum>midIndex){
r=midIndex-1;
}
else{
l=midIndex+1;
}
}
return -1;
}
int main(){
int num[]={-1,0,2,3,4,5,6};
// int num[]={0};
int K=findK(num, sizeof(num)/sizeof(int));
cout<<"One of the number which is equal to its index is:"<<K<<endl;
return 0;
}
Java代码
class Solution {
public int search(int[] nums, int target) {
if(nums==null){
return -1;
}
int l=0;
int r=nums.length-1;
while(l<=r){
int mid=(l+r)/2;
if(nums[mid]==target){
return mid;
}
else if(nums[mid]<target){
l=mid+1;
}
else{
r=mid-1;
}
}
return -1;
}
}
[剑指Offer]53-在排序数组中查找数字(二分查找)的更多相关文章
- 剑指offer——56在排序数组中查找数字
题目描述 统计一个数字在排序数组中出现的次数. 题解: 使用二分法找到数k然后向前找到第一个k,向后找到最后一个k,即可知道有几个k了 但一旦n个数都是k时,这个方法跟从头遍历没区别,都是O(N) ...
- 剑指Offer - 九度1348 - 数组中的逆序对
剑指Offer - 九度1348 - 数组中的逆序对2014-01-30 23:19 题目描述: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个 ...
- 剑指offer:二维数组中的查找
目录 题目 解题思路 具体代码 题目 题目链接 剑指offer:二维数组中的查找 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺 ...
- 剑指Offer - 九度1370 - 数组中出现次数超过一半的数字
剑指Offer - 九度1370 - 数组中出现次数超过一半的数字2013-11-23 03:55 题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组 ...
- 剑指Offer - 九度1351 - 数组中只出现一次的数字
剑指Offer - 九度1351 - 数组中只出现一次的数字2013-11-23 01:23 题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. ...
- 剑指 Offer 04. 二维数组中的查找 (思维)
剑指 Offer 04. 二维数组中的查找 题目链接 本题的解法是从矩阵的右上角开始寻找目标值. 根据矩阵的元素分布特性, 当目标值大于当前位置的值时将row行号++,因为此时目标值一定位于当前行的下 ...
- 《剑指offer》 二维数组中的查找
本题目是<剑指offer>中的题目 二维数组中的查找 题目: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个 ...
- 【Java】 剑指offer(3) 二维数组中的查找
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上 ...
- [剑指Offer]5.二维数组中的查找
题目 在一个二维数组中,每一行都依照从左到右递增的顺序排序,每一列都依照从上到下递增的顺序排序.请完毕一个函数,输入这种一个二维数组和一个整数.推断数组中是否含有该整数. 思路 [算法系列之三十三]杨 ...
- 《剑指Offer 1.二维数组中的查找》2019-03-25
剑指Offer 第一题 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数 ...
随机推荐
- 机器学习进阶-图像基本操作-边界补全操作 1.cv2.copyMakeBoder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REPLICATE) 进行边界的补零操作 2.cv2.BORDER_REPLICATE(边界补零复制操作)...
1.cv2.copyMakeBoder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REPLICATE) 参数说明: i ...
- HBase 入门
使用条件: 海量数据百亿级的行 百万列, 准实时查询 使用场景: 比如金融,交通,电商,移动等 特点: 1:
- cxgrid合并值相同的某列
设置 cxGrid 的某列的 CellMerging 属性可使这一列相同值的单元格合并. 1)cxGridDBTableViewColumn1.Options.CellMerging:=true 2 ...
- python语言中的数据类型之元组
数据类型 元组 tuple 元组:不可变类型 用途:元组就是一个不可变的列表,当需要存不改动的值时可用元组 定义方式:在()内用逗号分隔开多个任意类型的元素 t=(1,2.2,'aa',( ...
- Cobbler自动化工具实践
1.Cobbler Install 安装前准备 /*注:Cobbler需安装在CentOS7机器上面,建议安装Cobbler机器的CentOS7 everything版本*/ 关闭SELinux c ...
- 在postgresqlz中查看与删除索引
查看索引 select * from pg_indexes where tablename='tbname'; 或者 select * from pg_statio_all_inde ...
- Linux sort命令使用方法
sort命令在Linux中主要用于对文件进行排序,并将排序结果输出.sort命令输入可以是指定的文件和数据流.本文主要介绍sort命令的基本语法和常见使用实例. sort命令语法 sort命令格式:s ...
- 手工获取AWR报告
AWR(Automatic Workload Repository)报告常用于Oracle数据库性能分析.熟练解读AWR报告有助于快速分析Oracle性能问题.下面主要描述如何手工获取AWR报告. 操 ...
- 传输层——TCP报文头介绍
16位源端口号 16位目的端口号 32位序列号 32位确认序列号 4位头部长度 保留6位 U R G A C K P S H R S T S Y N F I N 16位窗口大小 16位检验和 16位紧 ...
- reids遇到问题
今天重启爬虫服务器在连接redis数据库时突然报错:MISCONF Redis is configured to save RDB snapshots, but it is currently not ...