程序员面试金典 - 面试题 10.05. 稀疏数组搜索

题目难度: 简单

原题链接

今天继续更新程序员面试金典系列, 大家在公众号 算法精选 里回复 面试金典 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

稀疏数组搜索。有个排好序的字符串数组,其中散布着一些空字符串,编写一种方法,找出给定字符串的位置。

示例 1:

  • 输入: words = [“at”, “”, “”, “”, “ball”, “”, “”, “car”, “”, “”,“dad”, “”, “”], s = “ta”
  • 输出:-1
  • 说明: 不存在返回-1。

示例 2:

  • 输入:words = [“at”, “”, “”, “”, “ball”, “”, “”, “car”, “”, “”,“dad”, “”, “”], s = “ball”
  • 输出:4

提示:

  • words 的长度在[1, 1000000]之间

题目思考

  1. 如何利用数组有序这一条件?

解决方案

思路
  • 解决有序数组搜索问题, 一个很自然的想法就是二分查找
  • 但这个题目略有不同, 因为会存在一些空字符
  • 如果区间中点字符不是空字符, 则可以根据它和 s 的大小关系, 决定向左还是向右查找, 这里和传统二分一样
  • 那如果区间中点字符恰好是空字符, 该如何处理呢?
  • 此时我们只能依次查找左右两个区间了, 左边如果找到目标字符就不再继续, 否则继续查找右边
  • 这也限制了需要采用递归来实现二分, 递归二分需要注意递归出口, 即起点大于终点的情况, 此时肯定找不到, 返回-1
  • 下面的代码就对应了上面的整个过程, 并且有详细的注释, 方便大家理解
复杂度
  • 时间复杂度 O(N): 空字符不多的情况下时间复杂度接近传统二分, 即 O(logN); 最差情况(所有字符串都是空)下, 需要遍历每个字符串一遍, 此时复杂度为O(N)
  • 空间复杂度 O(logN): 递归栈的消耗
代码
class Solution:
    def findString(self, words: List[str], s: str) -> int:
        def find(b, e):
            if b > e:
                # 递归出口, 起点大于终点, 肯定找不到, 返回-1
                return -1
            m = (b + e) >> 1
            if words[m] == "":
                # 当前中点字符是空, 需要依次查找左右区间
                l = find(b, m - 1)
                # 左边找到后就直接返回, 不再继续查找右区间
                return l if l != -1 else find(m + 1, e)
            elif words[m] == s:
                return m
            elif words[m] < s:
                return find(m + 1, e)
            else:
                return find(b, m - 1)

        return find(0, len(words) - 1)

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值