[题解&总结]LeetCode第205场周赛

LeetCode第205场周赛

比赛地址

A:替换所有的问号

题意

给定一个只含小写字母和?的字符串,现需要将所有的问号改为小写字母,切不能和与其相连的字符相同。

题解

直接暴力即可。遍历整个字符串,出现?号判断即可。

AC代码(cpp)
class Solution {
public:
    string modifyString(string s) {
        int len=s.length();
        for(int i=0;i<len;i++){
            if(s[i]=='?'){
                if(i==0){
                    for(int j=0;j<26;j++){
                        if('a'+j!=s[i+1]){
                            s[i]='a'+j;break;
                        }
                    }
                }else if(i==len-1){
                    for(int j=0;j<26;j++){
                        if('a'+j!=s[i-1]){
                            s[i]='a'+j;break;
                        }
                    }
                }else{
                    for(int j=0;j<26;j++){
                        if('a'+j!=s[i-1]&&'a'+j!=s[i+1]){
                            s[i]='a'+j;break;
                        }
                    }
                }
            }
        }
        return s;
    }
};

比赛时写的,代码有点丑

B:数的平方等于两数乘积的方法数

题意

给定两个整形数组num1、num2,需要求三元组的个数
三元组规则如下:

  • n u m 1 [ i ] 2 = n u m 2 [ j ] ∗ n u m 2 [ k ] ; j < k num1[i]^2=num2[j]*num2[k];j<k num1[i]2=num2[j]num2[k];j<k
  • n u m 2 [ i ] 2 = n u m 1 [ j ] ∗ n u m 1 [ k ] ; j < k num2[i]^2=num1[j]*num1[k];j<k num2[i]2=num1[j]num1[k];j<k
题解

数据为1000,显然O( n 3 n^3 n3)是不行的,于是考虑O( n 2 n^2 n2)
直接使用hash表(个人习惯于c++,于是即:c++中的map or unordered_map)保存两个不同的数的乘积。然后遍历一遍另外一个数组判断是否有元素的平方与两个数的乘积相同的情况,具体见代码。

AC代码(cpp)
#define ll long long
class Solution {
public:
    int solve(vector<int>& a, vector<int>& b){
        map<ll,int>mp;
        int ans=0;
        int len1=a.size(),len2=b.size();
        for(int j=0;j<len2;j++){
            for(int k=j+1;k<len2;k++){
                mp[(ll)b[j]*b[k]]++;
            }
        }
        for(int i=0;i<len1;i++){
            ans+=mp[(ll)a[i]*a[i]];
        }
        return ans;
    }
    int numTriplets(vector<int>& nums1, vector<int>& nums2) {
        return solve(nums1,nums2)+solve(nums2,nums1);
    }
};

C:避免重复字母的最小删除成本

题意

给定一字符串s,和一个对应的代价数组(即:删除s[i]则对应需要付出代码cost[i])
现需要相邻的字符不相同,问最少需要多少删除代价,才能满足题意。

题解

dp。dp[i][j]表示:前i个字符满足题意的条件下最后的字符为’a’+j的情况。
于是乎状态转移方程为:

  • 删 除 s [ i ] 的 情 况 : d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + c o s t [ i ] 删除s[i]的情况:dp[i][j]=dp[i-1][j]+cost[i] s[i]dp[i][j]=dp[i1][j]+cost[i]
  • 不 删 除 s [ i ] 的 情 况 : d p [ i ] [ j ] = d p [ i − 1 ] [ k ] ; 其 中 k 不 等 于 j 不删除s[i]的情况:dp[i][j]=dp[i-1][k];其中k不等于j s[i]dp[i][j]=dp[i1][k];kj
AC代码(cpp)
#define inf 0x3f3f3f3f
class Solution {
public:
    int dp[100010][30];   //dp[i][j]:前i个字符删除操作结束后最后的字符为j+'a'的最少代价(需要注意dp[i][26]表示前i个字符都需要删除的情况)
    int minCost(string s, vector<int>& cost) {
        int n=s.length();
        memset(dp,inf,sizeof(dp));
        dp[0][s[0]-'a']=0;dp[0][26]=cost[0];
        for(int i=1;i<n;i++){
            //删除s[i]的情况
            for(int j=0;j<=26;j++){
                dp[i][j]=dp[i-1][j]+cost[i];
            }
            //不删除s[i]的情况
            int j=s[i]-'a';
            for(int k=0;k<=26;k++){
                if(k==j) continue;
                dp[i][j]=min(dp[i][j],dp[i-1][k]);
            }
        }
        int ans=inf;
        for(int i=0;i<=26;i++){
            ans=min(ans,dp[n-1][i]);
        }
        return ans;
    }
};

