Android学习,冒泡排序和优化

Android学习,冒泡排序和优化


最近在学习( 所以有错请留言,我会修改并偷师),也在面试,今天就说一说遇到的一个面试题,也算是加深印象。

题目是这样的:按需求写出冒泡排序,要求从前比到后,相邻的数两两进行比较,如果前一个数比后一个数大,那么两个数互换,直到最后一个数。

这不就是简单的冒泡吗?没问题,我们可以很快的写出来如下的代码:

 public int[] bubbleSort(int[] arrays) {
        if (arrays.length == 0)
            return arrays;
        if (arrays.length == 1)
            return arrays;
        int length = arrays.length - 1;
        for (int i = 0; i < length; i++) 
        {
            for (int j = 1; j <= length - i; j++) {
                if (arrays[j - 1] > arrays[j]) {
                    swap(arrays, j - 1, j);                                    
                }
            }
        }
        return arrays;
    }

    private void swap(int[] arrays, int arg1, int arg2) {
        int temp = arrays[arg1];
        arrays[arg1] = arrays[arg2];
        arrays[arg2] = temp;
    }

完成,手撸冒泡so easy
但是冒泡号称最简单的排序算法,可不是浪得虚名,所以这道面试题肯定没这么简单!

面试官:那么我增加一个需求:当传入有序数组例如{1,2,3,4,5}的时候,要求你跳出循环,请在原有代码上进行修改

我就知道没这么简单,但是仔细想想也难不倒我,比划了几下,我们可以得到下面的代码:

 public int[] bubbleSort(int[] arrays) {
        if (arrays.length == 0)
            return arrays;
        if (arrays.length == 1)
            return arrays;
        int length = arrays.length - 1;
        for (int i = 0; i < length; i++) 
        {
            boolean flag = true; //新增代码
            for (int j = 1; j <= length - i; j++) {
                if (arrays[j - 1] > arrays[j]) {
                    swap(arrays, j - 1, j);
                    flag = false; //新增代码                
                }
            }
            if (flag) return arrays;//新增代码
        }
        return arrays;
    }

    private void swap(int[] arrays, int arg1, int arg2) {
        int temp = arrays[arg1];
        arrays[arg1] = arrays[arg2];
        arrays[arg2] = temp;
    }

关于为什么这么写,我就先不解释了,你仔细看看思考一下应该能明白(仔细看看才能发现我的错误,万一有错呢
写出来之后还没等我得意,面试官又是一个需求砸到了我的脸上:
有一个巨大的数组,例如{5,7,4,3,6,1,……,998,999,1000},这个数组是特殊的,前面一部分是无序数组,而从某一个位置开始,变成有序数组,现在要求我进行优化。

什么!?这是什么狗屁要求?!我Tm……也不能怎么样,没办法,人在屋檐下,而且这个需求也很合理,那就改吧。
还是在原有代码上进行修改:

    public int[] bubbleSort(int[] arrays) {
        if (arrays.length == 0)
            return arrays;
        if (arrays.length == 1)
            return arrays;
        int position = 1;
        int length = arrays.length - 1;
        boolean isfirst = true; //新增代码
        for (int i = 0; i < length; i++) 
        {
            boolean flag = true;
            for (int j = 1; j <= length - i; j++) {
                if (arrays[j - 1] > arrays[j]) {
                    swap(arrays, j - 1, j);
                    flag = false;
                    position = position > j ? position : j;
                }
            }
            /*新增代码*/
            if (isfirst) {
                isfirst = false;
                length = position;
            }
            if (flag) return arrays;
        }
        return arrays;
    }

    private void swap(int[] arrays, int arg1, int arg2) {
        int temp = arrays[arg1];
        arrays[arg1] = arrays[arg2];
        arrays[arg2] = temp;
    }

那么这个需求也完成了,我们来详细说一下时间复杂度的问题(本人之前也没太注意过算法和时间复杂度。关于时间复杂度都是自己分析+查阅别人的资料,有错误请指正,感谢),我查阅别人的博客得到分析如下:
冒泡排序的时间复杂度:(n-1)(n+1)/2 =(n^2 -1)/2 所以时间复杂度为(n^2)

这里我发现了一个问题,我在内层循环中加入计数器count,并输入一个n=17的倒序数组来模拟冒泡最坏的情况,打印出的count为136 ,如果套用别人的公式则应该是144次 ,这不能够啊!不应该啊!

别人的肯定不会错(因为看到好几个都是这个公式),那就是我错了呗? 我开始排查自己的代码,输入几个不同的测试用例之后,发现一直不能套进公式。为什么?我的冒泡和别人的不一样?

由于时间关系(AM2:00)脑子里一片混乱,我选择睡一觉再说(当然这部分工作是回家之后做的),醒来之后突然我发现了一个问题,就是,别人的外层循环i从1开始循环,内层j从0开始循环,而我则正好反过来(因为我做了length-1)。

发现问题就好办,那丢掉其他人的东西,从代码开始分析:
首先外层循环会循环n-1次(就是length-1),内层循环最多执行n-1次,最少执行1次,那么平均下来就是(n-1+1)/2, 时间复杂度就**是(n-1)n/2 = (n^2-n)/2。 **
把n=17套进去算一下(17
17-17)/2 =17*16/2 = 136
好嘛,终于对上了!虽然写法上让细节有区别,不过冒泡的时间复杂度始终还是O(n^2)
关于我遇到的这个冒泡的面试题算是说完了,其实你还可以扩展一下,比如,一个大数组,前面有序,中间无序,后面有序怎么优化? 当然了,冒泡再优化他还是冒泡,不过难保不会有面试官问,对不对?

你可能感兴趣的:(Android学习,冒泡排序和优化)