首页 > 试题广场 >

最小排列

[编程题]最小排列
  • 热度指数:2129 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
由数字 1 到 n 组成的一个序列我们称为一个 n 排列。对于两个不同的 n 排列 𝐴 = 𝑎1𝑎2 ... 𝑎𝑛 和 𝐵 = 𝑏1𝑏2 ... 𝑏𝑛 我们可以按字典序比较他们的大小:从前往后找到第一个两个排列中数字不同 的位置,即找到一个位置𝑝使得 𝑎1 = 𝑏1 ,  𝑎2 = 𝑏2 , ... , 𝑎𝑝−1 = 𝑏𝑝−1 ,  𝑎𝑝 ≠ 𝑏𝑝 ,若 𝑎𝑝 < 𝑏𝑝 ,我们 则称排列 𝐴 小于排列 𝐵 ,反之则 𝐴 大于 𝐵 。现在给出一个 n 排列,你需要选择排列中的两个不同的位置,然后交换这两个位置的数字, 你需要使得最后得到的排列尽量小。注意你必须进行一次且只能进行一次操作。

数据范围:

输入描述:
第一行包含一个数字 𝑛 ,表示排列的长度。
第二行包含 𝑛 个数字构成一个 𝑛 排列。     


输出描述:
输出一个 n 排列,表示能得到的最小的排列。
示例1

输入

3
3 2 1

输出

1 2 3
示例2

输入

4
2 1 4 3

输出

1 2 4 3
#include <bits/stdc++.h>
using namespace std;

int a[100001], b[100001];
int main(){
    int n, x;
    scanf("%d", &n);
    for(int i=1;i<=n;i++){
        scanf("%d", &a[i]);
        b[a[i]] = i;
    }
    for(int i=1;i<=n;i++){
        if(a[i]!=i){
            x = b[i];
            a[x] = a[i];
            a[i] = i;
            for(int i=1;i<=n;i++){
                if(i==n)
                    printf("%d\n", a[i]);
                else
                    printf("%d ", a[i]);
            }
            return 0;
        }
    }
    a[n] = n-1;
    a[n-1] = n;
    for(int i=1;i<=n;i++){
        if(i==n)
            printf("%d\n", a[i]);
        else
            printf("%d ", a[i]);
    }
    return 0;
}

发表于 2020-09-20 08:38:30 回复(0)
更多回答
解题思路就几个原则:
1.当序列第一个不是1的时候,那就是从后面的序列中找到1,然后跟序列的首位两个互换。
2.当序列是顺序的时候,检测第一个不连续的数,再从序列的后面找到此处原本应该是的数的位置,两个互换。
3.一种特殊的情况。如果序列顺序完全正确,那么交换最后两个数,因为题目说一定要进行一次数据交换。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void ChangeAndDisplay(vector<int>data,int a, int b)
{
    auto it1 = find(data.begin(), data.end(), a);
    auto it2 = find(data.begin(), data.end(), b);
    int temp = *it1;
    data[it1 - data.begin()] = *it2;
    data[it2 - data.begin()] = temp;
    for (auto c : data)
        cout << c << " ";
    cout << endl;
}
int main(void)
{
    int len;
    cin >> len;
    vector<int> data(len);
    int temp;
    for (int i = 0; i < len; i++)
    {
        cin >> temp;
        data[i] = temp;
    }
    if (data[0] != 1)
    {
        ChangeAndDisplay(data, 1, data[0]);
    }
    else
    {
        int count = 1;
        for (int i = 0; i < len; i++)
        {
            if (data[i] != count)
            {
                ChangeAndDisplay(data, data[i], count);
                return 0;
            }
            count++;
        }
        for (int i = 0; i < len - 2; i++)
        {
            cout << data[i] << " ";
        }
        cout << data[len - 1] << " " << data[len - 2] << endl;
    }
    return 0;
}

