01、数组中重复的数字
- 题目描述
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
- 解题思路
遍历数组,每次遇到索引为 i 的新数字 nums[i] 时,将其交换至索引为 nums[i] 的 nums[nums[i]] 处。而当遍历遇到一个重复数字 x 时,一定有 nums[x] == x (因为第一次遇到 x 时已经将其交换至 nums[x] 处了)。利用以上方法,即可得到一组重复数字。
- 代码实现
let findRepeatNumber = function(nums) {
// 遍历数组 nums ,设索引初始值为 i = 0
let i = 0;
while(i < nums.length){
//若 nums[i] == i 说明此数字已在对应索引位置,无需交换
if(nums[i] == i) {
i++;
continue;
}
//若 nums[nums[i]] == nums[i] 说明索引 nums[i] 处的元素值也为 nums[i]
if(nums[nums[i]] == nums[i]) return nums[i];
//交换索引为 i 和 nums[i] 的元素值,将此数字交换至对应索引位置
let tmp = nums[i];
nums[i] = nums[tmp];
nums[tmp] = tmp;
}
//若遍历完毕尚未返回,则返回 -1 ,代表数组中无相同值
return -1;
};
// 时间复杂度为O(N),遍历数组使用 O(N),每轮遍历的判断和交换操作使用 O(1)。
// 空间复杂度为O(1),使用常数复杂度的额外空间。
02、二维数组中的查找
- 题目描述
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
- 解题思路
若使用暴力法遍历矩阵 matrix ,则时间复杂度为 O(MN) 。暴力法未利用矩阵 “从上到下递增、从左到右递增” 的特点,显然不是最优解法。 本题解利用矩阵特点引入标志数,并通过标志数性质降低算法时间复杂度。
- 代码实现
let findNumberIn2DArray = function(matrix, target) {
//从矩阵 matrix 左下角元素(索引设为 i、j )开始遍历,并与目标值对比
let i = matrix.length - 1;
let j = 0;
while(i >= 0 && j < matrix[0].length){
//当 matrix[i][j] > target 时,行索引向上移动一格,消去矩阵第 i 行元素
if(matrix[i][j] > target) i--;
//当 matrix[i][j] < target 时,列索引向右移动一格,消去矩阵第 j 列元素
else if(matrix[i][j] < target) j++;
//当 matrix[i][j] == target 时,返回 true
else return true;
}
//若行索引或列索引越界,则代表矩阵中无目标值,返回 false
return false;
};
//时间复杂度 O(M+N),其中,N 和 M 分别为矩阵行数和列数,此算法最多循环 M+N 次。
//空间复杂度 O(1),指针i、j 使用常数大小额外空间。