排序算法

1. 插入排序:平均On2,最好On,最坏On2,稳定

  1. 提取当前元素作为基准,对当前位置前面区间进行以当前元素为基准进行升序排列,排序完成后将当前元素放入区间的后一个位置

     private static void insertSort(int[] nums) {
         for(int i=1;i<nums.length;i++){
             int insertIndex;
             int insertNum = nums[i];
    
             //以insertNum为基准对[0,insertIndex-1]区间进行升序排序
             for(insertIndex=i-1;insertIndex >= 0 && nums[insertIndex] > insertNum;insertIndex--){
                 nums[insertIndex+1] = nums[insertIndex];
             }
    
             //将insertNum插入到排序好的序列的后一个
             nums[insertIndex+1] = insertNum;
         }
     }

2. 冒泡排序:平均On2,最好On,最坏On2,稳定

  1. 前后比较,前比后大,交换前后
     private static void bubbleSort(int[] nums) {
         for(int i=0;i<nums.length-1;i++){
             for(int j=0;j<nums.length-1-i;j++){
                 //前后比较,前比后大,交换前后
                 if(nums[j] > nums[j+1]){
                     swap(nums,j,j+1);
                 }
             }
         }
     }

3. 选择排序:平均On2,最好On2,最坏On2,不稳定

  1. 选择当前元素为基准,对后面的区间查找最小值,交换当前和最小值
     private static void selectSort(int[] nums) {
         for(int i=0;i<nums.length;i++){
             int min = i;
             for(int j=i+1;j<nums.length;j++){
                 if(nums[j] < nums[min]){
                     min = j;
                 }
             }
             if(min != i){
                 swap(nums,min,i);
             }
         }
     }

4. 归并排序:平均Onlogn,最好Onlogn,最坏Onlogn,稳定

    private static void MergeSort(int[] nums, int start, int end) {
        if(start == end){
            return;
        }

        int middle = start + (end - start)/2;
        //递归排序左右
        MergeSort(nums,start,middle);
        MergeSort(nums,middle+1,end);
        //合并左右
        Merge(nums,start,middle,end);
    }

    private static void Merge(int[] nums, int start, int middle, int end) {
        int[] temp = new int[end - start + 1];
        int index = 0;

        int index1 = start;
        int index2 = middle+1;

        while(index1 <= middle && index2 <= end){
            if(nums[index1] < nums[index2]){
                temp[index++] = nums[index1++];
            }else{
                temp[index++] = nums[index2++];
            }
        }
        while(index1 <= middle){
            temp[index++] = nums[index1++];
        }
        while(index2 <= end){
            temp[index++] = nums[index2++];
        }
        for(int i=0;i<temp.length;i++){
            nums[i+start] = temp[i];
        }
    }

5. 快排:平均Onlogn,最坏On2(冒泡),最好Onlogn,不稳定

  1. 以第一个数为基准,比基准数小的,排在基准数左边,比基准数大的,排在基准数右边。递归再对这两个数组进行快排

     private static void quickSort(int[] nums, int start, int end) {
         if(start > end){
             return;
         }
    
         int pivot = getPivot(nums,start,end);
         //根据本次基准数,排序基准数左右序列
         quickSort(nums,start,pivot-1);
         quickSort(nums,pivot+1,end);
     }
    
     private static int getPivot(int[] nums, int start, int end) {
         int pivot = nums[start];
         int left = start;
         int right = end;
    
         while(left <= right){
             while(left <= right && nums[left] <= pivot){
                 left++;
             }
             while(left <= right && nums[right] > pivot){
                 right--;
             }
             if(left <= right){
                 swap(nums,left,right);
             }
         }
         //基准数归位,返回基准数
         swap(nums,start,right);
         return right;
     }

7. 堆排:平均Onlogn,最好Onlogn,最坏Onlogn,不稳定

  1. 建堆:par和cur比较,如果par比cur小,交换,cur=par

  2. 排序:提取nums[0],将nums[0]替换nums[index],提取left和right,判断left越界,提取left为max,比较max和right,比较max和cur

     public static void main(String[] args) {
         int[] nums = new int[]{10,3,5,6,7,0,2};
    
         //建堆
         for(int i=0;i<nums.length;i++){
             create(nums,i);
         }
    
         //排序
         int [] result = new int[nums.length];
         int len = result.length-1;
         for(int i=nums.length-1;i>=0;i--){
             result[i] = poll(nums,len--);
         }
    
         for(int i : result){
             System.out.println(i);
         }
     }
    
     private static int poll(int[] nums, int index) {
         int result = nums[0];
         nums[0] = nums[index];
         int cur = 0;
         while(true){
             int left = cur*2 + 1;
             int right = cur*2 + 2;
             //左子树越界
             if(left >= index){
                 break;
             }
             //右子树和max比较
             int max = left;
             if(right <= index && nums[max] < nums[right]){
                 max = right;
             }
             //cur和max比较
             if(nums[cur] < nums[max]){
                 swap(nums,cur,max);
             }else{
                 break;
             }
             cur = max;
         }
         return result;
     }
    
     private static void create(int[] nums, int index) {
         //当前节点
         int cur = index;
         while(cur > 0){
             //父节点
             int par = (cur-1)/2;
             //如果当前比父节点大,交换
             if(nums[par] < nums[cur]){
                 swap(nums,par,cur);
             }else{
                 break;
             }
             cur = par;
         }
     }
