[Leetcode] 128, 16, 18

本文介绍了解决寻找最长连续整数序列及求最接近目标值三数之和等问题的方法。通过哈希表存储元素并从两端扩展,实现O(n)复杂度找出最长连续序列;利用排序和双指针技巧,高效找到三数之和最接近目标值的组合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

128. Longest Consecutive Sequence

Given an unsorted array of integers, find the length of the longest consecutive elements sequence.

For example,
Given [100, 4, 200, 1, 3, 2],
The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.

Your algorithm should run in O(n) complexity.

Solution: 哈希表存储后,两头查询。

快排的时间复杂度是O(nlogn),但此题要求O(n),因此此题不能进行排序操作。

但是,排序算法中有一个很特别的算法,时间复杂度也仅为O(n):
假设需要排序的数据是整数且范围是有限的0<=x<=max,那么可以建立一个数组x[0]-x[max],初始化为0,遍历无序数组a,然后将x[an]++,这样就能在O(n)的时间复杂度内进行排序。

此题数据为整数,但是没有给出范围,因此不能使用这种排序算法,但是可以将其进行变体,使用unordered_map来存储,然后对于一个数据向两头查找,就能够得到包含它的最长连续序列。

Note:map和unordered_map对比。
map和unordered_map的使用方法类似,但是实现方式不同,导致性能有差异:
map使用红黑树实现,unordered_map使用哈希表实现。
map内部是有序的,每次插入和查询的复杂度均为logn。
但我查到的资料对于unordered_map的性能有不同的说法,unordered_map的查询操作是公认的快,但是插入操作有说比map慢,也有说比map快。但就哈希表的特性和这题解法来说,用unordered_map进行插入操作时间复杂度应该在O(1)才对,但是鉴于我不清楚unordered_map具体的实现细节,可能也有待补充的地方。(待查)

Code:

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_map<int,bool> m;
        for(auto i:nums) m[i] = false; //遍历的简化写法,auto:自动判断变量类型
        
        int maxlength = 0;
        for(auto i:nums){
            
            if(m[i]==true) continue;
            else{
                
                int min = i;
                int max = i;
                
                int length = 1;
                int end = false;
                while(!end){
                    end = true;
                    if(m.find(min-1)!=m.end()){
                        m[min-1] = true;
                        min--;
                        length++;
                        end = false;
                    }
                    if(m.find(max+1)!=m.end()){
                        m[max+1] = true;
                        max++;
                        length++;
                        end = false;
                    }
                }
                if(maxlength<length) maxlength = length;
            }
        }
        
        return maxlength;
    }
};



16. 3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.


Solution: 排序之后,夹逼(不需要遍历)

Code:

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        
        int cloSum = nums[0] + nums[1] + nums[2];
        for(auto a = nums.begin(); a<prev(nums.end(),2); 
            a = upper_bound(a,prev(nums.end(),2),*a)){//得到下一个不重复的a值
            auto b = next(a);
            auto c = prev(nums.end());
                
            while(b<c){
                int sum = *a + *b + *c;
                
                if(abs(sum-target)<abs(cloSum-target)){
                    cloSum = sum;
                }
                
                if(sum<target) b++;
                else c--;
            }
            
        }
        
        return cloSum;
    }
};


18. 4Sum

Given an array S of n integers, are there elements abc, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note: The solution set must not contain duplicate quadruplets.

Solution: 排序之后,两层遍历之后夹逼(不需要遍历)

Code:

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        
        vector<vector<int>> result;
        if(nums.size()<4) return result;
        
        sort(nums.begin(), nums.end());
        
        
        for(auto a = nums.begin(); a<prev(nums.end(), 3); 
           a = upper_bound(a, prev(nums.end(), 3), *a)){
            int t = target - *a;
            for(auto b = next(a); b<prev(nums.end(),2); 
               b =upper_bound(b, prev(nums.end(),2), *b)){
                auto c = next(b);
                auto d = prev(nums.end());
                
                while(c<d){
                    int sum = *b + *c + *d;
                    if(sum==t){
                        vector<int> r;
                        r.push_back(*a);
                        r.push_back(*b);
                        r.push_back(*c);
                        r.push_back(*d);
                        result.push_back(r);
                        c = upper_bound(c, prev(nums.end()), *c);
                    }else if(sum>t){
                        d = prev(d);
                    }else if(sum<t){
                        c = next(c);
                    }
                }
                
            }
            
        }
        
        return result;
    }
};


 

18. 4S

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值