4.排序算法

/*
c++ 中 std::sort()使用了快速排序的算法,下面看下它的实现算法
快速排序的基本思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的数字均比另一部分数字小,则可分别对这两部分进行排序,以达到整个序列有序。
算法描述:https://www.bilibili.com/video/BV1at411T75o?from=search&seid=3870102746514763528
    1.选定Pivot中心轴(随机选取,一般选数组第一个值为Pivot)
    2.从后向前遍历,将大于Pivot中心轴的数字放在Pivot的右边
    3.从前向后遍历,将小于Pivot中心轴的数字放在Pivot的左边
    4.分别对左右子序列重复前三步
*/
void quick_sort(vector<int> &nums, int l, int r){   //l=0,r=nums.size()
    if(l+1 >= r) return;
    int first=l, last=r-1, key=nums[first];
    while (first < last){   //循环完会把nums分成两部分,左边小于k,右边大于k
        while(first < last && nums[last] >= key){   //数组从后向前查找小于key的值,交换至左边
            --last;
        }
        nums[first] = nums[last];
        while(first < last && nums[first] <= key){  //数组从前向后查找大于key的值,交换至右边
            ++first;
        }
        nums[last]=nums[first];
    }
    nums[first] = key;  //此时的first已不是0
    quick_sort(nums, l, first);
    quick_sort(nums, first+1, r);
}

//215.数组中第k大元素
/*
K-th Element描述:在一个未排序的数组中,找到第k大的数字。
输入输出:输入一个数组和一个目标值k,输出第k大的数字。题目默认一定有解。
题解:快速选择一般用于求解k-th Element问题,可以在O(n)时间复杂度,O(1)空间复杂度完成求解工作。快速选择的实现和快速排序相似,不过只需要
找到第k大的枢(pivot)即可,不需要对其左右边再进行排序,只需在范围内选择一边递归即可。与快速排序一样,快速选择一般需要先打乱数组,否则最坏
情况下时间复杂度为O(n^2),我们这里为了方便省略掉了打乱的步骤。
*/

//主函数
int findKthLargest(vector<int>& nums, int k) {
    int l=0, r=nums.size(), target=nums.size()-k;
    while(l<r) {
        int mid =quickSelection(nums, l, r);
        if(mid == target) {
            return nums[mid];
        }
        if (mid < target){  //二分思想
            l=mid+1;
        } else {
            r=mid-1;
        }
    }
    return nums[l]; //l=r
}
//辅函数-快速选择
int quickSelection(vector<int>& nums, int l, int r) {
    int first=l,last=r-1,key=nums[first];
    while(first < last){
        while(first<last && key <= nums[last]){
            --last;
        }
        nums[first]=nums[last];
        while(first<last && key >= nums[first]){
            ++first;
        }
        nums[last]=nums[first];
    }
    nums[first]=key;
    return first;
}


//347.前k个高频元素 桶排序
/*
给定一个数组,求前k个最频繁的数字。
input:nums=[1,1,1,2,2,3,4], k=2
output:[1,2]
题解:顾名思义,桶排序的意思是为每个值设立一个桶,桶内记录这个值出现的次数(或其他属性),然后对桶进行排序。针对样例来说,我们先通过桶排序得到
四个桶[1,2,3,4],它们的值分别为[4,2,1,1],表示每个数字出现的次数。
紧接着我们对桶的频次进行排序,前k大桶即是前k个频繁的数。
*/
vector<int> topKFrequent(vector<int>& nums, int k){
    unordered_map<int, int> counts;
    int max_count = 0;
    for(const int & num:nums){
        max_count = max(max_count, ++counts[num]);  //map统计频次,找出最大的频次
    }

    vector<vector<int>> buckets(max_count+1);
    for(const auto & p : counts){
        buckets[p.second].push_back(p.first);
    }

    vector<int> ans;
    for(int i=max_count; i >= 0 && ans.szie() < k; --i){
        for (const int & num:buckets[i]){
            ans.push_back(num);
            if(ans.size() == k){
                break;
            }
        }
    }
    return ans;
}

 

上一篇:排序算法(二):快速排序


下一篇:关于“The import org.junit.jupiter cannot be resolved”出现错误