128. 最长连续序列/283. 移动零/11. 盛最多水的容器

128. 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

思路:注意这里要求是复杂度为n,所以双层for循环暴力解法不可取。

        重新思考,当遍历到当前元素时,我们需要去寻找它的下一个数字,例如遍历到100去找101,这里肯定是没有错的,所以我们能节省时间的就是去减少寻找次数,例如对于1,2,3,4这四个元素而言,都是在一个序列中,显然从1开始寻找是最长的,其他三个都比1要短。

        这里就可以看出1和2,3,4的区别,就是1是序列起点,换句话说1前面没有0,而2前面有3,3前面有2,4前面有3所以当遍历到2,3,4就跳过不去寻找,因为在遍历1的时候我们就会找到包含它们的序列,并且最长。那么跳过条件我们就知道了,如果当前元素减一也在数组中就跳过,例如4前面有3就跳过,我们只找起点元素。

        查找我们就用unordered_set,无序集合上的所有操作在平均情况下都具有常数时间复杂度O(1),但在最坏情况下,时间复杂度可以达到线性时间O(n),这取决于内部使用的哈希函数,但实际上它们表现非常出色,通常提供常数时间的查找操作。

        同时注意一下unordered_set是如何循环输出元素。

代码:

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        //初始化unordered_set
        unordered_set<int> set;
        //将数组中元素填入set中
        for(int i=0;i<nums.size();i++){
            set.insert(nums[i]);
        }
        //最长序列
        int m=0;
        for(auto iter = set.begin(); iter != set.end(); ++iter){
            //如果没有当前元素减一的值在set中,就开始统计
            if(!set.count(*iter-1)){
                //当前元素下一个数字
                int a=*iter+1;
                //当前序列长度
                int b = 1;
                //按照当前元素寻找后面依次递增的数字
                while(set.count(a)){
                    a+=1;
                    b+=1;
                }
                 //更新
                m=max(m,b);
            }
           
        }
        return m;
    }
};

283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]

输出: [1,3,12,0,0]

思路:涉及到这种不复制数组就用双指针法处理,这里要求不移动其他元素的相对位置,双指针就只能从头开始。

代码:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int left=0;
        int right=0;
        while(right<=(nums.size()-1)){
           if(nums[right]!=0){
               swap(nums[left], nums[right]);
               ++left;
           }
           ++right;
    }
    }
};

11. 盛最多水的容器

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

思路:木桶能装多少水,是由最短的木板来决定,所以双指针法移动的是最短的那边,也就是比较一下元素值,再移动。

代码:

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left=0;
        int right=height.size() - 1;
        int m=0;
        while(left<right){
           int n = min(height[left], height[right]) * (right - left);
            m=max(m,n);
            if(height[left]<=height[right]){
                ++left;
            }
            else{
                --right;
            }
           
        }
        return m;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值