发表于 2019-07-19 16:54:17 回复(0)
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    vector<int>v(n);
    for(int i=0;i<n;++i) cin>>v[i];
    int j = -1;
    // 递增的部分直接先跳过
    for(int i=1;i<n;++i){
        if(v[i]>=v[i-1]) continue;
        else{
            j = i;
            break;
        }
    }
    // 整个序列都单调递增 交换最后两个数
    if(j==-1){
        int tmp = v[n-1];
        v[n-1] = v[n-2];
        v[n-2] = tmp;
    }else{
        // 否则从不单调的位置开始往后找一个最小值
        // 从头扫描一个比该值大的位置进行交换
        int MIN = INT_MAX;
        int idx = -1;
        for(int k=j;k<n;++k){
            if(v[k]<MIN){
                idx = k;
                MIN = v[k];
            }
        }
        for(int i=0;i<n;++i){
            if(v[i]>MIN){
                int t = v[i];
                v[i] = MIN;
                v[idx]=t;
                break;
            }
        }
    }
    for(auto t:v)
        cout<<t<<" ";

    return 0;
}
发表于 2020-06-16 21:39:33 回复(0)
# 寻找差最大的一对逆序,记录对应的索引,交换对应元素,输出新序列
# 思路有问题,并不是找逆序,而是尽量保证靠前的数字按顺序排列,越靠前优先级越高
# 如果顺序都正确,交换最后两个数字,因为必须组一次交换(题目要求)
n = int(input())
ln = list(map(int, input().split()))
for i in range(len(ln)):
    if ln[i] != i+1:
        for j in range(i+1, len(ln)):
            if ln[j] == i+1:
                ln[i], ln[j] = ln[j], ln[i]
                break  # 这个不是必要的,但是提前截断循环,节约时间
        break  # 操作且只操作一次
else:   # 所有元素顺序都正确
    ln[-1], ln[-2] = ln[-2], ln[-1]
print(" ".join((map(str, ln))))

发表于 2019-08-11 20:35:43 回复(0)
//1-n有序排列,找出第一个不在原位置的数,找出最小的不在原位置的数,交换这两个数即可
//注意给出的数组若是有序也要交换,此时交换最后两个数即可
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scan=new Scanner(System.in);
        while(scan.hasNext()) {
            int n = scan.nextInt();
            int[]data=new int[n+1];
            for(int i=1;i<n+1;i++){
                data[i]=scan.nextInt();
            }
            boolean flag=false;
            int firstpoi=1;
            int minpoi=0;
            int min=Integer.MAX_VALUE;
            for(int i=1;i<n+1;i++){
                if(data[i]!=i){
                    if(flag==false){
                        firstpoi=i;
                        flag=true;
                    }
                    if(min>data[i]){
                        minpoi=i;
                        min=data[i];
                    }
                }
            }
            if(flag==true){
                data[minpoi]=data[firstpoi];
                data[firstpoi]=min;
            }else{
                int tem=data[n];
                data[n]=data[n-1];
                data[n-1]=tem;
            }
            System.out.print(data[1]);
            for(int i=2;i<n+1;i++){
                System.out.print(" "+data[i]);
            }
        }
    }
}

发表于 2019-05-08 21:20:17 回复(0)
package main

import (
    "fmt"
    "os"
    "bufio"
)

var in=bufio.NewReader(os.Stdin)

func main() {
    var n int
    fmt.Scan(&n)
    arr:=make([]int,n)
    pre,cur:=-1,-1
    for i:=0;i<n;i++{
        fmt.Fscan(in,&arr[i])
        if pre==-1{
            if arr[i]!=i+1{
                pre=i
            }
        }else{
            if arr[i]==pre+1{
                cur=i
            }
        }
    }
    if pre==-1{
        arr[n-2],arr[n-1]=arr[n-1],arr[n-2]
    }else{
        arr[pre],arr[cur]=arr[cur],arr[pre]
    }
    for _,x:=range arr{
        fmt.Printf("%v ",x)
    }
}

发表于 2023-03-18 10:44:41 回复(0)
n, a = int(input()), list(map(int, input().split()))
for i in range(n):
    if a[i] != i + 1:
        a[a.index(i + 1)], a[i] = a[i], i + 1
        break
    if i == n - 1: a[i - 1], a[i] = a[i], a[i - 1]
print(' '.join(map(str, a)))

