题目描述
稀疏数组搜索。有个排好序的字符串数组,其中散布着一些空字符串,编写一种方法,找出给定字符串的位置。
示例1:
- 输入: words = [“at”, “”, “”, “”, “ball”, “”, “”, “car”, “”, “”,“dad”, “”, “”], s = “ta”
- 输出:-1
- 说明: 不存在返回-1。
示例2:
- 输入:words = [“at”, “”, “”, “”, “ball”, “”, “”, “car”, “”, “”,“dad”, “”, “”], s = “ball”
- 输出:4
提示:
- words的长度在[1, 1000000]之间
解题思路与代码
- 这道题是一道十足的简单题,我们可以用两种方式去解决它。一种方法是顺序查找元素,那么它的时间复杂度为O(n),另一种就是使用二分法,它的时间复杂度为O(log(n)),n为字符数组中元素的个数。下面就让我们来看看这两种方法各自的实现是什么?
方法一: 顺序查找
很简单,就是一个for循环去比较元素,如果相等,返回下标,如果找不到目标元素,返回 -1。
具体的代码如下:
class Solution {
public:
int findString(vector<string>& words, string s) {
for(int i = 0; i < words.size(); ++i){
if(words[i] == s) return i;
}
return -1;
}
};
复杂度分析
时间复杂度 O(n)
空间复杂度 O(1)
方法二:二分查找
- 我们首先设置两个指针left 与 right,分别指向数组的首元素与尾元素。然后使用while循环去遍历。
- 我们找出数组的中间元素mid,用一个temp遍历去记录此时mid的值。如果mid为空,就while循环遍历mid。++mid。mid < right 是内层for循环的停止条件。这个目的是使中间元素的字符串不为空。
- 假如最后mid 还是为空,我们就缩小right的范围,使right = temp -1;然后跳过此次循环。
- 之后,我们开始进行二分查找与比较操作。这里我们要用到string自带的成员比较函数compare
- 如果word[mid] = s,就直接返回mid。
- 如果word[mid] < s,left = mid + 1;
- 否则right = mid -1;
具体的实现请看代码:
class Solution {
public:
int findString(vector<string>& words, string s) {
int left = 0;
int right = words.size() - 1;
while(left <= right){
int mid = (left + right) / 2;
int temp = mid;
while(words[mid] == "" && mid < right)
++mid;
if(words[mid] == ""){
right = temp -1;
continue;
}
int cmp = words[mid].compare(s);
if(cmp == 0) return mid;
else if(cmp < 0) left = mid + 1;
else right = mid - 1;
}
return -1;
}
};
复杂度分析
首先,我们来分析这段代码的时间复杂度。
-
在最好的情况下,如果目标字符串是中间的元素,时间复杂度为 O(1)。但这不是我们关心的情况,我们需要分析最坏情况和平均情况。
-
在最坏情况下,空字符串的数量可能非常多,导致代码的时间复杂度降低。每次执行循环时,我们可能需要跳过 k 个空字符串,其中 k 是当前区间内的空字符串数量。在最坏情况下,k 可能接近 n/2,这将使时间复杂度变为 O(k * log(n)),即 O(n * log(n))。
-
然而,在平均情况下,空字符串应该较少,时间复杂度应接近 O(log(n))。这是因为二分查找法在平均情况下具有 O(log(n)) 的时间复杂度,而跳过空字符串只会稍微影响性能。
接下来,我们分析空间复杂度。
- 这段代码中,我们只使用了一些辅助变量(如 left、right、mid、temp 和 cmp),而没有使用任何额外的数据结构。因此,空间复杂度为 O(1)。这意味着代码具有很好的空间效率。
总结一下,这段代码在平均情况下的时间复杂度为 O(log(n)),空间复杂度为 O(1)。在最坏情况下,时间复杂度可能会降低,但这取决于空字符串的分布情况。
总结
- 这道题其实可以算是学习二分法或者分治思想的入门题目,还是很有必要去学习和掌握一下的。
- 觉得我写的还行的小伙伴们请给我点一个赞,你们的赞就是对我持续输出优质内容的最大鼓励,谢谢!