一:剑指 Offer 03. 数组中重复的数字
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例 1:
输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3
限制:
2 <= n <= 100000
题解:数组中某些数字是重复的,那么我们可以知道,在java集合中有HashSet可以存储元素,并且其特点包括:无序,
不可重复,无索引。那么这道题就比较简单了:上代码:
class Solution {
public int findRepeatNumber(int[] nums) {
HashSet <Integer> set =new HashSet<Integer>();//使用HashSet ,保证去重
//hashSet 底层 hash表 数组 链表 红黑树
//特点:无序 不可重复 无索引
int m=0;
for(int num :nums){
if(!set.add(num)){
m=num;
}
}
return m;
}
}
HashSet的底层原理:是基于HashMap实现的,默认初始容量是16,负载因子为0.75的HashMap(实际上是只保有值的HashMap),扩容时乘以2。
二:剑指 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
题解:
(1)暴力法:实际上就是二维数组遍历找到目标值,然后返回。
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
//两次循环 遍历找到特殊值
for(int[] raw :matrix ){
for(int i : raw){
if(i==target){
return true;
}
}
}
return false;
}
}
(2)可以采用二分法,查找目标值。 每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。采用二分查找的关键是要有序,只要在每一行使用二分查找就可以,只用一层循环。
//第二种解法
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
//利用二分查找
for(int[] raw : matrix){//先把一维数组取出来
int index=Seach(raw,target,0,raw.length-1);
if(index>=0){
return true;
}
}
return false;
}
//二分查找 递归方法
public static int Seach(int[] raw,int target,int low,int high){
int middle=(low+high)/2;//确定中点
if(low<=high){//
if(target==raw[middle]){
return middle;//我要返回的是具体的数组下标,在0到raw.length-1中间
}else if(raw[middle]>target){//在左侧
high=middle-1;
return Seach(raw,target,low,high);
}else if(raw[middle]<target){
//在右侧
low=middle+1;
return Seach(raw,target,low,high);
}
}
return -1;
}
}
(3)从大神学到的:
m*n二维数组arr[m][n]可以把它认为是一张m*n的表,那么我们可以从题目中发现每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
那么如果从左下角开始: (注意数组下标从零开始)
如果target<arr[i][j] 那么这一整行都比它大,自然target就不在这一行,i--换到上一行(根据红字)
如果target>arr[i][j],那么这一列都比它小,自然target就不再这一列,j++换到右列
例如:如下图
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
int i = matrix.length - 1;
int j = 0;
while (i >= 0 && j < matrix[0].length) {
if (matrix[i][j] > target) {
i--;
} else if (matrix[i][j] < target) {
j++;
} else {
return true;
}
}
return false;
}
}