稀疏数组搜索
稀疏数组搜索。有个排好序的字符串数组,其中散布着一些空字符串,编写一种方法,找出给定字符串的位置。
示例1:
输入: words = [“at”, “”, “”, “”, “ball”, “”, “”, “car”, “”, “”,“dad”, “”, “”], s = “ta”
输出:-1
说明: 不存在返回-1。
示例2:
输入:words = [“at”, “”, “”, “”, “ball”, “”, “”, “car”, “”, “”,“dad”, “”, “”], s = “ball”
输出:4
此题是二分搜索的变种。在写好了二分搜索的大体代码后, 需要思考的是如何处理这些空格。
如下是不考虑正常的二分搜索
left = 0
right = len(words) - 1
while left <= right:
mid = left + (right - left) // 2
// 其中,如果这里的mid对应的字符正好是空格怎么办???
if words[mid] == s:
return mid
elif words[mid] > s:
right = mid - 1
else:
left = mid + 1
考虑到mid处可能是空格, 那么很自然就想到了,将mid向前或向后移动,直到找到了不为空格的字符。 我在做此题时,由于考虑了前后两种情况,反而没有处理的很好。后来发现只需要在一个方向上压缩查找区间即可。
如下,向右压缩区间。
# 不断的向右寻找不为空的字符
while mid <= right and words[mid] == "": # 注意先判断mid是否小于right,否则可能words[mid]越界
mid += 1
那么循环结束后,mid要么大于right, 要么mid处字符不为空。 如果大于right的情况,则将right赋值为原mid值。 如果不为空,则走正常的二分查找。如下
# 如果此时mid大于right,则说明右边都是空格。
if mid > right:
right = originMid - 1
# 此处结束循环。
continue
此时,left与right就在各种条件下不断的缩小,直到查找到字符或无区间可查。 完整代码如下:
def findString(self, words: List[str], s: str) -> int:
left = 0
right = len(words) - 1
while left <= right:
mid = left + (right - left) // 2
originMid = mid
# 不断的向右压缩空间
while mid <= right and words[mid] == "":
mid += 1
# 如果此时mid大于right,则说明右边都是空格
if mid > right:
right = originMid - 1
# 这个很重要
continue
if words[mid] == s:
return mid
elif words[mid] > s:
right = mid - 1
else:
left = mid + 1
return -1
如果采取向左移动mid来找不为空的字符,则完整代码如下:
def findString(self, words: List[str], s: str) -> int:
left = 0
right = len(words) - 1
while left <= right:
mid = left + (right - left) // 2
originMid = mid
# 不断的向左压缩空间
while mid >= left and words[mid] == "":
mid -= 1
# 如果此时mid小于left,则说明左边都是空格
if mid < left:
left = originMid + 1
continue
if words[mid] == s:
return mid
elif words[mid] > s:
right = mid - 1
else:
left = mid + 1
return -1