面试题 10.05. 稀疏数组搜索(C++)
题目
稀疏数组搜索。有个排好序的字符串数组,其中散布着一些空字符串,编写一种方法,找出给定字符串的位置。
示例1:
输入: words = ["at", "", "", "", "ball", "", "", "car", "", "","dad", "", ""], s = "ta"
输出:-1
说明: 不存在返回-1。
示例2:
输入:words = ["at", "", "", "", "ball", "", "", "car", "", "","dad", "", ""], s = "ball"
输出:4
提示:
- words的长度在[1, 1000000]之间
分析与题解
暴力遍历
在考虑输入数组为空的情况后,从头便利整个数组,知道找到匹配的字符串并返回下标,否则返回-1。
class Solution {
public:
int findString(vector<string>& words, string s) {
int len = words.size();
if(len==0){
return -1;
}
for(int i=0;i<len;i++){
if(words[i]==s)
return i;
}
return -1;
}
};
二分查找法
相对于普通二分查找,还需要注意如下几点:
- left 和right可能对应的是空字符串,还需要人为的判断并缩小边界。
- 计算出的mid可能对应的也是空值。这里的策略是将mid向右偏,直到不为空或者接触到右边界:如果到达右边界,说明mid和right这一段全为空字符串,没有目标元素。所以将right更新为最初的mid即可。
具体代码如下:
class Solution {
public:
int findString(vector<string>& words, string s) {
int len = words.size();
if(len==0){
return -1;
}
int left=0,right=len-1;
while(left<=right){
//先排除左右边界是空字符串的情况
//因为按ASCII码排序不包含空字符串
if(words[left].size()==0){
left++;
continue;
}
if(words[right].size()==0){
right--;
continue;
}
int mid = (left + right)/2;
//排除mid也是空字符串的情况
while(words[mid].size()==0){
mid++;
if(mid==right){
//说明mid到right之间没有我们想要的答案
if(words[right]==s)
return right;
//将right更新为初始的mid
right = (left + right)/2;
continue;
}
}
//经过上层删选的mid肯定不为空字符串
if(words[mid]==s)
return mid;
else if(words[mid]>s)
right = mid - 1;
else
left = mid + 1;
}
return -1;
}
};