leetcode 第199场周赛 [阿里云]

重新排列字符串灯泡开关Ⅳ好叶子节点对的数量压缩字符串Ⅱ
3分 简单4分 中等5分 中等8分 困难
写的时候傻逼了,结束后立马过了

5472 重新排列字符串

签到题

复杂度

O(n)

执行用时

24ms

内存消耗

15.4MB

class Solution {
public:
    string restoreString(string s, vector<int>& indices) {
        string ans=s;
        for(int i=0;i<indices.size();i++){
            ans[indices[i]]=s[i];
        }
        return ans;
    }
};

5473 灯泡开关Ⅳ

开关是转变i-n的状态,所以必须要先从将前面的灯泡的状态变成要求的状态

转化下题意,其实就是要求段的个数,段是连续的1或者连续的0

开头全是0的段不计次数

执行用时

44 ms

内存消耗

9.5MB

复杂度

O(n)

class Solution {
public:
    int minFlips(string target) {
        int len=target.length();
        int now=0;
        int ans=0;
        while(now<len&&target[now]=='0') now++;
        if(now<len){
            while(now<len){
                ans++;
                int flag=target[now]-'0';
                while(now<len&&flag==(target[now]-'0')) now++;
            }
        }
        
        return ans;
    }
};

 


5474 好叶子节点对的数量

用vector < int > tmp 维护叶子节点到当前节点的距离 i 的个数tmp[i]

dfs先求出左儿子的集合left和右儿子的集合right

枚举左子树的叶子节点到当前节点的距离i,右子树的叶子节点到当前的距离j

这一对叶子节点的距离就是 i+j+2 , 它们的贡献就是left[i]*right[j]


再将左右子树集合合并

for(int i=0;i<dis;i++){
    if(i+1<dis) tmp[i+1]+=(left[i]+right[i]);
}

 

复杂度

O(n * d * d)

n为节点个数,d为传入参数distance

执行用时

96 ms

内存消耗

33.6MB

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int ans=0;
    vector<int> dfs(TreeNode* root,int dis){
        vector<int>tmp(dis,0);
        if(root==NULL){
            return tmp;
        }
        if(root->left==NULL&&root->right==NULL){
            tmp[0]=1;
            return tmp;
        }
        vector<int>left=dfs(root->left,dis);
        vector<int>right=dfs(root->right,dis);
        for(int i=0;i<dis;i++){
            if(i+1<dis) tmp[i+1]+=(left[i]+right[i]);
            if(left[i]==0) continue;
            for(int j=0;j<dis;j++){
                int sum=i+j+2;
                if(sum<=dis){
                    ans+=left[i]*right[j];
                } 
                else break;
            }
        }
        return tmp;
    }
    int countPairs(TreeNode* root, int distance) {
        if(distance<2) return 0;
        dfs(root,distance);
        return ans;
    }
};

 


5462 压缩字符串Ⅱ

dp[i][j][k] 表示到字符串第i位,与第i位左边相邻的连续相同字符个数为j

(eg:abcc 与第4位左边相邻的连续相同字符个数为2;与第3位左边相邻的连续相同字符个数为1)

删除了k个字符


枚举前一个状态 f[j][l][m]

        for(int i=1;i<=n;i++){
            for(int j=i-1;j>=0;j--){
                for(int l=0;l<=j;l++){
                    for(int m=0;m<=min(k,j);m++){
                    }
                }
            }   
        }

当s[i]==s[j]

状态转移方程为:

int flag=0;//flag表示当前字符的个数进位了,如从个位数到达十位数
if((l+1==2)||(l+1==10)||(l+1==100)) flag=1;
int tmp=m+i-j-1;//tmp表示删除(j+1~i-1)之间所有的数
else f[i][l+1][tmp]=min(f[i][l+1][tmp],f[j][l][m]+flag);

连续相邻个数加1

当i后面的数都可以被删除时,更新最后的答案if(n-i<=k-tmp) ans=min(ans,f[i][l+1][tmp]);


当s[i]!=s[j]

状态转移方程为

int tmp=m+i-j-1;//tmp表示删除(j+1~i-1)之间所有的数
f[i][1][tmp]=min(f[i][1][tmp],f[j][l][m]+1);

连续相邻个数变为1


当i后面的数都可以被删除时,更新最后的答案 if(n-i<=k-tmp) ans=min(ans,f[i][1][tmp]);

复杂度

O(N^4)

执行用时

1652 ms

内存消耗

11.5MB

class Solution {
public:
    int f[105][105][105];
    int getLengthOfOptimalCompression(string ss, int k) {
        string s="!"+ss;
        int n=ss.length();
        
        memset(f,-1,sizeof(f));
        f[0][0][0]=0;
        int ans=n-k;
        for(int i=1;i<=n;i++){
            for(int j=i-1;j>=0;j--){
                for(int l=0;l<=j;l++){
                    for(int m=0;m<=min(k,j);m++){
                        if(f[j][l][m]==-1) continue;
                        int tmp=m+i-j-1;
                        if(tmp>k) break;
                        if(s[i]==s[j]){
                            int flag=0;
                            if((l+1==2)||(l+1==10)||(l+1==100)) flag=1;
                            if(f[i][l+1][tmp]==-1) f[i][l+1][tmp]=f[j][l][m]+flag;
                            else f[i][l+1][tmp]=min(f[i][l+1][tmp],f[j][l][m]+flag);
​
                            if(n-i<=k-tmp) ans=min(ans,f[i][l+1][tmp]);
                        }
                        else{
                            if(f[i][1][tmp]==-1) f[i][1][tmp]=f[j][l][m]+1;
                            else f[i][1][tmp]=min(f[i][1][tmp],f[j][l][m]+1);
                            if(n-i<=k-tmp) ans=min(ans,f[i][1][tmp]);
                        }
                    }
                }
            }
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值