软件版本交叉排序
题意
给定 个软件版本号,格式为
a.b.c.d(主版本号.次版本号.修订号.构建号),每个分量都是整数。要求先按版本号从小到大排序,然后按"交叉"顺序输出:最小、最大、次小、次大……依次交替,直到所有版本号输出完毕。
版本号比较规则:先比主版本号,相同则比次版本号,再相同比修订号,最后比构建号。
思路
这道题分两步走:排序 + 重排列。
第一步:排序。 把版本号字符串拆成四个整数,按字典序(先比第一个分量,再比第二个……)排序。这就是最基本的多关键字排序。
第二步:交叉排列。 排好序之后,用双指针从两头往中间收。左指针 lo 从最小端出发,右指针 hi 从最大端出发,交替取值放进结果数组:
- 取
sorted[lo],lo++ - 如果
lo <= hi,取sorted[hi],hi-- - 重复直到
lo > hi
拿样例验证一下:排序后是 1.126.127.128, 3.36.80.34, 35.107.224.55, 80.42.126.88, 101.21.35.63,交叉取就是 1... 101... 3... 80... 35...,和预期输出一致。
复杂度
- 时间:
,排序主导
- 空间:
代码
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
scanf("%d", &n);
vector<string> vers(n);
vector<array<int,4>> parsed(n);
for(int i = 0; i < n; i++){
char buf[200];
scanf("%s", buf);
vers[i] = buf;
sscanf(buf, "%d.%d.%d.%d", &parsed[i][0], &parsed[i][1], &parsed[i][2], &parsed[i][3]);
}
vector<int> idx(n);
iota(idx.begin(), idx.end(), 0);
sort(idx.begin(), idx.end(), [&](int a, int b){
return parsed[a] < parsed[b];
});
vector<string> res;
int lo = 0, hi = n - 1;
while(lo <= hi){
res.push_back(vers[idx[lo]]);
lo++;
if(lo <= hi){
res.push_back(vers[idx[hi]]);
hi--;
}
}
for(int i = 0; i < (int)res.size(); i++){
if(i) printf(" ");
printf("%s", res[i].c_str());
}
printf("\n");
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String[] vers = new String[n];
int[][] parsed = new int[n][4];
for (int i = 0; i < n; i++) {
vers[i] = sc.next();
String[] parts = vers[i].split("\\.");
for (int j = 0; j < 4; j++) {
parsed[i][j] = Integer.parseInt(parts[j]);
}
}
Integer[] idx = new Integer[n];
for (int i = 0; i < n; i++) idx[i] = i;
final int[][] p = parsed;
Arrays.sort(idx, (a, b) -> {
for (int j = 0; j < 4; j++) {
if (p[a][j] != p[b][j]) return p[a][j] - p[b][j];
}
return 0;
});
StringBuilder sb = new StringBuilder();
int lo = 0, hi = n - 1;
while (lo <= hi) {
if (sb.length() > 0) sb.append(' ');
sb.append(vers[idx[lo]]);
lo++;
if (lo <= hi) {
sb.append(' ');
sb.append(vers[idx[hi]]);
hi--;
}
}
System.out.println(sb.toString());
}
}
import sys
def main():
input_data = sys.stdin.read().split()
n = int(input_data[0])
vers = input_data[1:n+1]
def parse(v):
return tuple(int(x) for x in v.split('.'))
sorted_vers = sorted(vers, key=parse)
res = []
lo, hi = 0, n - 1
while lo <= hi:
res.append(sorted_vers[lo])
lo += 1
if lo <= hi:
res.append(sorted_vers[hi])
hi -= 1
print(' '.join(res))
main()
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });
const lines = [];
rl.on('line', line => lines.push(line.trim()));
rl.on('close', () => {
const n = parseInt(lines[0]);
const vers = [];
for (let i = 1; i <= n; i++) vers.push(lines[i]);
const parse = v => v.split('.').map(Number);
vers.sort((a, b) => {
const pa = parse(a), pb = parse(b);
for (let j = 0; j < 4; j++) {
if (pa[j] !== pb[j]) return pa[j] - pb[j];
}
return 0;
});
const res = [];
let lo = 0, hi = n - 1;
while (lo <= hi) {
res.push(vers[lo]);
lo++;
if (lo <= hi) {
res.push(vers[hi]);
hi--;
}
}
console.log(res.join(' '));
});

京公网安备 11010502036488号