题目一:二维数组中的查找
(2021/1/1)
在一个 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
自己的方法一:暴力遍历:两重for循环,代码比较简单
自己的方法二:根据矩阵排序特点,设置一个行标记和列标记,从矩阵的左下角或者右上角出发进行查找
Java源代码
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
int row = matrix.length - 1;
int col = 0;
while (row >= 0 && col < matrix[0].length) {
if (matrix[row][col] == target) {
return true;
} else if (matrix[row][col] > target) {
row--;
} else if (matrix[row][col] < target) {
col++;
}
}
return false;
}
}
题目二:三数之和
(2021/1/4)链接:https://leetcode-cn.com/problems/3sum
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
方法一:我自己的思路就是三重循环,想不到更好的方法。
方法二:官方解答:排序+双指针
双指针法铺垫: 先将给定 nums 排序,复杂度为 O(NlogN)O(NlogN)。
双指针法思路: 固定 33 个指针中最左(最小)数字的指针 k,双指针 i,j 分设在数组索引 (k, len(nums))(k,len(nums)) 两端,通过双指针交替向中间移动,记录对于每个固定指针 k 的所有满足 nums[k] + nums[i] + nums[j] == 0 的 i,j 组合:
当 nums[k] > 0 时直接break跳出:因为 nums[j] >= nums[i] >= nums[k] > 0,即 33 个数字都大于 00 ,在此固定指针 k 之后不可能再找到结果了。
当 k > 0且nums[k] == nums[k - 1]时即跳过此元素nums[k]:因为已经将 nums[k - 1] 的所有组合加入到结果中,本次双指针搜索只会得到重复组合。
i,j 分设在数组索引 (k, len(nums))(k,len(nums)) 两端,当i < j时循环计算s = nums[k] + nums[i] + nums[j],并按照以下规则执行双指针移动:
当s < 0时,i += 1并跳过所有重复的nums[i];
当s > 0时,j -= 1并跳过所有重复的nums[j];
当s == 0时,记录组合[k, i, j]至res,执行i += 1和j -= 1并跳过所有重复的nums[i]和nums[j],防止记录到重复组合。
复杂度分析:
1)时间复杂度 O(N^2)O(N
2 ):其中固定指针k循环复杂度 O(N)O(N),双指针 i,j 复杂度 O(N)O(N)。
空间复杂度 O(1)O(1):指针使用常数大小的额外空间。
Java源代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> listresult = new ArrayList<>();
Arrays.sort(nums);
{
for(int k = 0; k<nums.length-2;k++){
if(nums[k]>0) return listresult;
int i = k+1;
int j = nums.length-1;
if(k>0 &&nums[k]==nums[k-1]){
continue;
}
while(i<j){
if(nums[k]+nums[i]+nums[j] <0){
while(i<j &&nums[i] == nums[++i]);
}else if(nums[k]+nums[i]+nums[j]>0){
while(i<j && nums[j]== nums[--j]);
}
else{
List<Integer> templist = new ArrayList<>();
templist.add(nums[k]);
templist.add(nums[i]);
templist.add(nums[j]);
listresult.add(templist);
while(i<j &&nums[i] == nums[++i]);
while(i<j && nums[j]== nums[--j]);
}
}
}
}
return listresult;
}
}