zoukankan      html  css  js  c++  java
  • 【每天一道算法题】时间复杂度为O(n)的排序

    有1,2,……一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度为O(1),使用交换,而且一次只能交换两个数。

    这个是以前看到的算法题,题目不难。但是要求比较多,排序算法中,时间复杂度为O(n)就是基数排序了。

    现在介绍两种解法:

    解法一:用数组特性——下标实现交换

    扫描数组,每次arr[i],arr[arr[i]-1]交换,如果arr[i]=i+1,则什么都不做。这样交换一次保证一个数字被放到它应该被放置的位置上。最后数组有序。

    #include <vector>
    #include <iostream>
    using namespace std;
    
    void swap(int& a, int& b){
        a^=b;
        b^=a;
        a^=b;
    }
    vector<int>& Sort(vector<int>& vec1){
        if(vec1.size()==1)
            return vec1;
        for(int i=0;i<vec1.size();){
            if(vec1[i]==i+1)
                i++;
            else swap(vec1[i],vec1[vec1[i]-1]);
        }
        return vec1;
    }
    int main(){
        int arr[9]={1,3,7,2,9,6,8,5,4};
        vector<int> vec2(arr,arr+9);
        Sort(vec2);
        for(int i=0;i<vec2.size();i++)
            cout<<vec2[i]<<"    ";
        return 0;
    }

    上面的题目是每个数字只出现一次,如果不限制出现的次数,要求时间复杂度是O(n),空间复杂度为O(1)又该怎么做,给出数字的最大范围假设为65536。

    这个题用桶排序应该可以做。

    解法二:利用count[65536](和n无关,空间复杂度为O(1))数组记录出现的次数

    那么假设有下面这些数字:

    100
    200
    300
    119
    0
    6
    ...
    那么对于每个这个数字,都做在count中记录一下:
    100 => count[100]++
    200 => count[200]++
    300 => count[300]++
    119 => count[119]++
    0 => count[0]++
    6 => count[6]++
     
    最后,遍历一边所有这些数字就可得到0~65535每个数字的个数(在count数组中),然后再顺序遍历count数组,count[n] = m,则输出m个n,(比如说有count[3] = 2, 那么说明有2个数字3),依次输出,最后可得结果。
  • 相关阅读:
    VUE中实现iview的图标效果时遇到的一个问题
    VUE中获取url中的值
    VUE的生命周期
    基于Vue的省市区三级联动插件
    父子组件通讯(2)
    vue中声明式导航和编程式导航
    java Calendar(日历)
    java Date
    java equals
    java 内部类
  • 原文地址:https://www.cnblogs.com/LUO77/p/5780187.html
Copyright © 2011-2022 走看看