文章目录
- 1、[剑指 Offer 04. 二维数组中的查找](https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/)
- 2、[剑指 Offer 11. 旋转数组的最小数字](https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/)
- 3、[剑指 Offer 50. 第一个只出现一次的字符](https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof/)
1、剑指 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。
思路(参考题解)
从左下角开始遍历,i表示行,j表示列。i从最大行开始遍历(matrix.length - 1),如果目标值<当前值,说明该行大于目标值,因为是行递增的;j从第0列开始遍历,如果目标值>当前值,说明该行后面可能有满足条件的值,列方向往后移。找到满足条件的值返回true
public class findNumberIn2DArray {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
//(从左下角开始)i:行 j:列
int i = matrix.length - 1, j = 0;
while (i >= 0 && j < matrix[0].length) {
//如果目标值<当前值,说明该行大于目标值,因为是行递增的
if (target < matrix[i][j]) {
i --;
//如果目标值>当前值,说明该行后面可能有满足条件的值,列方向往后移
} else if (target > matrix[i][j]) {
j ++;
} else {
//找到目标值,返回true
return true;
}
}
return false;
}
}
2、剑指 Offer 11. 旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1
思路:
暴力解法:遍历查找最小值
public int minArray(int[] numbers) {
//暴力解法
int res = numbers[0];
for (int i = 1; i < numbers.length; i ++) {
if (numbers[i] < res) {
res = numbers[i];
}
}
return res;
}
二分法
最小值元素一定在右排序数组中,因此通过二分法找到右排序数组,其中首位就是最小值。本题使用j与mid的值进行比较,从而缩小区间,不能用i,因为当mid>i时,无法判断mid在哪个排序数组中 ,如果与j比较,j肯定在右排序数组中。
public int minArray2(int[] numbers) {
//二分法
//旋转数组 最小值肯定在右排序数组
int i = 0, j = numbers.length - 1;
while (i < j) {
int mid = (i + j) / 2;
//mid在左排序数组中
if (numbers[mid] > numbers[j]) {
i = mid + 1;
//mid在右排序数组中
} else if(numbers[mid] < numbers[j]) {
j = mid;
} else {
j --;
}
}
return numbers[i];
}
}
3、剑指 Offer 50. 第一个只出现一次的字符
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例 1:
输入:s = “abaccdeff”
输出:‘b’
思路:哈希表
先将字符串转为字符数组,第一次遍历,如果该字符是第一次出现,添加键值对dic(c,true),如果不是第一次出现,则添加键值对dic(c,false);第二次遍历,查找第一个值为true的字符,找到返回字符。如果没有,返回空格。
public class firstUniqChar {
public char firstUniqChar2(String s) {
//参考题解 哈希表
//dic(c,true)
HashMap<Character, Boolean> dic = new HashMap<Character, Boolean>();
char[] sc = s.toCharArray();//字符串转为字符数组
//第一次遍历,将所有字符添加到map
for (char c : sc) {
//如果map中不包含字符c,第一次出现,添加键值对dic(c,true)
if (! dic.containsKey(c)) {
dic.put(c, true);
} else {
//如果包含了字符c,说明重复出现,添加键值对dic(c,false)
dic.put(c, false);
}
}
//第二次遍历,返回map中的第一个值
for (char c : sc) {
//dic.get(c)为true,说明只出现了1次,返回
if (dic.get(c)) {
return c;
}
}
return ' ';
}
}