刷题训练之分治快排

简介: 刷题训练之分治快排

> 作者:დ旧言~

> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:熟练掌握分治快排算法。

> 毒鸡汤:学习,学习,再学习 ! 学,然后知不足。

> 专栏选自:刷题训练营

> 望小伙伴们点赞👍收藏✨加关注哟💕💕



🌟前言分析

       最早博主续写了牛客网130道题,这块的刷题是让同学们快速进入C语言,而我们学习c++已经有一段时间了,知识储备已经足够了但缺少了实战,面对这块短板博主续写刷题训练,针对性学习,把相似的题目归类,系统的刷题,而我们刷题的官网可以参考:


⭐知识讲解

基本思想:


这个算法在我们学习数据结构中八大排序之快排,但这个快排比起数据结构中的快排简单不少,这个算在C语言中我们也涉及到了,如果大家对这个算法比较陌生的话,可以参考下面两篇博客,一个是数据结构中的另一个是C语言中的:


数据结构:手撕各种排序

C语言:快快快快快快快快快快排


特点:

我们下面题目所采用的方法都是三路划分法思想,这也和我们的标题分治不谋而合。

大致做题流程:

做题前一定要先画图,在写代码,如果能自己画出图来写代码轻松不少。


🌙topic-->1

题目链接:1.分治快-



题目分析:

题目意思比较简单,把数组中的0  1  2排序。

算法原理:

  • 解法:采用三指针

图解:



细节处理:

left需要指向为 - 1,循环条件为 i < right.

代码演示:

class Solution 
{
public:
    void sortColors(vector<int>& nums) 
    {
        int n = nums.size();
        // 定义三个指针
        int left = -1,right = n,i = 0;
        // 循环
        while(i < right) // 细节
        {
            if(nums[i] == 0) swap(nums[++left],nums[i++]);
            else if(nums[i] == 1) i++;
            else swap(nums[--right],nums[i]);
        }
    }
};


🌙topic-->2

题目链接:2.排序数组



题目分析:

给你一个整数数组 nums,请你将该数组升序排列。(解法有很多,我们采用快速排序算法)

算法原理:

  • 解法:采用快速排序算法(三指针)

图解:



细节处理:

  • 递归结束标志是 l >= r

代码演示:

class Solution 
{
public:
    vector<int> sortArray(vector<int>& nums) 
    {
        srand(time(NULL)); // 种下随机种子
        qsort(nums, 0, nums.size() - 1); // 调用快速排序
        return nums; // 返回数组
    }
 
    // 快排
    void qsort(vector<int>& nums,int l,int r)
    {
        if(l >= r) return; // 递归结束条件
 
        // 数组分三块
        int key = getRandom(nums, l, r); // 找一个对比值
        int i = l,left = l - 1,right = r + 1; // 三个指针
        // 循环
        while(i < right)
        {
            if(nums[i] < key) swap(nums[++left],nums[i++]);
            else if(nums[i] == key) i++;
            else swap(nums[--right],nums[i]);
        }
 
        // 划分三个区域 [l ,left]  [left + 1, right - 1]  [right, r]
        qsort(nums ,l ,left);
        qsort(nums ,right ,r);
    }
 
    // 找对比值
    int getRandom(vector<int>& nums ,int left,int right)
    {
        int r = rand();
        return nums[r % (right - left + 1) + left];
    }
};


🌙topic-->3

题目链接:3. 数组中的第K个最大元素



题目分析:

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。(你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。)


算法原理:

  • 解法:采用快速排序算法(三指针)

 图解:



细节处理:

  • 递归结束标志是 l == r

代码演示:

class Solution 
{
public:
    int findKthLargest(vector<int>& nums, int k) 
    {
        srand(time(NULL));// 种下随机种子
        return qsort(nums, 0 ,nums.size() - 1, k); // 调用快排
    }
 
