剑指offer 【查找】

统计一个数字在排序数组中出现的次数

输入: nums = [5,7,7,8,8,10], target = 8
输出: 2

  • hash字典的方法,第一次遇见简历一个key,默认值为1
  • 后续遇见该key,value += 1
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        all_num = dict()
        for i in nums:
            if i not in all_num:
                all_num[i] = 1
            else:
                all_num[i] += 1
        if target in all_num:
            return all_num[target]
        return 0

数组中重复的数字

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
输入:[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3

  • 建立一个集合all_num用于无序、不重复储存数字
  • 如果不在集合里,add; 如果集合中已存在,即为重复数
class Solution:
    def findRepeatNumber(self, nums: List[int]) -> int:
        all_num = set()
        for i in nums:
            if i not in all_num:
                all_num.add(i)
            else:
                return i

0~n-1中缺失的数字

  • 通过数学公式解决,0~n-1求和 - 实际和
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        length = len(nums)
        sum_exp = (1+length)*length//2
        sum_ac = sum(nums)
        return sum_exp - sum_ac

二维数组中的查找

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。


image.png
  • 利用二维数组的特性,仿二叉树进行操作
  • 旋转,从右上角开始便利,index依次左右移动
class Solution:
    def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
        if matrix:
            r = 0
            c = len(matrix[0]) - 1
            while r < len(matrix) and c >= 0 :
                flag = matrix[r][c]
                if flag == target:
                    return True
                elif flag > target:
                    c -= 1
                else:
                    r += 1
            return False
        else:
            return False

旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。
输入:[3,4,5,1,2]
输出:1
输入:[2,2,2,0,1]
输出:0

  • 简单遍历,遇见second < first 即为找到最小值 second
class Solution:
    def minArray(self, numbers: List[int]) -> int:
        if len(numbers):
            first = 0
            second = 1
            while second < len(numbers):
                if numbers[first] > numbers[second]:
                    return numbers[second]
                else:
                    first += 1
                    second += 1
            return numbers[0]
  • 二分法查找
  • 通过比较mid和right的关系,分为三种情况:
  • 若 mid < right,说明当前 mid~right这部分为单调递增,即最小值应该在当前mid左侧,更新right指针位置 = mid


    image.png
  • 若 mid> right,说明mid~right部分肯定包含最小值,更新left指针为mid + 1


    image.png
  • 若存在 mid == right,无法判定,因此右侧指针依次左移;
class Solution:
    def minArray(self, numbers: List[int]) -> int:
        # 初始化边界指针
        left = 0
        right = len(numbers) - 1 
        while right > left:
            mid = left + (right-left) // 2
            if numbers[mid] > numbers[right]:
                # 5 6 7【10】11 1 min 3.  --->10>3
                #           11 1 min 3
                left = mid + 1
            elif numbers[mid] < numbers[right]:
                # 10 11 12 2【3】4 6 8   --->3<8
                # 10 11 12 2【3】
                right = mid
            else:
                # 正常右侧指针左移 (可能存在重复元素)
                # 10 7【10】10 10
                # 10 7 10 10 
                right -= 1
        return numbers[left]

第一个只出现一次的字母

在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
输入:s = "abaccdeff"
输出:'b'

遍历一次构建字典,再便利一次输出第一个key=1的字母

  • 其中生成计数字典也可以使用 frequency = collections.Counter(s)
class Solution:
    def firstUniqChar(self, s: str) -> str:
        if not s:
            return " "
        all_char = dict()
        for char in s:
            if char in all_char:
                all_char[char] += 1
            else:
                all_char[char] = 1
        for char in s:
            if all_char[char] == 1:
                return char
        return " "

有序哈希表

  • 使用 collections.OrderedDict() 简历有序哈希表,避免第二次遍历字符串
  • 直接遍历 dic.items(),如果v=1,return k

哈希表存索引

  • key = char, value = index
  • 如果出现重复的, value赋值为 -1
  • 遍历keys,存下最小的无重复char的index
class Solution:
    def firstUniqChar(self, s: str) -> str:
        positions = dict()
        length = len(s)
        for i in range(length):
            char = s[i]
            # 如果已经存在,那就返回-1(必不是要找的那个)
            if char in positions:
                positions[char] = -1
            else:
                positions[char] = i
        first = length # 取不到这个值的,index最大值为length-1
        for pos in positions.values():
            if pos != -1 and pos < first:
                # pos != -1: pos没有重复出现
                # pos < first:比当前记录的idnex小,即为第一个出现的非重复
                first = pos 
        return ' ' if first == length else s[first]
        # first == n 即为没找到只出现一次的字符
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容