D:保证图可完全遍历

题意

给定一无向图,有三种类型的边:分别为Alice可以走,Bob可以走,两个都可以走。问最多删除多少条边可以使得Alice和Bob都可以遍历所有的点。

题解

问最多删除多少条边,转化为最少需要多少条边可以使得图对于Alice和Bob而言都是联通的。也就是:最小生成树问题。
先考虑第三种类型的边,然后考虑另外两种类型的边,具体操作间代码。

AC代码(cpp)
class Solution {
public:
    int para[100010],parb[100010];
    int get_par1(int a){
        if(para[a]!=a) para[a]=get_par1(para[a]);
        return para[a];
    }
    int get_par2(int a){
        if(parb[a]!=a) parb[a]=get_par2(parb[a]);
        return parb[a];
    }
    int maxNumEdgesToRemove(int n, vector<vector<int>>& edges) {
        for(int i=1;i<=n;i++) para[i]=i,parb[i]=i;
        int ans=0,cnta=n,cntb=n;  //ans表示生成的需要多少条边,cnta:表示Alice的连通块为多少,cntb:表示Bob的连通块为多少
        
        //考虑类型3的边
        for(int i=0;i<edges.size();i++){
            int c=edges[i][0],u=edges[i][1],v=edges[i][2];
            if(c==3){
                int para_u=get_par1(u),para_v=get_par1(v);
                int parb_u=get_par2(u),parb_v=get_par2(v);
                if(para_u!=para_v){
                    para[para_v]=para_u;cnta--;
                    parb[parb_v]=parb_u;cntb--;
                }else ans++;
            }
        }

        //考虑另外两种类型的边
        for(int i=0;i<edges.size();i++){
            int c=edges[i][0],u=edges[i][1],v=edges[i][2];
            if(c==3) continue;
            if(c==1){
                int para_u=get_par1(u),para_v=get_par1(v);
                if(para_u!=para_v){
                    para[para_v]=para_u;cnta--;
                }else ans++;
            }else{
                int parb_u=get_par2(u),parb_v=get_par2(v);
                if(parb_u!=parb_v){
                    parb[parb_v]=parb_u;cntb--;
                }else ans++;
            }
        }

        if(cnta>1||cntb>1) return -1; 
        return ans;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:这段代码是一个解决LeetCode上某个题目的C++实现,具体是一个双指针的解法。该题目是计算一个数组中的积水量。代码中使用了个指针分别指向数组的左右边界,然后通过比较左右指针所指向的元素的大小,来确定当前位置的积水量。具体的计算方法是,如果左指针所指向的元素小于右指针所指向的元素,则对左指针的左边进行操作,如果左指针所指向的元素大于等于右指针所指向的元素,则对右指针的右边进行操作。在每一次操作中,都会更新左边的最大值和右边的最大值,并计算当前位置的积水量。最后返回的积水量。\[1\] 引用\[2\]:这段代码是另一个解决LeetCode上某个题目的C++实现,具体是一个深度优先搜索的解法。该题目是计算一个二维网格中从起点到终点的可行路径数量。代码中使用了递归的方式进行深度优先搜索,从起点开始,每次向下或向右移动一步,直到到达终点。在每一步移动中,会判断当前位置是否有障碍物,如果有障碍物则返回0,如果到达终点则返回1,否则继续递归搜索下一步的位置。最后返回的可行路径数量。\[2\] 引用\[3\]:这段代码是另一个解决LeetCode上某个题目的C++实现,具体是一个动态规划的解法。该题目是计算一个数组中的积水量。代码中使用了动态规划的思想,通过遍历数组中的每个元素,分别计算该元素左边和右边的最大值,并计算当前位置的积水量。最后返回的积水量。\[3\] 综上所述,这三段代码分别是解决LeetCode上不同题目的C++实现,分别使用了双指针、深度优先搜索和动态规划的方法来解决问题。 #### 引用[.reference_title] - *1* *3* [Leetcode 热题100 42.接雨水(C++ 多种解法,错过可惜)](https://blog.csdn.net/qq_51933234/article/details/124637883)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [[C++]Leetcode 不同路径 || 解题思路及详解](https://blog.csdn.net/weixin_62712365/article/details/123951736)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值