[c++] [leetcode二刷] 数组

思路总结

(1)使用哈希表空间换时间

(2)排序后使用左右指针

 

1. Remove Duplicates from Sorted Array

Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

Example 1:

Given nums = [1,1,2],

Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.

It doesn't matter what you leave beyond the returned length.

思路:easy

只需要两个下标,一个记录不重复所在位置,一个不断遍历即可

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size() < 2) return nums.size();
        int i = 0;
        for(int j = 1;j < nums.size();j++){
            if(nums[i] != nums[j]){
                i++;
                nums[i] = nums[j];
            }
        }
        return i+1;
    }
};

 

2. Remove Duplicates from Sorted Array II

Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twice and return the new length.

Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.

Example 1:

Given nums = [1,1,1,2,2,3],

Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively.

It doesn't matter what you leave beyond the returned length.

思路:medium

注意,这里不能改上面的代码,变成减2,会出现问题,1,1,1,2,2,3会变成1,1,2,3,因为第一个2移位之后,会变成1,1,2,2,2,3,造成误判,必须使用count去计次

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size() < 3) return nums.size();
        int i = 1,cnt = 1;
        for(int j = 1;j < nums.size();j++){
            if(nums[j] == nums[j-1]) cnt++;
            else cnt = 1;
            if(cnt < 3) nums[i++] = nums[j];
        }
        return i;
    }
};

 

3. Longest Consecutive Sequence

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

Your algorithm should run in O(n) complexity.

Example:

Input: [100, 4, 200, 1, 3, 2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.

思路:hard

怎样O(n)时间去检测顺序序列 -> 空间换时间,使用哈希表

思路1: 使用字典去记录边界的长度,不断更新

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        if(nums.size()<2) return nums.size();
        int left = 0,right = 0;
        int res = 0;
        map<int,int> m;
        for(int num:nums){
            if(!m.count(num)){
                left = (m.count(num-1) > 0)? m[num-1]:0;
                right = (m.count(num+1) > 0)? m[num+1]:0;
                // 更新左右边界的长度
                m[num] = left+right+1;
                m[num-left] = m[num];
                m[num+right] = m[num];
                
                res = max(m[num],res);
            }
        }
        return res;
    }
};

思路2:使用set,很直观的想法,当一个数的num-1不在数组中时,说明这个num是一个上升序列的起始,因此去找这个序列的右边界

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        if(nums.size()<2) return nums.size();
        // 初始化set
        set<int> s(nums.begin(),nums.end());
        int res=1;
        for(int num:s){
            // 只有当当前数是一个序列的起始点的时候,去判断序列长度
            if(!s.count(num-1)){
                // 找到序列最长长度
                int right = num+1;
                while(s.count(right)) right++;
                res = max(res,right-num);
            }
        }
        return res;
    }
};

 

4.Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

思路:easy

(1)时间复杂度O(n^2)

因为未排序需要返回下标,故可以直接O(n^2)时间复杂度遍历

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> res;
        for(int i = 0;i < nums.size();i++){
            for(int j = i+1;j < nums.size();j++){
                if(nums[i]+nums[j] == target){
                    res.push_back(i);
                    res.push_back(j);
                    return res;
                }
            }
        }
        return res;
    }
};

(2)空间换时间,时间复杂度O(N)

这里思路跟上一题很像,充分利用哈希表的特性

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int,int> m;
        vector<int> res;
        for(int i = 0;i < nums.size();i++){
            m[nums[i]] = i;
        }
        for(int i = 0;i < nums.size();i++){
            int num_j = target-nums[i];
            // 注意这里m[num_j] != i,确保不会取到自己
            if(m.count(num_j) && m[num_j] != i){
                res.push_back(i);
                res.push_back(m[num_j]);
                break;
            }
        }
        return res;
    }
};

 

5.3Sum

Given an array nums of n integers, are there elements abc in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

思路:medium

(1)怎样去重:sort之后判断

(2)3 sum是2 sum的变形,排序后使用2 sum,时间复杂度O(n^2)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        if(nums.size() < 3) return res;
        // 排序:便于去重,同时2sum时间负责度变为O(n)
        sort(nums.begin(),nums.end());
        
        for(int i = 0;i < nums.size()-2;i++){
            int target = 0-nums[i];
            if(i == 0 || (i > 0 && nums[i] != nums[i-1])){
                int j = i+1,k = nums.size()-1;
                while(j < k){
                    if(nums[j]+nums[k] == target){
                        vector<int> cur{nums[i],nums[j],nums[k]};
                        res.push_back(cur);
                        while(j < k && nums[j+1] == nums[j]) j++;
                        while(k > j && nums[k-1] == nums[k]) k--;
                        j++;k--;
                    }
                    else if (nums[j]+nums[k] < target) j++;
                    else k--;
                }
            }  
        }
        return res;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>