1. 两数之和
- 由于哈希查找的时间复杂度为 O(1),所以可以利用哈希容器 map 降低时间复杂度
- 遍历数组 nums,i 为当前下标,每个值都判断map中是否存在 target-nums[i] 的 key 值
- 如果存在则找到了两个值,如果不存在则将当前的 (nums[i],i) 存入 map 中,继续遍历直到找到为止
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> hash;
for(int i=0; i<nums.size();i++){
if(hash.find(target-nums[i]) != hash.end()){
return {hash[target-nums[i]],i};
}
hash[nums[i]]=i;
}
return {};
}
};
2. 盛水最多的容器
题目:https://leetcode-cn.com/problems/container-with-most-water/
矩形的面积与两个因素有关:
矩形的长度:两条垂直线的距离
矩形的宽度:两条垂直线其中较短一条的长度
因此,要矩形面积最大化,两条垂直线的距离越远越好,两条垂直线的最短长度也要越长越好。
我们设置两个指针 left 和 right,分别指向数组的最左端和最右端。此时,两条垂直线的距离是最远的,若要下一个矩形面积比当前面积来得大,必须要把 height[left] 和 height[right] 中较短的垂直线往中间移动,看看是否可以找到更长的垂直线。
class Solution {
public:
int maxArea(vector<int>& height) {
int i=0, j=height.size()-1;
int ret=0, s=0;
while(i<j){
s=min(height[i],height[j])*(j-i);
ret=max(s,ret);
if(height[i]<=height[j]){
i++;
}
else j--;
}
return ret;
}
};
3. 最接近的三数之和
题目:https://leetcode-cn.com/problems/3sum-closest/
思路:
- 首先进行数组排序
- 在数组 nums 中,进行遍历,每遍历一个值利用其下标i,形成一个固定值 nums[i]
- 再使用前指针指向 l = i + 1 处,后指针指向 r = nums.size() - 1 处,也就是结尾处
- 根据 sum = nums[i] + nums[l] + nums[r] 的结果,判断 sum 与目标 target 的距离,如果更近则更新结果 res
- 同时判断 sum 与 target 的大小关系,因为数组有序,如果 sum > target 则 r--,如果 sum < target 则 l++,如果 sum == target 则说明距离为 0 直接返回结果
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
if(nums.size()<3) return 0;
sort(nums.begin(),nums.end());
int res=nums[0]+nums[1]+nums[2];
for(int i=0; i+2<nums.size(); i++){
int l=i+1, r=nums.size()-1;
while(l<r){
int sum=nums[i]+nums[l]+nums[r];
if(abs(target-sum)<abs(target-res)){
res=sum;
}
if(target>sum){
l++;
}
else if(target<sum){
r--;
}
else return res;
}
}
return res;
}
};
4. 删除排序数组中的重复项
题目:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
求删除重复元素,实际上就是将不重复的元素移到数组的左侧。考虑用 2 个指针,一个在前记作 p,一个在后记作 q,算法流程如下:
1.比较 i 和 j 位置的元素是否相等。
如果相等,j 后移 1 位
如果不相等,将 j 位置的元素复制到 i+1 位置上,i 后移一位,j 后移 1 位
重复上述过程,直到 j 等于数组长度。
2. 返回 i + 1,即为新数组长度。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.empty()) return 0;
int i=0;
int _size=nums.size();
for(int j=1; j<_size; j++){
if(nums[j]!=nums[i]){
i++;
nums[i]=nums[j];
}
}
return i+1;
}
};
5. 在排序数组中查找元素的第一个和最后一个位置
题目:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/
二分法:查找左右边界,二次循环实现
一个技巧,可以用一个函数只查询左边界
int l=binarySearch(nums,target); //左边界
int r=binarySearch(nums,target+1); //右边界
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int l=binarySearch(nums,target);
int r=binarySearch(nums,target+1);
if(l==nums.size() || nums[l]!=target){
return vector<int>{-1,-1};
}
return vector<int>{l,r-1};
}
int binarySearch(vector<int>& nums, int target){
int left=0, right=nums.size();
while(left<right){
int mid=left+(right-left)/2;
if(nums[mid]<target){
left=mid+1;
}
else right=mid;
}
return left;
}
};