Leetcode第309场周赛+Acwing第67场周赛

Leetcode第309场周赛

第一题2399. 检查相同字母间的距离

分析:用一个数组记录每个字符首次出现的位置并计算距离。定义一个26位场的vector数组,每位的初始值为-1,遍历数组,某个字符第一次出现时就将其值vec[c]变为i作为第一次出现的位置,如果不是第一次出现就用此时的i减去该字符第一次出现记录的位置减一,得出来的就是两相同字符间的距离。

代码

class Solution {
public:
    bool checkDistances(string s, vector<int>& distance) {
        int n = s.size();
        vector<int> vec(26, -1);
        for (int i = 0; i < n; i++) {
            int c = s[i] - 'a';
            // 字母第一次出现,记录位置
            if (vec[c] == -1) vec[c] = i;
            // 字母第二次出现,计算距离
            else vec[c] = i - vec[c] - 1;
        }
        // 与 distance 比较
        for (int i = 0; i < 26; i++) if (vec[i] >= 0 && vec[i] != distance[i]) return false;
        return true;
    }
};

第二题2400. 恰好移动 k 步到达某一位置的方法数目

分析:利用数学方法,记从起点startPos到终点endPos的方向为正方向,从起点到终点一共需要往正方向走a步,往负方向走k步,易得a - (k - a) = d,a=\frac{d+k}{2}d为startPos到endPos的距离。判断d+k是否为偶数,然后用递归计算组合数。思路参考

代码

class Solution {
    const int MOD = 1000000007;

public:
    int numberOfWays(int startPos, int endPos, int K) {
        int d = abs(startPos - endPos);
        if ((d + K) % 2 == 1 || d > K) return 0;
        // 递推求组合数
        vector<vector<long long>> f;
        f.resize(K + 1, vector<long long>(K + 1));
        for (int i = 0; i <= K; i++) {
            f[i][0] = 1;
            for (int j = 1; j <= i; j++) f[i][j] = (f[i - 1][j] + f[i - 1][j - 1]) % MOD;
        }
        return f[K][(d + K) / 2];
    }
};

Acwing第67场周赛

第一题4609. 火柴棍数字

分析:经过分析可知,当火柴根数小于3时只能输出1,当火柴根数为偶数时,每一位都是1是所组成的数字位数越长,也就越大;当火柴根数为奇数时,第一位为7,后面每位都是1时所组成的数数字越长,也就是越大。

代码

#include<iostream>

using namespace std;

int main(){
    int n,x;
    cin >> n;
    while(n --){
        cin >> x;
        if(x < 3)cout << 1 << endl;
        else if(x % 2 == 0){
            for(int i = x/2;i > 0;i --)cout << 1;
            cout << endl;
        }
        else{
            cout << 7;
            for(int i = x/2 - 1;i > 0;i --)cout << 1;
            cout << endl;
        }
    }
    return 0;
}

第二题4610. 列表排序

分析:暴力枚举思路。由于只能交换一次列,那么我们首先枚举出交换列的所有情况。时间复杂度m×m在此基础上判断每一行和[1,2,3,4…,m]有多少个数不同,分析可知如果超过2个,则这种情形不合法,返回NO,否则返回YES,总的时间复杂度为m×m×n。

代码

int main()
{
    cin >> n >> m;
    
    for(int i = 0; i < n; i ++ ) {
        for(int j = 0; j < m; j ++ ) {
            cin >> s[i][j];
        }
    }
    
    for(int i = 0; i < m; i ++ ) {
        for(int j = i; j < m; j ++ ) {
            for(int k = 0; k < n; k ++ ) swap(s[k][i], s[k][j]);
            if(check()) {
                puts("YES");
                return 0;
            }
            for(int k = 0; k < n; k ++ ) swap(s[k][i], s[k][j]);
        }
    }
    
    puts("NO");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值