力扣第234场周赛题解

目录

第一题 -- 字符串中不同整数的数目

第二题 -- 还原排列的最少操作

第三题 -- 替换字符串中的括号内容

第四题 -- 好因子的最大数目


第一题 -- 字符串中不同整数的数目

题目描述:

简单来说,就是从目标字符串中提取数字串,并统计个数。

注意:①需要去重 ②需要去掉前导零。

我的做法:

① 使用map数组存储是否存在过(可用set、unorderset代替)

② 使用一个bool型判断此串是否为全零

时间复杂度O(nmlogn)(因为string传入map是通过传值方式,O(m)的参数传递,m为平均数字串长度)

class Solution {
public:
    map<string,bool>s;    // 负责去重
    bool flag=0;            // 之前字符是数字的标志
    int numDifferentIntegers(string word) {
        string tmp="";
        flag=0;
        for(int i=0;i<word.length();i++){
            if(word[i]>='0'&&word[i]<='9'){
                if(tmp==""&&word[i]=='0'){
                    flag=1;
                    continue;
                }
                tmp+=word[i];
            }
            else{
                if(tmp!=""){
                    s[tmp]=1;
                }
                else if(flag){    // 可能是00000之类的全零数字串
                    s["0"]=1;
                }
                flag=0;
                tmp="";
            }
        }
        if(tmp!=""){
            s[tmp]=1;
        }
        else if(flag){    
            s["0"]=1;
        }
        
        return (int)s.size();
    }
};

第二题 -- 还原排列的最少操作

题目大意:

简单来说,就是通过上述的操作,返回原始顺序需要最少的操作步骤。

我的做法:

直接模拟即可,因为n最大为1000,我直接打表想看看是否有规律,结果哈哈哈直接是答案。算法复杂度O(n^{2}).

class Solution {
public:
    bool check(vector<int>&p){
        for(int i=0;i<p.size();i++){
            if(i!=p[i])return false;
        }
        return true;
    }

    int reinitializePermutation(int n) {
        vector<int>p(n);
        for(int i=0;i<n;i++)p[i]=i;
        int cnt=0;
        do{
            vector<int>arr(n);
            for(int i=0;i<n;i++){
                if(i&1){
                    arr[i]=p[n/2+(i-1)/2];
                }
                else{
                    arr[i]=p[i/2];
                }
                // cout<<arr[i]<<" ";
            }
            // cout<<endl;
            p=arr;
            cnt++;
        }while(!check(p));

        return  cnt;
    }
};

第三题 -- 替换字符串中的括号内容

题目大意:

简单来说,就是将(XXX)根据knowledge字典转换为真正的字符串,有点像函数传参。

我的做法:

字典的词数最多为1e5,所有直接遍历算法复杂度为O(n^{2}),肯定会超时。但使用map存储,时间复杂度缩小为O(n{logn}),符合题目要求。

class Solution {
public:
    map<string,int>p;
    string evaluate(string s, vector<vector<string>>& knowledge) {
        string ans="";
        string t;
        for(int i=0;i<knowledge.size();i++){
            p[knowledge[i][0]]=i+1;  // 为节省空间,存储的是序号
        }
        
        for(int i=0;i<s.length();i++){
            if(s[i]=='('){
                i++;
                string t="";
                while(s[i]!=')'){
                    t+=s[i++];
                }
                int j=p[t];   
                
                if(j==0)ans+='?'; // 字典中不存在,输出?
                else ans+=knowledge[j-1][1];
            }
            else{
                ans+=s[i];
            }
        }
        return ans;
    }
};

第四题 -- 好因子的最大数目

题目大意:

简单来说,就是求质因子数不超过primeFactors个的所有数中,其非质因子数目的最大乘积,需要mod 1e9+7.

我的做法:

我们通常知道,一个数的非质因子是由质因子组合相乘而得来的

举个例子:一个数存在x个为2的质因子,y个为3的质因子,z个为5的质因子,那么此数不同非质因子的个数为 x*y*z。

如果理解了上面那个例子,那么这道题就转换为:

\newline x_{1}+x_{2}+x_{3}+...+x_{n} <= primeFactors \newline query \ Max(x_{1}*x_{2}*x_{3}*...*x_{n})

 

我们通过举例:

n=2时,ans=2。                n=3时,ans=3。                          n=4时,ans=2*2=4。

n=5时,ans=3*2=6            n=6时,ans=3*3=9(>2*2*2)         n=7时,ans=3*2*2=12

我们可以以此类推,可以发现,可以推出规律:ans(n)=ans(n-3)*3。

为什么得出这样的结论?

因为其他质因子,例如5<3*2,7<3*2*2,11<3*3*3*2,而且可以发现,随着其他质因子的增大,差距愈发明显。而2这个质因子,当n=6时,2*2*2 < 3*3,故除了n=4,首选3必然会有更大的结果。

算法复杂度O(logn)

const int mod = 1e9+7;
typedef long long ll;
class Solution {
public:
    ll mod_pow(ll a,ll b){    // 快速幂,函数作用为求 a^b
        ll r = 1;
        while(b){
            if(b&1)r=(r*a)%mod;
            a=(a*a)%mod;
            b>>=1;
        }
        return r%mod;
    }
    int maxNiceDivisors(int primeFactors) {
        if(primeFactors<=4)return primeFactors;
        ll p = 1;
        
        for(int i=2;i<=4;i++){    // 判断是由哪个子集通过增加3得来的
            if((primeFactors-i)%3==0){
                int t = (primeFactors-i)/3;
                p = (p*mod_pow(3,t))%mod; 
                p = (p*i)%mod;    // 注意还要乘上子集解。
                break;
            }
        }
        
        return p%mod;
    }
};

本人是一个退役的Acm老狗,保研后生活比较闲,故想捡起之前所学的算法,写写博客也算是记录下自己的思路。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述: 给出两个非空链表来表示两个非负整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 您可以假设除了数字 0 之外,这两个数都不会以零开头。 示例: 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 原因:342 + 465 = 807 解题思路: 题目中要求我们按照逆序的方式存储两个非负整数,也就是说链表的头节点表示该数的个位,第二个节点表示该数的十位,以此类推。 因此,我们可以从两个链表的头节点开始,对应位相加,并记录进位,将结果添加到新的链表中。如果有进位,需要在下一位相加时加上进位。 需要注意的是,当两个链表的长度不一致时,可以将较短的链表的缺失位看作是 0。 最后,如果最高位有进位,还需要在新链表的最高位添加一个值为 1 的节点。 C 语言代码实现: /** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){ struct ListNode *head = NULL, *tail = NULL; int carry = 0; while (l1 || l2) { int n1 = l1 ? l1->val : 0; int n2 = l2 ? l2->val : 0; int sum = n1 + n2 + carry; if (!head) { head = tail = malloc(sizeof(struct ListNode)); tail->val = sum % 10; tail->next = NULL; } else { tail->next = malloc(sizeof(struct ListNode)); tail = tail->next; tail->val = sum % 10; tail->next = NULL; } carry = sum / 10; if (l1) l1 = l1->next; if (l2) l2 = l2->next; } if (carry > 0) { tail->next = malloc(sizeof(struct ListNode)); tail = tail->next; tail->val = carry; tail->next = NULL; } return head; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值