剑指 Offer 04. 二维数组中的查找
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5
,返回 true
。
给定 target = 20
,返回 false
。
限制:
0 <= n <= 1000
0 <= m <= 1000
思路流程:
- 从矩阵 matrix 左下角元素(索引设为 (i, j) )开始遍历,并与目标值对比:
- 当
matrix[i][j] > target
时,执行 i - 1 ,即消去第 i 行元素; - 当
matrix[i][j] < target
时,执行 j + 1 ,即消去第 j 列元素; - 当
matrix[i][j] = target
时,返回 true ,代表找到目标值。
- 当
- 若行索引或列索引越界,则代表矩阵中无目标值,返回 false。
- 每轮 i 或 j 移动后,相当于生成了“消去一行(列)的新矩阵”, 索引(i,j) 指向新矩阵的左下角元素(标志数),因此可重复使用以上性质消去行(列)。
复杂度分析:
时间复杂度 O(M+N) :其中,N 和 M 分别为矩阵行数和列数,此算法最多循环 M+N 次。
空间复杂度 O(1) : i, j 指针使用常数大小额外空间。
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
i, j = len(matrix) - 1, 0
while i >= 0 and j < len(matrix[0]):
if matrix[i][j] > target: i -= 1
elif matrix[i][j] < target: j += 1
else: return True
return False
剑指 Offer 11. 旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复元素值的数组 numbers
,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2]
为 [1,2,3,4,5]
的一次旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1
示例 2:
输入:[2,2,2,0,1]
输出:0
思路流程:
- 初始化: 声明 i, j 双指针分别指向 nums 数组左右两端;
- 循环二分: 设 m = (i + j) / 2 为每次二分的中点( “/” 代表向下取整除法,因此恒有 i<=m<j ),可分为以下三种情况:
- 当 nums[m] > nums[j]时: m 一定在 左排序数组 中,即旋转点 x 一定在 [m + 1, j] 闭区间内,因此执行 i = m + 1;
- 当 nums[m] < nums[j] 时: m 一定在 右排序数组 中,即旋转点 x 一定在[i, m] 闭区间内,因此执行 j=m;
- 当 nums[m] = nums[j] 时: 无法判断 mm 在哪个排序数组中,即无法判断旋转点 x 在 [i, m]还是 [m + 1, j] 区间中。解决方案: 执行 j = j - 1 缩小判断范围,分析见下文。
- 返回值: 当 i = j 时跳出二分循环,并返回 旋转点的值 nums[i] 即可。
class Solution:
def minArray(self, numbers: [int]) -> int:
i, j = 0, len(numbers) - 1
while i < j:
m = (i + j) // 2
if numbers[m] > numbers[j]: i = m + 1
elif numbers[m] < numbers[j]: j = m
else: return min(numbers[i:j])
return numbers[i]
面试题50. 第一个只出现一次的字符
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例 1:
输入:s = "abaccdeff"
输出:'b'
示例 2:
输入:s = ""
输出:' '
算法流程:
- 初始化: 初始化一个字典 ,记为 dic ;
- 字符统计: 遍历字符串 s 中的每个字符 c ;
- 若 dic 中 不包含 键(key) c :则向 dic 中添加键值对 (c, True) ,代表字符 c 的数量为 11 ;
- 若 dic 中 包含 键(key) c :则修改键 c 的键值对为 (c, False) ,代表字符 c 的数量 > 1>1 。
- 查找数量为 11 的字符: 遍历字符串 s 中的每个字符 c ;
- 若 dic中键 c 对应的值为 True :,则返回 c 。
- 返回 ’ ’ ,代表字符串无数量为 11 的字符。
class Solution:
def firstUniqChar(self, s: str) -> str:
dic = {}
for c in s:
dic[c] = not c in dic
for c in s:
if dic[c]: return c
return ' '