这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
剑指Offer 03.数组中重复的数字
找出数组中重复的数字。
在一个长度为n的数组nums里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
限制:
2 <= n <= 100000
题解
法一 哈希表
通过题意,我们可以使用哈希表来实现,分析如下:
- 遍历数组,若当前数字不存在于哈希表,则添加到哈希表即可。
- 若当前数字哈希表中已存在,则返回结果。
var findRepeatNumber = function(nums){
let map = new Map();
for(let i of nums){
if(map.has(i)){
return i;
}
map.set(i,1);
}
return null;
}
-
空间复杂度:O(n)
-
时间复杂度:O(n)
法二 原地交换
剑指Offer中的解法,空间复杂度O(1) 时间复杂度O(n)
因为在一个长度为n点数组nums里的所有数字都在0~n-1的范围内,所以数组元素的索引和值是一对多的关系,因此可以建立索引和值的映射,起到字典等价的作用。
思路:
- 从头到尾依次扫描,如果当前项和下标不相等,则比较当前项和以当前项对应的下标的项是否相等,不相等则交换位置
- for循环中有一个while,但是由于每一项最多只会在while中交换两次,所以总体的时间复杂度仍然是O(n)
var findRepeatNumber = function(nums) {
for(let i = 0;i < nums.length;i++){
let num = nums[i];
while(num !== i){
if(nums[i] === nums[num]){
return num
}
nums[i] = nums[num]
nums[num] = num
}
}
return null
};
- 时间复杂度:O(n)
- 空间复杂度:O(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。
限制:0 <= n <= 1000; 0 <= m <= 1000
题解
法一 坐标轴法
根据题意知,二维数组从左往右递增,从上往下递增,则:
- 某列的某个数字,该数之上的数字,都比其小;
- 某行的某个数字,该数右侧的数字,都比其大;
所以,解题流程如下:
- 以二维数组左下角为原点,建立直角坐标轴。
- 若当前数字大于了查找数,查找往上移一位。
- 若当前数字小于了查找树,查找往右移一位。
如果target = 19,则路径为:18->21->13->14->17->24->22->19
var findNumberIn2DArray = function(matrix,target){
if(!matrix.length) return false;
let x = matrix.length-1 , y = 0;
while(x>=0 && y< matrix[0].length){
if(matrix[x][y] === target){
return true;
}else if(matrix[x][y] > target){
x--;
}else{
y++;
}
}
return false;
}
法二 数组降维法
将二维数组扁平化,再看其是否包含目标值。
var findNumberIn2DArray = function(matrix,target){
return matrix.flat(Infinity).includes(target);
}