力扣剑指Offer 第5天 查找算法(中等) 剑指 Offer 04. 二维数组中的查找 剑指 Offer 11. 旋转数组的最小数字 剑指 Offer 50. 第一个只出现一次的字符
剑指 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。
思路
原本我想从中间开始搜索,类似二分一样的去处理,但是这样考虑将会非常复杂。
但是如果从某个角落开始,利用每一个方向都有着变大或变小的固定规则来进行二分选择,高效率又简单编写。
这个角落只能是左下角或右上角(符合一个方向递增一个方向递减的规则),利用这个规则利用当前位置的值与target比较,如果相等说明存在,大于则往递减方向移动,小于则往递增方向移动,如果移动到了边界还没有找到target则说明不存在。
代码
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if(matrix.length==0)return false;//特判是否为空
int rows = matrix.length,cols = matrix[0].length;
int r=rows-1,c=0;
while(r>=0&&r<rows&&c>=0&&c<cols){
if(matrix[r][c]>target)r--;
else if(matrix[r][c]<target)c++;
else return true;
}
return false;
}
}
☆剑指 Offer 11. 旋转数组的最小数字
题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [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
思路(比较难!)
- 判断是否旋转了(首元素与末尾元素比大小即可)
- 如果没有旋转(首元素<末尾元素)return numbers[0]
- 如果旋转了(首元素>末尾元素)二分搜索 (numbers[m]与number[r]比较 小则往左 大则往右)
- if(numbers[m]<number[r])r=m
- if(numbers[m]>number[r])l=m+1
- if(number[m]==number[r])r=r-1
为什么与number[r]比较?
[已旋转]由上述思路可知,当到达第3步的时候可以确定是已经旋转的数组。
以下是numbers[m]==numbers[r]后r—的所有情况
- [001|0] 跳跃转折点 -> [001|] 此时 numbers[r]为左边最大值 一直向左 找到最小值
- [1111]全部相同 一直r–直到 最左
- [0001|00] 最后会转向情况1
- [1111|011]最后会转向情况5
- [11|01] 未跳跃转折点
从以上可知r–1不会影响判断的内容
代码
class Solution {
public int minArray(int[] numbers) {
if(numbers.length==1)return numbers[0];//只有一个数
int l=0,r=numbers.length-1,m;
if(numbers[0]<numbers[r])return numbers[0];//没有旋转(加快判断)
while(l<r){
m=(l+r)>>1;
if(numbers[m]<numbers[r])r=m;
else if(numbers[m]>numbers[r])l=m+1;
else r--;
}
return numbers[l];
}
}
剑指 Offer 50. 第一个只出现一次的字符
思路
用set来判断是否已经是第一次出现该字符
- 如果是第一次出现则向动态数组后面添加该字符
- 不是第一次则删除动态数组中的该字符(没有则啥也不发生)
代码
class Solution {
public char firstUniqChar(String s) {
Set<Character> set=new HashSet<>();
ArrayList<Character> a=new ArrayList<>();
int len = s.length();
for(int i=0;i<len;i++){
Character c = s.charAt(i);
if(!set.contains(c)){
set.add(c);
a.add(c);
}else a.remove(c);
}
if(!a.isEmpty())return a.get(0);
return ' ';
}
}
本文介绍剑指Offer中的三道查找题:二维数组中的查找、旋转数组的最小数字及第一个只出现一次的字符。提供了详细的解题思路与代码实现。
517

被折叠的 条评论
为什么被折叠?



