刷题分享_11_25

刷题分享

1.(力扣349)这是一道用哈希表解决的经典题目。但在实现哈希表的时候,一般有vec,set,map,三种情况。对于数据量较小的时候,可以选择用vec,它对于数据的访问较于其他两个更快一点。如果此题不限制数据范围,则应该用set来存储,如果使用vec可能会浪费大量空间

*这是用set实现的版本,因为set底层是用数结构实现的,所以可以使用unordered_set来存储,正好可以利用set不可以存储重复元素这一个特性

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int>set;
        for(int i =0;i<nums1.size();i++){
            set.insert(nums1[i]);
        }
        unordered_set<int>mid;
        for(int i=0;i<nums2.size();i++){
            if(set.find(nums2[i])!=set.end()){
                mid.insert(nums2[i]);
            }
        }
        vector<int>res;for(unordered_set<int>::iterator it=mid.begin();it!=mid.end();it++){
            res.push_back(*it);

        }
        return res;
    }
};

*这是利用vec或者数组来实现的版本,在样本范围小且已知的情况下,这样可以使用更少的时间

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        int hash[1006]={0};
        for(int i=0;i<nums1.size();i++){
            hash[nums1[i]]=1;
        }
        vector<int>res;
        for(int i=0;i<nums2.size();i++){
            if(hash[nums2[i]]==1){
                res.push_back(nums2[i]);
                hash[nums2[i]]=0;
            }
        }
        return res;
    }
};

2.(力扣992)这道题是求恰有k个元素的连续子数组。对于求恰有k个,这个问题十分不好求,所以我们可以转变思路,先实现一个函数 F(K),这个函数可以求出来所含元素小于等于k个的子数组的数量,那么结果就是 F(K) - F(K-1)。这样,我们就可以使用滑动窗口来解决了。参数方面:有一个表用来记录每个元素的 出现次数,另外需要一个变量size来存放当前窗口里已经有了几种数字。具体思路:相当于每一次循环内部固定窗口的右边界,然后看窗口左边界,当左边界也符合时,在窗口内所有以右边界为尾巴的子数组均符合要求,因为F(K)求的是种类不超过K的长度包括1,2,…k

class Solution {
public:
    int getnum(vector<int>& nums, int k){
        int l=0;int r=0;
        int size=0;int res=0;
        int hash[20005]={0};
        for(r=0;r<nums.size(); r++){
            if(hash[nums[r]]==0){
                hash[nums[r]]++;
                size++;
               
            }else{
                hash[nums[r]]++;
            }
            while(size>k){
                if(hash[nums[l]]==1){
                    size--;
                    hash[nums[l]]--;
                    l++;
                }else{
                    hash[nums[l]]--;
                    l++;
                }
            }
                res+=r-l+1;       
        }
        return res;
    }

    int subarraysWithKDistinct(vector<int>& nums, int k) {
        int res=getnum(nums,k)-getnum(nums,k-1);
        return res;
    }
};

3.(力扣395)这是一道求 有k个重复字符 的最长子串的问题(即如果结果里多了一种字母,那么该字母最少出现k次,可能不连续)。因为它的元素只有可能是小写字母,所以可以将它拆解为26个子问题,即 包括N种字母,每种字母的出现次数大于等于K的子串的长度 (N属于1~26)在让结果等于上述26种情况里的最大值即可。此题需要两个关键参数:col是现在窗口里收集到的字母种类,sat是现在窗口里包含的字母中出现次数>=k次的字母种类数量。窗口的移动条件:当前窗口里含有的元素数量(col)比应该含有的(res)大

class Solution {
public:
    int longestSubstring(string s, int k) {
        int res=0;
        for(int req=1;req<=26;req++){
        int hash[256]={0};
        int l=0;int r=0;
        int col=0;int sat=0;
        
            for(r=0;r<s.size();r++){
            hash[s[r]]++;
            if(hash[s[r]]==1){
                col++;
            }
            if(hash[s[r]]==k){
                sat++;
            }
            while(col>req){
                if(hash[s[l]]==1){
                col--;
               }
               if(hash[s[l]]==k){
                sat--;
               }
               
               hash[s[l]]--;
               l++;
            }
            if(sat==req){
                res=max(res,r-l+1);
            }
        }
        }
        return res;
    }
};

4.这道题是高精度的大整数加法,核心在于模拟

#include 
#include 
#include
using namespace std;
vector<int> add(vector<int>&a,vector<int>&b){
    vector<int>res;
    int tem=0;
    for(int i=0;i<a.size()||i<b.size();i++){
        if(i<a.size()){
            tem+=a[i];
        }
        if(i<b.size()){
            tem+=b[i];
        }
        res.push_back(tem%10);
        tem/=10;
    }
    if(tem!=0){
        res.push_back(1);
    }
    return res;
}
int main(){
    string a,b;
    cin>>a>>b;
    vector<int>A,B;
    for(int i=a.size()-1;i>=0;i--){
        A.push_back(a[i]-'0');
    }
    for(int i=b.size()-1;i>=0;i--){
        B.push_back(b[i]-'0');
    }
    auto C=add(A,B);
    for(int i=C.size()-1;i>=0;i--){
        printf("%d",C[i]);
    }
    return 0;
}

5.这道题是高精度的大整数减法,核心在于模拟

#include 
#include 
#include
using namespace std;

bool com(vector<int>&a,vector<int>&b){
    if(a.size()<b.size()){
        return false;
    }else if(a.size()>b.size()){
        return true;
    }
    for(int i=a.size()-1;i>=0;i--){
        if(a[i]!=b[i]){
            return a[i]>b[i];
        }
    }
    return true;
    
}

vector<int> sub(vector<int>&a,vector<int>&b){
    vector<int>res;
    int tem=0;
    for(int i=0;i<a.size();i++){
        tem=a[i]-tem;
        if(i<b.size()){
            tem-=b[i];
        }
        res.push_back((tem+10)%10);
        if(tem<0){
            tem=1;
        }else{
            tem=0;
        }
    }
    while(res.size()>1&&res.back()==0){
        res.pop_back();
    }
    return res;
}


int main(){
    
    string a,b;
    cin>>a>>b;
    vector<int>A,B;
    
    for(int i=a.size()-1;i>=0;i--){
        A.push_back(a[i]-'0');
    }
    for(int i=b.size()-1;i>=0;i--){
        B.push_back(b[i]-'0');
    }
    
    if(com(A,B)){
    auto C=sub(A,B);
    for(int i=C.size()-1;i>=0;i--){
        printf("%d",C[i]);
    }
    
    }else{
        auto C=sub(B,A);
        cout<<'-';
        for(int i=C.size()-1;i>=0;i--){
        printf("%d",C[i]);
        }
    }
    
    
    return 0;
}

你可能感兴趣的:(算法刷题,算法)