#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
说明