[剑指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)。
这里使用循环写法。

代码

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

原文地址:https://www.cnblogs.com/coding-gaga/p/10449579.html

时间: 2024-08-27 12:03:36

[剑指Offer]53-在排序数组中查找数字(二分查找)的相关文章

剑指offer:在排序数组中查找数字

题目: 统计一个数字在排序数组中出现的次数. 例如输入排序数组{1,2,3,3,3,3,4,5},由于3在这个数中出现了4次,输出4. # -*- coding: utf-8 -*- # @Time : 2019-07-13 15:10 # @Author : Jayce Wong # @ProjectName : job # @FileName : getNumberOfK.py # @Blog : https://blog.51cto.com/jayce1111 # @Github : ht

剑指offer——56在排序数组中查找数字

题目描述 统计一个数字在排序数组中出现的次数. 题解: 使用二分法找到数k然后向前找到第一个k,向后找到最后一个k,即可知道有几个k了 但一旦n个数都是k时,这个方法跟从头遍历没区别,都是O(N)的复杂度 可以再次利用二分法,在第一次找到k的左半部分使用二分法找到不再出现k的位置,其右半部份类似. 1 class Solution01 { 2 public: 3 int GetNumberOfK(vector<int> data, int k) { 4 if (data.size() == 0

【剑指offer】二维数组中的查找

题目描述: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 分析: 首先选择数组中右上角的数字.如果该数字等于要查找的数字,查找过程结束:如果该数字大于要查找的数字,剔除这个数字所在的列:如果该数字小于要查找的数字,剔除这个数字所在的行.依次类推,直到查找范围为空. 示例程序: #include <stdio.h> #include <stdlib.h> int

剑指OFFER之二维数组中的查找(九度OJ1384)

题目描述: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的矩阵的行数和列数. 输入的第二行包括一个整数t(1<=t<=1000000):代表要查找的数字. 接下来的m行,每行有n个数,代表题目所给出的m行n列的矩阵(矩阵如题目描述所示,每

【剑指offer】Q29:数组中出现次数超过一半的数字

就本题而言,个人觉得练习下partition函数是有必要的,毕竟它是快速排序的核心,是基础性的东西,也是必须要掌握的,至于书中给出的"取巧"性解法,是属于个人思维能力的考察,是一种考虑问题的思路,不是一两个问题就能练就的. partition函数,包括快速排序,是一定要信手拈来的,必须的. import random def MoreThanHalf(array): if len(array) == 0: return 0 start = 0 end = len(array) - 1

【剑指offer】Q40:数组中出现一次的数字

按着书里面讲述的方法,根据某一位来将整个数组拆分成两个部分,取每一部分中出现一次的数.书中的处理略显复杂,这里简化下分类的方法. def once(array): reOR = 0 for x in array: reOR ^= x bit1 = firstBit1(reOR) first = 0 second = 0 for x in array: if x & bit1 != 0: first ^= x else: second ^= x return first, second def f

【剑指offer】Q40:数组中出现一次的数

书里面关于分类的判断有些麻烦,通过某一位为0为1来对数组元素进行分类.假如第3位为1,那么也就是元素x & 8 等于或不等于0,所以没必要非的用第几位去判断. def once(array): reOR = 0 for x in array: reOR ^= x bit1 = firstBit1(reOR) first = 0 second = 0 for x in array: if x & bit1 != 0: first ^= x else: second ^= x return f

[剑指Offer]5.二维数组中的查找

题目 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 思路 [算法系列之三十三]杨氏矩阵 代码 /*--------------------------------------- * 日期:2015-07-19 * 作者:SJF0115 * 题目: 5.二维数组中的查找 * 网址:http://www.nowcoder.com/books/coding-interviews/a

剑指Offer--038-数字在排序数组中出现的次数

链接 牛客OJ:数字在排序数组中出现的次数 九度OJ:http://ac.jobdu.com/problem.php?pid=1349 GitHub代码: 038-数字在排序数组中出现的次数 CSDN题解:剑指Offer–038-数字在排序数组中出现的次数 牛客OJ 九度OJ CSDN题解 GitHub代码 038-数字在排序数组中出现的次数 1505-数字在排序数组中出现的次数 剑指Offer–038-数字在排序数组中出现的次数 038-数字在排序数组中出现的次数 题意 题目描述 统计一个数字

《剑指Offer 1.二维数组中的查找》2019-03-25

剑指Offer  第一题 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 本人简单的解题思路  就是通过二重循环,遍历.查找数组中是否有目标数字,思路是简单的,但是有个小坑 ,就是没有进行数组越界判断 少判断了  array = [ [ ] ] 这种情况,最终通过的代码为 public class Solution { public bool