LeetCode刷题笔记5
LeetCode 剑指Offer
剑指 Offer 04. 二维数组中的查找
题目描述
在一个n * m
的二维数组中,每一行都按照从左到右 非递减 的顺序排序,每一列都按照从上到下 非递减 的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
实例:
1
2
3
4
5
6
7
8
9
10
11现有矩阵 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
解题思路
解题思路:
直接遍历 —— 时间复杂度
O(nm)
, 空间复杂度O(1)
;每行二分查找 —— 时间复杂度
O(nlogm)
, 空间复杂度O(1)
;Z字查找/二叉排序树 —— 时间复杂度
O(n+m)
, 空间复杂度O(1)
。二叉排序树构建过程,将第一行的最后一列作为二叉树的根节点。
此时,树的左孩子永远比父节点小,右孩子会比父节点大。
遍历过程中,若当前节点的值小于目标值
target
,则遍历该节点的右孩子;当大于target
则遍历左孩子,若相等则返回True
。当i<0或j>=len(matrix)时仍未找到,说明不存在target
,返回False
。 由于是将数组视为二叉树,所以当
i--
的时候,相当于遍历左子树,当j++
时遍历右子树。
实现代码
1 |
|
剑指 Offer 11. 旋转数组的最小数字(简单)
154. 寻找旋转排序数组中的最小值 II(困难)
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2]
为 [1,2,3,4,5]
的一次旋转,该数组的最小值为 1。
注意,数组[a[0], a[1], a[2], ..., a[n-1]]
旋转一次 的结果为数组[a[n-1], a[0], a[1], a[2], ..., a[n-2]]
。
示例
1
2
3
4
5输入:numbers = [3,4,5,1,2]
输出:1
输入:numbers = [2,2,2,0,1]
输出:0提示
n == numbers.length
1 <= n <= 5000
-5000 <= numbers[i] <= 5000
numbers
原来是一个升序排序的数组,并进行了1
至n
次旋转
解题思路
调用API….. min,sorted…[当然不给用] 时间复杂度
O(n)
二分查找 时间复杂度
O(logn)
使用左右指针l,r记录首位位置,m为中间位置。
最小值一定在右排序数组中。
当
nums[m]<nums[r]
,说明此时m一定是在右排序数组中,因此l = m + 1
,在m的右边继续搜索;当
nums[m]>nums[r]
,说明此时m一定在左排序数组中,因此r = m
, 在m的左边搜索;当
nums[m]==nums[r]
,无法判断m在哪一边,但是此时可以缩小数组的范围,令r = r - 1
,此操作可能导致旋转点被去除,但是去除旋转点同时可以理解为在一个没有进行旋转的数组进行搜索,所以r=r-1
操作可行。
==为什么不能与左侧端点l进行比较呢?==
原因在于: r的初始位置一定是在右排序数组中,而l的初始位置无法确定在哪个排序数组中
代码实现
1 |
|
剑指 Offer 50. 第一个只出现一次的字符
题目描述
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例
1
2
3
4
5输入:s = "abaccdeff"
输出:'b'
输入:s = ""
输出:' '提示
0 <= s 的长度 <= 50000
解题思路
- hash map
代码实现
1 |
|