    int qsort(vector<int>& nums, int l, int r, int k)
    {
        if(l == r) return nums[l];// 递归结束条件
 
        // 随机选择基准元素
        int key = getRandom(nums, l, r);
        // 数组分三块
        int left = l - 1,right = r + 1,i = l;
        // 循环
        while(i < right)
        {
            if(nums[i] < key) swap(nums[++left], nums[i++]);
            else if(nums[i] == key) i++;
            else swap(nums[--right], nums[i]);
        }
 
        // 讨论
        int c = r - right + 1,b = right - left - 1;
        if(c >= k) return qsort(nums, right, r, k);
        else if(b + c >= k) return key;
        else return qsort(nums, l, left, k - b - c);
    }
 
    int getRandom(vector<int>& nums, int left, int right)
    {
        return nums[rand() % (right - left + 1) + left];
    }
};


🌙topic-->4

题目链接:


 


题目分析:

输入整数数组 arr,找出其中最小的 k 个数。(跟上面的题目相似,这里不在细致讲解)

算法原理:

  • 解法:采用快速排序算法(三指针)

 图解:



细节处理:

  • 递归结束标志是 l >= r

代码演示:

class Solution
{
public:
  vector<int> getLeastNumbers(vector<int>&nums, int k)
  {
    srand(time(NULL));
    qsort(nums, 0, nums.size() - 1, k);
    return { nums.begin(), nums.begin() + k };
  }
  void qsort(vector<int>& nums, int l, int r, int k)
  {
    if (l >= r) return;
    // 1. 随机选择⼀个基准元素 + 数组分三块
    int key = getRandom(nums, l, r);
    int left = l - 1, right = r + 1, i = l;
    while (i < right)
    {
      if (nums[i] < key) swap(nums[++left], nums[i++]);
      else if (nums[i] == key) i++;
      else swap(nums[--right], nums[i]);
    }
    // [l, left][left + 1, right - 1] [right, r]
    // 2. 分情况讨论
    int a = left - l + 1, b = right - left - 1;
    if (a > k) qsort(nums, l, left, k);
    else if (a + b >= k) return;
    else qsort(nums, right, r, k - a - b);
  }
  int getRandom(vector<int>& nums, int l, int r)
  {
    return nums[rand() % (r - l + 1) + l];
  }
};


🌟结束语

      今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。


目录
相关文章
|
3月前
|
算法 搜索推荐
算法设计 (分治法应用实验报告)基于分治法的合并排序、快速排序、最近对问题
这篇文章是关于分治法应用的实验报告,详细介绍了如何利用分治法实现合并排序和快速排序算法,并探讨了使用分治法解决二维平面上的最近对问题的方法,包括伪代码、源代码实现及时间效率分析,并附有运行结果和小结。
|
4月前
|
算法 C语言 C++
刷题训练之分治归并
刷题训练之分治归并
22 0
|
4月前
|
算法 C语言 C++
刷题训练之二分查找
本文详细介绍了二分查找算法,包括其时间复杂度、适用场景(如有序/无序数组),并提供了针对LeetCode上常见题型的解析,包括查找、范围搜索和插入位置等,强调理解和记忆关键模板。
27 0
|
4月前
|
算法 Java C语言
刷题训练之双指针问题
刷题训练之双指针问题
30 0
|
6月前
|
算法
|
6月前
|
算法 搜索推荐
【算法基础】基础算法(一)--(快速排序、归并排序、二分)
【算法基础】基础算法(一)--(快速排序、归并排序、二分)
|
6月前
|
算法 数据安全/隐私保护 决策智能
【算法训练-回溯算法 零】回溯算法解题框架
【算法训练-回溯算法 零】回溯算法解题框架
63 0
|
6月前
|
存储 缓存 算法
【算法训练-动态规划 零】动态规划解题框架
【算法训练-动态规划 零】动态规划解题框架
97 0
|
算法 C++
C++基础算法二分篇
C++基础算法二分篇
|
存储 人工智能 分布式计算
动态规划从理论到实践-深入理解贪心/分治/回溯/动态规划的算法思想
动态规划从理论到实践-深入理解贪心/分治/回溯/动态规划的算法思想
235 0