#P2829. 第1题-字符串排序
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 17
            Accepted: 12
            Difficulty: 3
            
          
          
          
                       所属公司 : 
                              阿里
                                
            
                        
              时间 :2025年4月12日-阿里淘天(开发岗)
                              
                      
          
 
- 
                        算法标签>排序算法          
 
第1题-字符串排序
题解思路
1. 输入解析
我们首先需要读取输入:
- 一个整数
k,代表要操作的倍数。 - 一个字符串
s,我们需要对其进行操作。 
2. 分组与排序
- 对于下标是
k的倍数的位置(例如:k, 2k, 3k,...),我们需要提取出这些位置上的字符,并按照字母表从小到大的顺序进行排序。 - 对于非
k的倍数的位置,提取出这些字符,并按照字母表从大到小的顺序进行排序。 
3. 重建字符串
在排序完成后,我们将排序后的字符放回对应的位置,生成最终的字符串。
4. 算法步骤
- 提取与分组:遍历字符串,分别提取出
k倍数位置和非k倍数位置上的字符。 - 排序:对提取出来的字符进行相应的排序。
 - 重建:将排序后的字符放回原字符串中的对应位置。
 
5. 时间复杂度分析
- 提取字符的时间复杂度是O(n),其中n是字符串的长度。
 - 排序操作的时间复杂度是O(n log n),因为我们需要分别对
k倍数和非k倍数的位置进行排序。 - 因此,整个算法的时间复杂度为O(n log n),这是因为排序操作的复杂度主导了整体时间复杂度。
 
代码实现
Python代码实现
def solve(k, s):
    n = len(s)
    
    # 提取k的倍数位字符
    k_chars = [s[i] for i in range(k-1, n, k)]
    # 提取非k的倍数位字符
    non_k_chars = [s[i] for i in range(n) if (i + 1) % k != 0]
    
    # 对k的倍数位字符进行字母表升序排序
    k_chars.sort()
    
    # 对非k的倍数位字符进行字母表降序排序
    non_k_chars.sort(reverse=True)
    
    # 初始化一个结果列表
    result = list(s)
    
    # 将排序后的k倍数位字符放回原位置
    k_index = 0
    for i in range(k-1, n, k):
        result[i] = k_chars[k_index]
        k_index += 1
    
    # 将排序后的非k倍数位字符放回原位置
    non_k_index = 0
    for i in range(n):
        if (i + 1) % k != 0:
            result[i] = non_k_chars[non_k_index]
            non_k_index += 1
    
    # 输出结果
    return ''.join(result)
# 输入处理
k = int(input())  # 读取k值
s = input()  # 读取字符串s
# 输出操作后的字符串
print(solve(k, s))
Java代码实现
import java.util.*;
public class Main {
    public static String solve(int k, String s) {
        int n = s.length();
        
        // 提取k的倍数位字符
        List<Character> kChars = new ArrayList<>();
        for (int i = k - 1; i < n; i += k) {
            kChars.add(s.charAt(i));
        }
        
        // 提取非k的倍数位字符
        List<Character> nonKChars = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if ((i + 1) % k != 0) {
                nonKChars.add(s.charAt(i));
            }
        }
        
        // 对k的倍数位字符进行字母表升序排序
        Collections.sort(kChars);
        
        // 对非k的倍数位字符进行字母表降序排序
        Collections.sort(nonKChars, Collections.reverseOrder());
        
        // 初始化结果字符串
        char[] result = s.toCharArray();
        
        // 将排序后的k倍数位字符放回原位置
        int kIndex = 0;
        for (int i = k - 1; i < n; i += k) {
            result[i] = kChars.get(kIndex++);
        }
        
        // 将排序后的非k倍数位字符放回原位置
        int nonKIndex = 0;
        for (int i = 0; i < n; i++) {
            if ((i + 1) % k != 0) {
                result[i] = nonKChars.get(nonKIndex++);
            }
        }
        
        return new String(result);
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int k = sc.nextInt();
        sc.nextLine();  // 读取换行符
        String s = sc.nextLine();
        
        System.out.println(solve(k, s));
    }
}
C++代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
string solve(int k, string s) {
    int n = s.length();
    
    // 提取k的倍数位字符
    vector<char> kChars;
    for (int i = k - 1; i < n; i += k) {
        kChars.push_back(s[i]);
    }
    
    // 提取非k的倍数位字符
    vector<char> nonKChars;
    for (int i = 0; i < n; i++) {
        if ((i + 1) % k != 0) {
            nonKChars.push_back(s[i]);
        }
    }
    
    // 对k的倍数位字符进行字母表升序排序
    sort(kChars.begin(), kChars.end());
    
    // 对非k的倍数位字符进行字母表降序排序
    sort(nonKChars.rbegin(), nonKChars.rend());
    
    // 初始化结果字符串
    vector<char> result(s.begin(), s.end());
    
    // 将排序后的k倍数位字符放回原位置
    int kIndex = 0;
    for (int i = k - 1; i < n; i += k) {
        result[i] = kChars[kIndex++];
    }
    
    // 将排序后的非k倍数位字符放回原位置
    int nonKIndex = 0;
    for (int i = 0; i < n; i++) {
        if ((i + 1) % k != 0) {
            result[i] = nonKChars[nonKIndex++];
        }
    }
    
    return string(result.begin(), result.end());
}
int main() {
    int k;
    cin >> k;
    string s;
    cin >> s;
    
    cout << solve(k, s) << endl;
    return 0;
}
        题目内容
对于给定的由小写字母构成的字符串s,下标从1开始,我们需要将每一个k的倍数位取出,按照字母表从小到大的顺序排序后依次放回每一个取出字符的位置(即对于下标k的位置,放回排序后的第1个字符,对于下标k的位置,放回排序后的第2个字符,以此类推);随后,再对非k的倍数位按照字母表从大到小的顺序进行排序,并放回原位置。
输出操作后的字符串。
输入描述
第一行输入一个正整数k(1≦k≤105)代表操作位倍数。
第二行输入一个长度为1≤len(s)≤105,由小写字母构成的字符串s,代表需要进行操作的字符串。
输出描述
输出一行,代表操作后的字符串。
样例1
输入
2
zyabx
输出
zbxya
说明