首页 > 试题广场 >

有趣的排序

[编程题]有趣的排序
  • 热度指数:8669 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
度度熊有一个N个数的数组,他想将数组从小到大 排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?

输入描述:
首先输入一个正整数N,接下来的一行输入N个整数。(N <= 50, 每个数的绝对值小于等于1000)


输出描述:
输出一个整数表示最少的操作次数。
示例1

输入

4
19 7 8 25

输出

2
找的需要移动的数的数量就可以了。
import java.util.Arrays;
import java.util.Scanner;
public class Main4 {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();
		int[] in=new int[n];
		for(int i=0;i<n;i++) 
			in[i]=sc.nextInt();
		int[] in2=in.clone();
		Arrays.sort(in2);
		int count=0;
		for(int i=0;i<n;i++)
			if(in[i]==in2[count]) 
				count++;
		System.out.println(n-count);
	}
}
编辑于 2018-03-14 13:34:11 回复(0)
// 只需要扫描2遍就能完成
// 交换发生的情况应该是:
// 如果当前数之后有比自己小的数,说明当前数是逆序数,这个时候需要把当前数扔到末尾,操作次数+1;
// 另外一种情况是虽然当前数不是逆序数, 但是前面有逆序数比自身小,那么操作次数也需要+1,因为之前的逆序数被扔到后面去了
// 之后,当前数肯定要被扔一次。
import java.util.*;
import java.io.*;
 
public class Main {   
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int count = scan.nextInt();       
        if(count < 0) {
            return;
        }
        inti = 0;
        int[] nums = new int[count];
        while(scan.hasNextInt() && i < count) {
            nums[i] = scan.nextInt();
            ++i;
        }
        scan.close();
        
//为了快速判断后面是否有比自己小的数,使用了一个栈保存从后往前,
//到每一个位置的最小值,这样可以快速判断逆序数。这里遍历了一遍
        int res = 0;
        Stack<Integer> reverMin = newStack<Integer>();
        reverMin.push(nums[count-1]);       
        i = count - 2;
        for(; i > 0; --i) {
            if(nums[i] < reverMin.peek()) {
                reverMin.push(nums[i]);
            }
            else{
                reverMin.push(reverMin.peek());
            }
        }
        //逆序或者前面有小于自身的逆序数
        int min = Integer.MAX_VALUE;
        for(i = 0; i < count; ++i) {
            if(!reverMin.empty() && nums[i] > reverMin.pop()) {
                ++res;
                min = Math.min(min, nums[i]);
                continue;
            }
            if(nums[i] > min) {
                ++res;
            }           
        }
         
        System.out.println(res);
    }
}

发表于 2017-10-28 16:23:51 回复(0)
首先考虑策略:先把数组排好序,然后从小到大检测相邻的一对数的各自原始位置,如果a<b,但是原数组中a在b的后面,那就必须将b移到最后的位置,然后更新b的原始位置,按照这样的过程遍历一遍,最后就会排好序。这样必然是最少的操作,因为是从小到大检测的,小的数必然会被先移到后面。
具体实现时,采用HashMap,key为数组的数,value为当前位置,实际把一个数移到最后一位,不需要实际移位操作,只需要把value顺序加一,就代表移到最后了。

import java.util.Arrays;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
int n = Integer.parseInt(scanner.nextLine());
String[] strings = scanner.nextLine().split("\\s+");
int[] a = new int[n];
HashMap<Integer, Integer> map = new HashMap<>();
int i;
for (i=0;i<n;i++){
a[i]= Integer.parseInt(strings[i]);
map.put(a[i], i);
}
Arrays.sort(a);
int sum=0;
for (int j=0;j<n-1;j++){
if (map.get(a[j+1]) < map.get(a[j])){
map.put(a[j+1],i++);
sum++;
}
}
System.out.println(sum);
}
}
发表于 2017-04-28 12:42:25 回复(4)