【备战秋招】每日一题:2023.08.22-拼多多服务端研发笔试-第一题-塔子哥的回文修改

为了更好的阅读体检,可以查看我的算法学习网
在线评测链接:P1477
视频题解

题目内容

塔子哥有一个字符串 s s s

现在塔子哥给这个串恰好 k k k 次修改,问修改后的串是否可能是回文串?需要保证修改一个字符后,修改前后的字符不同。

输入描述

第一行,一个整数 T ( 1 ≤ T ≤ 10 ) T(1\leq T\leq 10) T(1T10) ,表示 T T T 组数据。

接下来对于每组数据,

第一行,输入一个字符串 s ( 1 ≤ l e n ( s ) ≤ 1 0 6 ) s (1\leq len(s)\leq 10^6) s(1len(s)106)

第二行,输入一个整数 k ( 1 ≤ k ≤ 1 0 6 ) k(1\leq k\leq 10^6) k(1k106) ,表示修改次数。

输出描述

输出 Yes 表示修改后可以为回文串,输出 No 表示在 k k k 次修改后不可能为回文串。

样例

输入

4
aaa
1
bac
2
bbcc
3
cdefgh
2

输出

Yes
Yes
Yes
No

思路:思维

首先考虑将 s [ i ] s[i] s[i] s [ j ] s[j] s[j] 修改为相同,满足 0 ≤ i , j ≤ n − 1 , i + j = n − 1 0\leq i, j\leq n-1, i+j=n-1 0i,jn1,i+j=n1

如果修改了 c n t cnt cnt 次:

  • c n t > k cnt > k cnt>k ,则必然无法修改为回文串。

  • c n t = = k cnt == k cnt==k ,则恰好可以修改为回文串

  • c n t < k cnt < k cnt<k 但是 n n n 是奇数,那么多的 k − c n t k - cnt kcnt 次都用来修改最中间的字符即可

  • c n t < k cnt < k cnt<k 但是 n n n 是偶数,那么多的 k − c n t k - cnt kcnt 可以这么考虑:

    如果 k − c n t k - cnt kcnt 为偶数,那么我们对于相同的两个字符 s [ i ] = s [ j ] s[i]=s[j] s[i]=s[j],修改 k − c n t 2 \frac{k - cnt}{2} 2kcnt 次这两个字符即可。

    如果 k − c n t k - cnt kcnt 为奇数,且 c n t > 0 cnt > 0 cnt>0,那么我们对于修改前不相同的两个字符 s [ i ] s[i] s[i] s [ j ] s[j] s[j] ,假设 s [ i ] = ′ a ′ , s [ j ] = ′ b ′ s[i]='a', s[j]='b' s[i]=a,s[j]=b ,那么我们不把 s [ i ] s[i] s[i] 修改为和 s [ j ] s[j] s[j] 一样,此时剩余了 k − c n t + 1 k-cnt+1 kcnt+1 次,因为 k − c n t k-cnt kcnt 是奇数,所以 k − c n t + 1 k-cnt+1 kcnt+1 是偶数且大于等于 2 2 2 。这时候可以将 s [ i ] s[i] s[i] s [ j ] s[j] s[j] 都修改为 ′ c ′ 'c' c 。后面剩余的 k − c n t − 1 k-cnt-1 kcnt1 次,均可以选择 s [ i ] s[i] s[i] s [ j ] s[j] s[j] 同时修改为一个同样的字符即可。

    如果 k − c n t k - cnt kcnt 为奇数,且 c n t = 0 cnt = 0 cnt=0 ,如果 k − c n t > 1 k - cnt > 1 kcnt>1 ,则必然可以修改为回文串,否则 k − c n t = 1 k - cnt = 1 kcnt=1 ,就无法修改为回文串。

时间复杂度: O ( n ) O(n) O(n)

代码

C++

#include <bits/stdc++.h>
using namespace std;

string s;
int k;

void solve() {
    cin >> s;
    cin >> k;

    int n = int(s.size());
    // 先查看有多少需要修改的
    int cnt = 0;
    for (int l = 0, r = n - 1; l < r; ++l, --r) {
        if (s[l] != s[r]) {
            cnt += 1;
        }
    }

    if (cnt > k) {
        cout << "No\n";
        return;
    }
    
    if (cnt == k || (n & 1)) {
        cout << "Yes\n";
        return;
    }
    
    // k > cnt, n 是偶数
    // 如果 k - cnt 是偶数,则修改完后,将一个字符反复修改再修改回来即可
    if ((k - cnt) % 2 == 0) {
        cout << "Yes\n";
    } else {
        // 如果 k - cnt 是奇数,cnt > 0 或者 (cnt == 0 && k - cnt > 1),则可以
        if (cnt > 0 || k - cnt > 1) {
            cout << "Yes\n";
        } else {
            // cnt == 0 and k - cnt == 1 ,则不可以
            cout << "No\n";
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int T;
    cin >> T;

    while (T--) solve();

    return 0;
}

Java

import java.util.Scanner;

public class Main {
    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        int T = scanner.nextInt();

        while (T-- > 0) {
            solve();
        }
    }

    private static void solve() {
        String s = scanner.next();
        int k = scanner.nextInt();

        int n = s.length();
        int cnt = 0;
        for (int l = 0, r = n - 1; l < r; ++l, --r) {
            if (s.charAt(l) != s.charAt(r)) {
                cnt += 1;
            }
        }

        if (cnt > k) {
            System.out.println("No");
            return;
        }

        if (cnt == k || (n & 1) == 1) {
            System.out.println("Yes");
            return;
        }

        if ((k - cnt) % 2 == 0) {
            System.out.println("Yes");
        } else {
            if (cnt > 0 || k - cnt > 1) {
                System.out.println("Yes");
            } else {
                System.out.println("No");
            }
        }
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔子哥学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值