有趣的排序新解(百度2017春招第四题)

40 篇文章 3 订阅
3 篇文章 0 订阅

关于百度2017年校招排序题,网上有好多解法,比如利用新建另一个数组存中间数据,还有利用Arrays.sort对数组进行排序等等方法,笔者的解法如下:

[编程题] 有趣的排序
时间限制:1秒
空间限制:32768K
题目描述:度度熊有一个N个数的数组,他想将数组从小到大排好序,但是萌萌的度度熊只会下面这个操作:
任取数组中的一个数然后将它放置在数组的最后一个位置。
问最少操作多少次可以使得数组从小到大有序?
输入描述:
首先输入一个正整数N,接下来的一行输入N个整数。(N <= 50, 每个数的绝对值小于等于1000)

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

输入例子:
4
19 7 8 25

输出例子:
2

解题思路:
总原则:
1)空间有限制,如果想空间最优,则不要新开数组,要在原数组中操作为最好;
2)时间有限制,如果想时间最优,宜用好原数组中已有的排序;
题目分析:
度度熊对N个数的数组进行排序,想从小到大排好,并且他只能从数组中任选一个数将它放在最后一个位置,由例子19 7 8 25,最好的方法是利用原数组中7,8的有序,将19移到最后,形成数组7 8 25 19,
之后再将25移到最后,形成7 8 19 25,共需操作2次;将例子扩展一下,数量为5,即19 7 8 25 23 ,数组中原有的升序是7 8 23 ,第一次将19移动到最后,变为7 8 25 23 19,第二次将23移动到最后,变为7 8 25 19 23,第三次将25移到最后,变为7 8 19 23 25,共需操作3次;将例子变形为 23 7 8 19 25 ,第一次移动23,第二次移动25,共操作2次。由以上三个例子分析,可以将求解方法转化为移动非序整数到数组末尾与对新数组进行冒泡排序,分为2步;第一步,从左到右遍历数组,将非递增的整数依次排在数组最后位置,并记录移动次数,并将其它整数前移;第二步对新的数组进行冒泡排序,并记录移动的整数个数,两次移动的数量之和即为最少操作次数。

算法特点:此算法没有开辟新数组,空间最优;利用数组原有的排序,并结合冒泡排序,效率也最优;

代码见下

public static void main(String[] args){
    System.out.println("请输入整数数量,然后按回车确认:");
    Scanner input = new Scanner(System.in);
    int n = input.nextInt();
    int[] arrayA=new int[n];
    System.out.println("请依次输入"+n+"个正整数,并依次回车确认:");
    for (int i = 0; i < n; i++)
    {
        arrayA[i] = input.nextInt();
    }
    //int[] arrayA=new int[]{19,7,8,25};
    int aLen=arrayA.length;
    int iNum=aLen;
    int m=0;
    System.out.println("原数组:");
    for (int j=0;j<aLen;j++)
        System.out.print(arrayA[j]+",");
    //从左到右利用数组中原有的有序升序数列,将非升序的字符移动到数组尾部,并记录移动的字符数量
    for (int i=0;i<aLen-1-m;i++) {
        if (arrayA[i]>arrayA[i+1]){
            int temp=arrayA[i];
            for(int k=i;k<aLen-1;k++){
                arrayA[k]=arrayA[k+1];
            }
            arrayA[aLen-1]=temp;
            //移动字符的数量
            m++;
        }
    }
    System.out.println("");
    System.out.println("调整后含部分有序数的数组:");
    for (int j=0;j<aLen;j++)
        System.out.print(arrayA[j]+",");
    System.out.println("");

    //冒泡排序
    for (int i=0;i<aLen-1;i++){
        for (int j=0;j<aLen-1-i;j++){
            if (arrayA[j]>arrayA[j+1]){
                int temp=arrayA[j];
                arrayA[j]=arrayA[j+1];
                arrayA[j+1]=temp;
                //累加冒泡排序中移动的字符数量
                m++;
            }
        }
    }
    System.out.println("冒泡排序后有序的数组:");
    for (int j=0;j<aLen;j++)
        System.out.print(arrayA[j]+",");
    System.out.println("");
    System.out.println("最少移动次数为:"+(m));

}

例1演示:
在这里插入图片描述
例2演示:
在这里插入图片描述
例3演示:
在这里插入图片描述

哪位同学如果有更好的解法,欢迎接龙.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值