C++ Leedcode刷题(日更)

目录

一、数组与双指针

1.两数之和

2.有序数组合并

3.寻找两个正序数组的中位数

一、数组与双指针

1.两数之和

暴力解法

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

 哈希解法

无序快速查找

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map <int,int> hashtable;  //建立无序哈希表
        for (int i=0; i<nums.size();++i){
            auto it = hashtable.find(target-nums[i]); //在哈希表内查值,是否有target-nums[i]的值
            if (it != hashtable.end()){ //如果他没有在哈希表的尾部,则返回他的值
                return {it->second,i};  //访问value  it->first访问key
            }
            hashtable[nums[i]] = i; //加入值 hashtable[key] = value
        }
        return {};
 
    }
};

2.有序数组合并

 暴力解法 :直接合并两个数组进行排序

但这种方法没有用到排序的特征

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        for (int i=0; i<n; i++){
            nums1[m+i] = nums2[i];
        }
        sort(nums1.begin(),nums1.end()); //从小到大

    }
};

双指针

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int p1=0;
        int p2=0;
        int cur;
        int nums3[m+n]; //创建一个m+n的空数组
        while(p1<m || p2<n){
            if (p1 == m){    //1、nums1用完了
                cur = nums2[p2];
                p2++;
            }
            else if (p2 == n){ //2、nums2用完了
                cur = nums1[p1];
                p1++;
            }
            else if (nums1[p1]<nums2[p2]){  //3、nums1的数小
                cur = nums1[p1];
                p1++;
            }
            else {
                cur = nums2[p2];   //4、nums2的数小
                p2++;
            }  
            nums3[p1+p2-1] = cur;   //p1+p2-1正好是每次依次增大的索引
            for (int i=0;i<m+n;i++){
                nums1[i] = nums3[i];  //将nums3的值赋予给nums1
            }          
        }
    }
};

3.寻找两个正序数组的中位数

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size();
        int n = nums2.size();
        int nums3[m+n];
        int p1=0;
        int p2=0;
        int cur;
        while( p1<m || p2<n ){
            if (p1==m){
                cur = nums2[p2];
                p2++;
            }
            else if (p2==n){
                cur = nums1[p1];
                p1++;
            }
            else if (nums1[p1]<nums2[p2]){
                cur = nums1[p1];
                p1++;
            }
            else {
                cur = nums2[p2];
                p2++;
            }
        nums3[p1+p2-1] = cur;
        }
        
        int c=m+n;
        if (c%2 == 1){
            return nums3[(c-1)/2];

        }
        else {
            double d = (nums3[c/2-1] + nums3[c/2])/2.0;  
            //!!一定是除2.0结果才会转化为浮点数,卡了好长时间
            return d;   
        }
    }
    
};

4. 求三个数之和 

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;  #动态容器用来返回数组
        // 枚举 a
        for (int first = 0; first < n; ++first) {
            // 需要和上一次枚举的数不相同 去重
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            // c 对应的指针初始指向数组的最右端
            int third = n - 1;
            int target = -nums[first];
            // 枚举 b
            for (int second = first + 1; second < n; ++second) {
                // 需要和上一次枚举的数不相同 去重
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue; //合理运用continue才能找全
                }
                // 需要保证 b 的指针在 c 的指针的左侧
                while (second < third && nums[second] + nums[third] > target) {
                    --third;
                }
                // 如果指针重合,随着 b 后续的增加
                // 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
                if (second == third) {
                    break;
                }
                if (nums[second] + nums[third] == target) {
                    ans.push_back({nums[first], nums[second], nums[third]});
                }
            }
        }
        return ans;
    }
};

 5. 颜色分类

 

单指针 

两次循环遍历

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int n=nums.size();
        int ptr = 0;
        for (int i=0; i<n;i++){
            if (nums[i]==0){
                swap(nums[i],nums[ptr]);
                ptr++;
            }            
        }
        for (int i=0; i<n;i++){
            if (nums[i]==1){
                swap(nums[i],nums[ptr]);
                ptr++;
            }            
        }
    }
};

双指针

一次循环遍历,需要注意用到while来避免,两个指针交换,只顾nums[n+1]而不管之前是否交换。

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int n=nums.size();
        int p1 = 0;
        int p2 = n-1;
        for (int i=0; i<n;i++){
            while (i <= p2 && nums[i] == 2) {
                swap(nums[i], nums[p2]);
                --p2;
            }
            if (nums[i] == 0) {
                swap(nums[i], nums[p1]);
                ++p1;
            } 
        }
    }
};

6、最小覆盖子串 

 思路

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> hs, ht; //声明哈希表
        for (auto& c : t) ht[c] ++ ; //建立ht的哈希表

        string res;
        int cnt = 0;
        for (int i = 0, j = 0; i < s.size(); i ++ ) {
            hs[s[i]] ++ ; //建立hs哈希表
            if (hs[s[i]] <= ht[s[i]]) cnt ++ ;
            
            while (hs[s[j]] > ht[s[j]]) hs[s[j ++ ]] -- ;
            if (cnt == t.size()) {
                if(res.empty() || i - j + 1 < res.size())
                    res = s.substr(j, i - j + 1);
            }
        }
        return res;
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桦树无泪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值