最近在写leetcode的题目,写到了15题三数之和以及240题搜索二维矩阵II,这两个题目存在一些相似之处,就是单调性查找。
15.三数之和
题目描述:
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为 0 且不重复的三元组。
思路:
对于一个数组nums
,从左至右扫描,当扫描至nums[i]
时,要寻找的另外两个数的和是 sum = 0 - nums[i]
。要找到这两个数,就要进行第二次循环。
那么问题来了,如何保证最后找到的结果不重复呢?如果在第二层循环的时候,查找是从nums[0]
开始的,那么势必会导致重复查询,最后给出的三元数组里会存在重复的数据。故而当第一层循环,遍历至位置i
时对应的第二层循环从位置i + 1
开始查找,从而避免重复查询。
以下是实现的c++代码。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<int> element(3);
vector<vector<int>> rs;
for(int i = 0; i < nums.size(); i++){
if (i > 0 && nums[i] == nums[i - 1]) continue;
int sum = 0 - nums[i];
towSum(nums, sum, i, rs);
}
return rs;
}
void towSum(vector<int>& nums, int target, int index, vector<vector<int>> & rs){
int i = index + 1, j = nums.size() - 1;
vector<int> element(3);
while(i < j){
if(nums[i] + nums[j] < target || i == index) i = i + 1;
else if(nums[i] + nums[j] > target || j == index) j = j - 1;
else{
element[0] = nums[index];
element[1] = nums[i];
element[2] = nums[j];
rs.push_back(element);
int temp = i + 1;
while(temp < nums.size() && nums[temp] == nums[i]) temp++;
i = temp;
temp = j - 1;
while(temp >= 0 && nums[temp] == nums[j]) temp--;
j = temp;
continue;
}
}
}
};
240.搜索二维矩阵
题目描述
编写一个高效的算法来搜索 m x n
矩阵 matrix
中的一个目标值 target
。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
若该二维矩阵中有target
,则返回true
,否则返回false
。
思路
对于这样一个二维数组,在查找的时候,如果将左上角(右下角)作为起始位置出发,那么当target
比起始位置大(小)的时候,存在向右和向下(向左和向上)两个方向,不利于查找。
但是在查找时如果将左下角(右上角)作为起始位置时,则查找的方向只有一个,当target比当前位置的数值大的时候,则往右(下)走,当target比当前位置的数值小的时候,则往上(左)走,故而能实现单调查找。
实现c++代码如下:
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int i = matrix.size() - 1, j = 0;
while (i >= 0 && j < matrix[i].size()){
if(matrix[i][j] == target) return true;
else if(matrix[i][j] < target) j++;
else i--;
}
return false;
}
};