#P3895. 第1题-大写迁移
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 24
            Accepted: 11
            Difficulty: 2
            
          
          
          
                       所属公司 : 
                              美团
                                
            
                        
              时间 :2025年10月11日-开发岗
                              
                      
          
 
- 
                        算法标签>模拟          
 
第1题-大写迁移
解题思路
题意:给定只含大小写字母的字符串 s(下标从 1 开始),维护计数器 x=1。按 i=1..n 顺序进行:
- 若 
i+x ≤ n且s[i+x]为大写字母,则把s[i+x]改成小写,并令x+=1;同时若s[i]为小写则把s[i]改成大写。 - 否则本次不做任何修改。输出最终字符串。
 
做法:模拟 / 双指针
用 0 下标实现更方便。遍历位置 i,动态维护 x,用另一个位置 j=i+x(相当于第二个指针)。若 j 在范围内且 s[j] 是大写,则按规则修改 s[j]、提升 x,并把 s[i] 在需要时改成大写。整个过程只前进一次,所有操作都可在原串上完成。
核心要点
- 使用数组(字符列表)就地修改,避免反复构造新串。
 - 每次成功触发操作都会使 
x增加 1,因此j=i+x单调增加,整体只会检查与修改每个位置常数次,保证线性复杂度。 
复杂度分析
- 时间复杂度:
O(n),每个位置至多被访问/修改常数次。 - 空间复杂度:
O(1)(除字符数组外不需要额外空间)。 
代码实现
Python
# 题面功能封装在外部函数里
def solve(n, s):
    # 转为列表以便就地修改
    a = list(s)
    x = 1  # 计数器
    for i in range(n):          # i 为 0-based
        j = i + x               # 对应题意中的 i+x
        # 判断是否满足触发条件:j 在范围内且 a[j] 为大写
        if j < n and 'A' <= a[j] <= 'Z':
            a[j] = a[j].lower()  # s[i+x] 改小写
            x += 1               # x 增加 1
            # 若 s[i] 是小写则改为大写
            if 'a' <= a[i] <= 'z':
                a[i] = a[i].upper()
    return ''.join(a)
if __name__ == "__main__":
    import sys
    data = sys.stdin.read().strip().split()
    n = int(data[0])
    s = data[1]
    print(solve(n, s))
Java
import java.util.*;
// ACM 风格,类名固定为 Main
public class Main {
    // 题面功能在外部函数里
    public static String solve(int n, String s) {
        char[] a = s.toCharArray();
        int x = 1; // 计数器
        for (int i = 0; i < n; i++) {
            int j = i + x; // 对应题意中的 i+x
            // 满足条件:j 合法且 a[j] 为大写
            if (j < n && Character.isUpperCase(a[j])) {
                a[j] = Character.toLowerCase(a[j]); // 改小写
                x++;                                // x 自增
                // 若 a[i] 为小写,则改为大写
                if (Character.isLowerCase(a[i])) {
                    a[i] = Character.toUpperCase(a[i]);
                }
            }
        }
        return new String(a);
    }
    public static void main(String[] args) {
        // 默认输入数据规模可用 Scanner
        Scanner sc = new Scanner(System.in);
        int n = Integer.parseInt(sc.next());
        String s = sc.next();
        System.out.print(solve(n, s));
        sc.close();
    }
}
C++
#include <bits/stdc++.h>
using namespace std;
// 题面功能在外部函数里
string solve(int n, string s) {
    int x = 1; // 计数器
    for (int i = 0; i < n; ++i) {
        int j = i + x; // 对应题意中的 i+x
        // 若 j 在范围内且 s[j] 为大写,则触发本次修改
        if (j < n && isupper(static_cast<unsigned char>(s[j]))) {
            s[j] = tolower(static_cast<unsigned char>(s[j])); // 改小写
            x++;                                              // x 自增
            // 若 s[i] 为小写,则改为大写
            if (islower(static_cast<unsigned char>(s[i]))) {
                s[i] = toupper(static_cast<unsigned char>(s[i]));
            }
        }
    }
    return s;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    string s;
    if (!(cin >> n)) return 0;
    cin >> s;
    cout << solve(n, s);
    return 0;
}
        题目内容
给定一个长度为 n 、由大小写字母组成的字符串 s (下标从 1 开始)。存在一个计数器 x ,初始 x=1 。你需要按下标从小到大的顺序,依次对每个下标 i 执行如下操作:
- 若 i+x≤n 且 si+x 为大写字母,则将 si+x 修改为小写字母,然后将增加 1 ;同时,若 si 为小写字母,则将 si 修改为大写字母。若不满足上述条件,则本次不进行任何修改。
 
请输出全部操作结束后的字符串。
输入描述
第一行输入一个整数 n(1≦n≦2×105) ,表示字符串长度。
第二行输入一个长度为 n 、仅由大小写字母组成的字符串 s 。
输出描述
在一行上输出一个长度为 n 的字符串,表示全部操作结束后的结果。
样例1
输入
4
abcX
输出
abCx
说明
在这组样例中:
- 
初始 x=1 。当 i=1,2 时 i+x 对应的字符均不满足大写当 i=3 时,i+x=4 且 s4=′X′ 为大写,故将其改为小写 ′x′ 灭 增加为 2 ;同时 s3=′c’ 为小写,改为大写 ′C′;
 - 
其他位置不触发条件,不进行修改,最终得到 "abCx" 。
 
样例2
输入
6
aABCDe
输出
AABcDe
样例3
输入
5
AbCdE
输出
ABCde