查找算法
Offer 04 二维数组中的查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
解题思路
若使用暴力法遍历矩阵 matrix ,则时间复杂度为 O(NM) 。暴力法未利用矩阵 “从上到下递增、从左到右递增”的特点,显然不是最优解法。
如下图所示,我们将矩阵逆时针旋转 45° ,并将其转化为图形式,发现其类似于二叉搜索树,即对于每个元素,其左分支元素更小、右分支元素更大。因此,通过从 “根节点” 开始搜索,遇到比 target 大的元素就向左,反之向右,即可找到目标值 target 。
算法流程
- 从矩阵 matrix 左下角元素(索引设为 (i, j) )开始遍历,并与目标值对比:
- 若行索引或列索引越界,则代表矩阵中无目标值,返回 false 。
每轮 i 或 j 移动后,相当于生成了“消去一行(列)的新矩阵”, 索引(i,j) 指向新矩阵的左下角元素(标志数),因此可重复使用以上性质消去行(列)。
Python代码如下:
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
#左下角初始化i,j
i, j = len(matrix) - 1, 0
#从左下角开始遍历
while i >= 0 and j < len(matrix[0]):
#若matrix[i][j]大于目标值,则向上移动一个
if matrix[i][j] > target: i -= 1
#若matrix[i][j]小于目标值,则向右移动一个
elif matrix[i][j] < target: j += 1
#若matrix[i][j]等于目标值,则返回True
else: return True
#若行索引或列索引越界,则代表矩阵中无目标值,返回 false
return False
作者:jyd
来源:力扣(LeetCode)
Offer 11 旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
解题思路
如下图所示,寻找旋转数组的最小元素即为寻找 右排序数组 的首个元素 numbers[x] ,称 x 为 旋转点 。
排序数组的查找问题首先考虑使用二分法解决
算法流程
Python代码如下:
class Solution:
def minArray(self, numbers: List[int]) -> int:
#初始化i j,分别指向 numbers 数组左右两端
i, j = 0, len(numbers)-1
while i < j:
#取中间值
m = (i+j) // 2
#若numbers[m] > numbers[j],m一定在左排序数组中,即旋转点x一定在 [m + 1, j]
if numbers[m] > numbers[j]: i = m + 1
#若numbers[m] < numbers[j],m一定在右排序数组中,即旋转点x一定在 [m, j]
elif numbers[m] < numbers[j]: j = m
#相等的话执行 j = j - 1 缩小判断范围
else: j -= 1
#当 i = j 时跳出二分循环,并返回旋转点的值 nums[i] 即可
return numbers[i]
作者:jyd
来源:力扣(LeetCode)
Offer 50 第一个只出现一次的字符
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
解题思路
1.遍历字符串 s ,使用哈希表统计 “各字符数量是否 >1 ”
2.再遍历字符串 s ,在哈希表中找到首个 “数量为 1 的字符”,并返回
算法流程
- 初始化: 字典记为 dic ;
- 遍历字符串 s 中的每个字符 c:
1.若 dic 中 不包含 键(key) c :则向 dic 中添加键值对 (c, True) ,代表字符 c 的数量为 1 ;
2.若 dic 中 包含 键(key) c :则修改键 c 的键值对为 (c, False) ,代表字符 c 的数量 >1 。 - 查找数量为 1 的字符: 遍历字符串 s 中的每个字符 c ;
1.若 dic中键 c 对应的值为 True ,则返回 c 。 - 返回 ’ ',代表字符串无数量为 1 的字符。
Python代码如下:
class Solution:
def firstUniqChar(self, s: str) -> str:
#初始化dic字典
dic = {}
#遍历字符串s的每个字符
for c in s:
#not c in dic 整体为一个布尔值; c in dic 为判断字典中是否含有键 c
dic[c] = not c in dic
for c in s:
#遍历中出现首位直接返回c
if dic[c]: return c
#如果没有,返回一个单空格
return ' '
作者:jyd
来源:力扣(LeetCode)