全部评论

相关推荐

写下这篇文章的时候,我正坐在从学校飞往北京的飞机上。就在今天,我的秋招终于算是有了结论,一共60场面试,拿到了字节百度美团等10+大厂offers,最终确认了腾讯给的机会。同时给我的这三个月,这三年以及从今天往前的所有人生做了个结。这句话写的真好,为什么这么说呢?本来挺久之前我就想写点什么,有特别多想记录的,从选择这个专业到选择这个岗位,从科研的疲惫到未来生活的期待,但总感觉这样写没个纲,乱成一团。直到我今天正式在系统中点击了三方的确认,我才突然发现这种感觉就是“不可逃避的结束”在向我走来,于是纲便有了。首先是这三个月的结果吧,或者换句话说,其实是秋招的结果。从我硕士选择了强化学习的研究方向,我就知道并不会有太多的岗位。从试错中学习,这听起来很符合人类的学习方式,但实际场景中哪来那么多试错的成本?除了游戏产业和机器人行业,我想不到特别对口的赛道,而这两个行业国内又只有寡头,让我望而生畏。整个秋招,我没法像学后端开发的同学一样投递大量的简历,我没法像学大模型的同学一样是时代的香饽饽,我只能盯着那几家公司去投,或者想方设法的在别的不太相关的算法岗上沾沾边。方向是大于努力的,但努力一定不是不重要的。秋招整体对我来说还算顺利,前文就自然变成了只有我自己懂的无病呻吟,不再赘述。从结果来说,我的秋招是非常成功的,至少我自己是满意的。命运给了我很大的惊喜,我从未想过能够在这次有多个远超期待的offer,所以我如今是心满意足。虽说很多事都是焉知非福吧,但对口的工作内容,熟悉的工作环境,我一定不会后悔。我就是这样,毕竟让我在做一百次选择也不会变,那为什么要在不可预测的未来后悔。然后是三年,三年即将过去,我的硕士生涯来到了最后一章。回想过往,我在其中反复感受井底之蛙的狭隘。从我在二十多个四点睡的凌晨产出的论文初稿开始,链式反应就这样发生了。把论文投出去,我发了一篇很长的朋友圈,那时候觉得压力真的好大,尽管其实根本没人要求我什么。那时,我第一次觉得我比本科毕业时的自己进步了太多,可以独当一面了。然后去了北京自所交流,尽管大多的时间都在修改那篇返稿的文章,但也在不一样的平台中见识了人外有人的世界。回来后,我第二次觉得自己有了很大的进步,而鄙夷去北京前的自己是如此短浅。那是11月,我开始纠结到底未来该从事开发岗还是算法岗,但时间并没有给我机会。我偷懒了,两个月根本没有做任何开发岗的准备,于是只能硬闯算法。期间只有那篇论文中了让我稍微有些自信,毕竟只有两周的理论准备时间让我心里太虚了,这甚至还算上了刷题的时间。第一面就是最想去的公司,我甚至紧张到大脑一片空白。好在后面算是有惊无险,拿到了腾讯给我的实习机会。去腾讯工作的时间是幸福的,组里氛围也很好,在公司获得的提升我觉得甚至超过了我在学校一年的量。毕竟做算法,思维的敏捷度和见识广度都是如此重要。看着同事前辈们的工作能力,和工业级的项目架构,我又一次不由得感叹曾经自己的狭隘。于是每天我只睡五小时,忙完工作忙学校,每每想到这里,我也不觉得我的成功是侥幸了。我真的建议大家离开自己舒适的环境到外面看看,鸡头或许真的不如凤尾。硕士是一个连锁反应最直接,最有力的时期。高考失利或许还能补救,考研没上岸还有第二次机会,但就业前这一年,努力就是会有回报,就一定会体现在结果中,没有侥幸。最后,也是我最想聊的。十九年的学生生涯终于快要画下句号,我其实一直觉得非常梦幻。我能回忆起每一个瞬间,有小学六年级遇到的很有个性的数学老师,有考上重点中学的快乐,有中考和提前高考而大失败的难受,有本科比赛的每个通宵的焦虑,有保研出现差错的绝望,有刚读研高压之下的崩溃。但这篇长文不会再有更多的剧情了,每个故事都让我无限回味,成为了我一生中最宝贵的财富。这些瞬间组成了我。我父亲说我是一个总抓不住机会的人,确实有很多别人没有的机会摆在我面前,我都错过了。但我心中的热爱始终没有错过,我觉得这对我来说是幸运且幸福的。我非常爱打游戏,从初中开始学编程,第一个目的就是做出属于自己的游戏,做了很多小游戏发在班级群里,被人厌烦。高中自己买了unity的书,想做自己的游戏,无奈连网络的基本知识都不懂,无功而返。到了大学,我又被强化学习吸引,我想知道能不能让人工智能来帮我打游戏呢?这一整条线我没有放弃过,拿到了游戏算法offer,我真的特别特别开心。人不是一直成功的,我经历过的失败远超过成功10倍,但那让我知道成功来之不易,让我知道失败是生活常态,让我知道真正的怯懦不是不敢失败,而是不敢尝试。言尽于此,这些都“不可逃避的结束”了。追风赶月莫停留,平芜尽处是春山。
肖先生~:追风赶月莫停留,平芜尽处是春山,passion!
我的秋招日记
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务