LeetCode刷题-稀疏数组搜索

该博客介绍了如何在有序且包含空字符串的数组中使用二分查找法寻找目标字符串。文章详细阐述了针对空字符串的特殊处理,即遇到空字符串时,中间指针会向左或向右移动,直到找到非空字符串或达到边界。通过这种方法,实现了对有序字符串数组的高效搜索。最终给出的解决方案在执行时间和空间效率上表现优秀。
摘要由CSDN通过智能技术生成

前言说明

算法学习,日常刷题记录。

题目连接

稀疏数组搜索

题目内容

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

示例1:

输入: words = [“at”, “”, “”, “”, “ball”, “”, “”, “car”, “”, “”,“dad”, “”, “”], s = “ta”

输出:-1

说明: 不存在返回-1。

示例2:

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

输出:4

说明:

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

分析过程

因为字符串数组是有序的,使用二分查找法来解决。

字符串比较大小通过字符串的compareTo方法来实现,compareTo方法传递的参数就是要比较的字符串。

当结果小于0时,当前字符串比参数中的字符串小。

当结果等于0时,当前字符串等于参数中的字符串。

当结果大于0时,当前字符串比参数中的字符串大。

但是这里有空字符串,当二分查找遇到空字符串时,无法判断下一步,这里需要对二分查找进行调整,如下:

遇到空字符串,中间指针往左移动,直到不为空字符串或者大于左指针,结束循环;或者中间指针往右移动,直到不为空字符串或者小于右指针,结束循环。

第一步

定义中间指针center。

定义左指针left,初始为0。

定义右指针right,初始为字符串数组words的最后下标。

第二步

开始二分查找,进行while循环,直到左指针left大于右指针right,结束while循环。

第三步

每次while循环时:

1、计算中间指针center,中间指针center = (左指针left + 右指针right) / 2,除以2可以用位运算>>1来代替。

2、当二分查找遇到了特殊值导致无法继续时,就临时退化为线性遍历。这里存在空字符串,当遇到空字符串时,中间指针center向左移动,直到不为空字符串或者大于左指针left,结束循环。

3、开始判断给定字符串s符合哪种情况:

若给定字符串s等于字符串数组words中间指针center的元素,那么找到了目标值,返回中间指针center,结束程序。

若给定字符串s小于字符串数组words中间指针center的元素,那么目标值落在字符串数组words的前半部分,把右指针right更新为中间指针center减1,继续while循环,直到左指针left大于右指针right,结束while循环,结束程序。

若给定字符串s大于字符串数组words中间指针center的元素,那么目标值落在字符串数组words的后半部分,把左指针left更新为中间指针center加1,继续while循环,直到左指针left大于右指针right,结束while循环,结束程序。

第四步

若结束while循环也没有找到给定字符串s,那么返回-1,结束程序。

解答代码

class Solution {
    public int findString(String[] words, String s) {
        // 因为字符串数组是有序的,可以通过修改二分查找法来解决
        // 遇到空字符串,中间指针往左移动,直到不为空字符串或者大于左指针,结束循环;或者中间指针往右移动,直到不为空字符串或者小于右指针,结束循环

        // 定义中间指针
        int center;
        // 定义左指针
        int left = 0;
        // 定义右指针
        int right = words.length - 1;

        // 二分查找,进行循环,直到左指针大于右指针,结束循环
        while (left <= right) {
            // 计算获取中间指针,可以用位运算向右移动1位来代替除以2
            center = (left + right) >> 1;

            // 当遇到了特殊值导致正常的二分无法继续时,就临时退化为线性遍历
            // 当遇到空字符串,中间指针向左移动,直到不为空字符串或者大于左指针,结束循环(这里和二分查找法不同,其他地方一模一样)
            while (center > left && "".equals(words[center])) {
                --center;
            }

            if (s.equals(words[center])) {
                // 若给定字符串等于字符串数组中间指针的元素,那么找到了目标值,返回中间指针
                return center;
            } else if (s.compareTo(words[center]) < 0) {
                // 字符串的compareTo()方法用于两个字符串的比较,按字典顺序比较两个字符串
                // 若给定字符串小于字符串数组中间指针的元素,那么目标值落在字符串数组的前半部分,把右指针更新为中间指针减1
                right = center - 1;
            } else {
                // 若给定字符串大于字符串数组中间指针的元素,那么目标值落在字符串数组的后半部分,把左指针更新为中间指针加1
                left = center +1;
            }
        }

        // 若没有找到给定字符串,返回-1
        return -1;
    }
}

提交结果

执行用时0ms,时间击败100.00%的用户,内存消耗38.1MB,空间击败90.86%的用户。

运行结果

原文链接

原文链接:稀疏数组搜索

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值