leetcode200题之数组(三)

1. 两数之和

  1. 由于哈希查找的时间复杂度为 O(1),所以可以利用哈希容器 map 降低时间复杂度
  2. 遍历数组 nums,i 为当前下标,每个值都判断map中是否存在 target-nums[i] 的 key 值
  3. 如果存在则找到了两个值,如果不存在则将当前的 (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/

思路:

  1. 首先进行数组排序
  2. 在数组 nums 中,进行遍历,每遍历一个值利用其下标i,形成一个固定值 nums[i]
  3. 再使用前指针指向 l = i + 1 处,后指针指向 r = nums.size() - 1 处,也就是结尾处
  4. 根据 sum = nums[i] + nums[l] + nums[r] 的结果,判断 sum 与目标 target 的距离,如果更近则更新结果 res
  5. 同时判断 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;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值