剑指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       : https://github.com/SysuJayce

def getFirstK(data, k):
    start, end = 0, len(data) - 1
    while start <= end:
        mid = (start + end) >> 1
        if data[mid] == k:
            # 关键在于,如果mid是k,那么就判断前一个元素是不是也是k,如果是,说明这个位置不是
            # 第一次出现,要在左边继续查找。否则,直接返回mid,因为是第一次出现了
            if mid - 1 >= start and data[mid - 1] == k:
                end = mid - 1
            else:
                return mid
        elif data[mid] < k:
            start = mid + 1
        else:
            end = mid - 1

    return -1

def getLastK(data, k):
    start, end = 0, len(data) - 1
    while start <= end:
        mid = (start + end) >> 1
        if data[mid] == k:
            if mid + 1 <= end and data[mid + 1] == k:
                start = mid + 1
            else:
                return mid
        elif data[mid] < k:
            start = mid + 1
        else:
            end = mid - 1

    return -1

def getNumberOfK(data, k):
    """
    要获取一个有序数组中某个元素出现的次数,最直观的做法就是遍历整个数组,然后统计该元素的出现次数,
    这样做的时间复杂度是O(n)

    但是由于这个数组是有序的,我们可以考虑利用二分查找的方法来解决这个问题。
    如果我们先利用二分查找定位到了这个元素,然后再往前往后遍历,这样的话时间复杂度也还是O(n)。

    但是如果我们在利用二分查找的时候,想办法定位这个元素第一次出现的下标和最后一次出现的下标。
    在利用二分查找找到一个这个元素之后,判断这个元素是否是第一个,也就是对比这个元素的前一个是否也
    是k,如果不是,说明这个元素就是第一个元素,否则在这个下标的左边继续查找。
    对于最后一次出现的下标同理。
    """
    if not data:
        return 0
    first = getFirstK(data, k)
    last = getLastK(data, k)
    if first != -1 and last != -1:
        return last - first + 1
    else:
        return 0

def main():
    data = [1, 2, 3, 3, 3, 3, 4, 5]
    k = 3
    print(getNumberOfK(data, k))

if __name__ == ‘__main__‘:
    main()

原文地址:https://blog.51cto.com/jayce1111/2419950

时间: 2024-08-06 17:18:58

剑指offer:在排序数组中查找数字的相关文章

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

题目一 数字在排序数组中出现的个数 题目描述 统计一个数字在排序数组中出现的次数. 解决思路 写两个二分查找分别找第一个和最后一个该数字,然后可直接出计算有几个该数字.时间复杂度为O(logn). 这里使用二分查找的递归写法,形式可以写得更简洁(见书). 当输入不符合规则返回-1.注意形参len表示原始数组的长度,在此题目中是必要的.注意特殊输入的处理. 代码 #include <iostream> using namespace std; int findFirstK(int* num,in

剑指Offer——在特殊数组中查找某数

问题:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断该数组中是否含有该整数.比如:在如下二维数组中查找是否有7,若存在,则返回true,否则,返回false. 1 2 8 9 2 4 9 12 4 7 10 13 6 8 11 15 此时,也许我们第一时间看到这个问题会很兴奋,想当然的觉得,如此简单的问题,何必在此浪费时间,不就是进行一次遍历数组嘛..但是再细细的想一想,面试官也不是等闲之辈,不会拿

【剑指offer】旋转数组中的最小值

题目总结: 1.若没有进行旋转,或者说旋转后的效果跟没有旋转是一样的,那么index1指示的值小于index2指示的值,返回index1的值. 2.若是一般性的旋转,那么最小的值旋转后肯定在中间,那么我们就可以从两边向中间夹逼. 3.夹逼的过程中,若 [ index1, middle ] 是有序的,说明这部分子区间没被破坏,旋转所移动的元素都在middle 的后面,那么最小值可定也在后面的部分,令 index1 = middle,继续向后夹逼:同理,若 [ middle ,index2 ] 是有

【剑指offer】旋转数组的最小数字

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 分析描述: 求一个数组中的最小值,最简单的办法就是逐个比较数组中各个元素的值,遍历完整个数组,即可得数组中最小元素.但这种方法存在的问题是时间复杂度为O(n). 利用题目中给出的条件:递增排序数组的旋转.利用递增排序的特点,可以用二分查找方法实现时间复杂度为O(logn)的查找.

剑指OFFER之旋转数组的最小数字(九度OJ1386)

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入的第一行为一个整数n(1<= n<=1000000):代表旋转数组的元素个数. 输入的第二行包括n个整数,其中每个整数a的范围是(1<=a<=10000000). 输出: 对应每个测试案例, 输出旋转数组

剑指Offer:旋转数组的最小数字【11】

剑指Offer:旋转数组的最小数字[11] 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. 解题分析 我们用两个坐标,Left,Right分别表示左右两个递增序列的下标,刚开始L为0,R为4: 当Arr[Mid]>Arr[Left],可以说明,Mid及左边构

剑指Offer 11. 旋转数组的最小数字

12345678910111213141516171819202122232425262728293031323334353637383940414243 public class { public int minNumberInRotateArray(int[] array) { int index1 = 0; int index2 = array.length - 1; int indexMid = 0; if (array.length == 0) { return 0; } while

【剑指Offer】面试题53 - I. 在排序数组中查找数字 I

题目 统计一个数字在排序数组中出现的次数. 示例 1: 输入: nums = [5,7,7,8,8,10], target = 8 输出: 2 示例?2: 输入: nums = [5,7,7,8,8,10], target = 6 输出: 0 限制:0 <= 数组长度 <= 50000 本题同[LeetCode]34. 在排序数组中查找元素的第一个和最后一个位置 思路 代码 时间复杂度:O(logn) 空间复杂度:O(1) class Solution { public: int search

剑指Offer对答如流系列 - 数组中数字出现的次数

面试题56:数组中数字出现的次数 题目描述 问题(1)数组中只出现一次的两个数字 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 问题(2)数组中唯一只出现一次的数字 在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次.请找出那个只出现一次的数字. 问题分析 问题(1)分析 在这篇文章剑指Offer对答如流系列 - 二进制中 1 的个数中,我们详细探讨了位运算,其中有重要的一条:两个相同的数异