发表于 2020-07-16 15:30:23 回复(0)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    int N;
    cin>>N;
    vector<int> rec(N);
    for(int i=0;i<N;i++)
    {
        cin>>rec[i];
    }
    if(is_sorted(rec.begin(),rec.end()))
    {
        for(int i=0;i<N-2;i++)
        {
            cout<<rec[i]<<' ';
        }
        cout<<*(rec.end()-1)<<' '<<*(rec.end()-2)<<endl;
    }
    else
    {
    vector<int> orin;
    copy(rec.begin(),rec.end(),inserter(orin,orin.begin()));
    sort(rec.begin(),rec.end());
    for(int i=0;i<N;i++)
    {
        if(rec[i]!=orin[i])
        {
            auto flag=find(orin.begin(),orin.end(),rec[i]);
            *flag=orin[i];
            orin[i]=rec[i];
            break;
        }
    }
    for(auto s:orin)
    {
        cout<<s<<' ';
    }
    }
}

发表于 2019-09-10 21:27:45 回复(0)
如果给出的序列本身就是最小序列,也就是1,2,3……n-1,n
由于题目说必须要进行一次交换,所以只能交换n-1 和 n

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] a = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            a[i] = scanner.nextInt();
        }
        solve(n, a);
        for (int i = 1; i <= n - 1; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println(a[n]);
    }
    private static void solve(int n, int[] a) {
        for (int i = 1; i <= n; i++) {
            if (a[i] == i) {
                continue;
            }
            for (int j = i + 1; j <= n; j++) {
                if (a[j] == i) {
                    a[j] = a[i];
                    a[i] = i;
                    return;
                }
            }
        }
        a[n] = n - 1;
        a[n - 1] = n;
    }
}

发表于 2019-05-23 16:28:29 回复(0)
#include <iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;

bool kmp(const string& s1,const string& s2){
    if(s1.size()<s2.size())
        return 1;
    else if(s1.size()==s2.size() ){
        return s1<s2;
    }
    else
        return 0;
}
int main(){
    int n;
    cin>>n;
    vector<string>v,vec;
    while(n--){
        string s;
        cin>>s;
        v.push_back(s);
    }
    vec=v;
    sort(vec.begin(),vec.end(),kmp);
    bool u=0;           //  标志位、记录是否进行了交换操作;
    for(int i=0,j=0; i<v.size() && j<vec.size();i++){
        if(v[i]==vec[j]){
            j++;
        }
        else{
            int p=0;
            for(int x=i+1;x<v.size();x++){
                if(v[x]==vec[j]){
                    u=1;
                    p=x;
                    break;
                }
            }
            swap(v[p],v[i]);
            break;
        }
    }
    if(u==0){   //  若未进行交换操作,说明原序列为一个升序; 按题意仍需交换 以满足目的;
        int len=v.size();
        swap(v.back(),v[len-2]);
    }
    for(int i=0;i<v.size();i++)
        cout<<v[i]<<" ";
    return 0;
}
发表于 2019-05-10 16:20:53 回复(0)
#AC80%,超时
while(True):
    def swap(data, l, r):
        if(l>=r):
            return
        index = data[l:r].index(min(data[l:r])) + l
        flag = False
        for i in range(l, index):
            if(data[i] > data[index]):
                temp = data[i]
                data[i] = data[index]
                data[index] = temp
                flag = True
                break
        if(not flag):
            swap(data, index + 1, r)
            
    try:
        n = int(input())
        data = list(map(int, input().split()))
        swap(data, 0, n)
        for n in data:
            print(n, end = ' ')
    except:
        break
发表于 2019-03-28 10:13:01 回复(0)
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

int a[100001], pos[100001];

void myPrint(int n){
    for (int i=1; i<=n; ++i){
        printf("%d", a[i]);
        if (i<n) printf(" ");
    }
}

int main(){
    int n, x;
    
    scanf("%d", &n);
    for (int i=1; i<=n; ++i){
        scanf("%d", &x);
        a[i] = x;
        pos[x] = i;
    }
    
    for (int i=1; i<=n; ++i)
    if (a[i] != i){
        x = pos[i];
        a[x] = a[i];
        a[i] = i;
        myPrint(n);
        return 0;
    }
    
    a[n] = n-1;
    a[n-1] = n;
    myPrint(n);
    
    return 0;
    
}
发表于 2019-03-09 17:36:59 回复(0)

问题信息

难度:
12条回答 2881浏览

热门推荐

通过挑战的用户

查看代码