《算法题讲解指南:优选算法-分治-快排》--43.颜色分类,44.排序数组

《算法题讲解指南:优选算法-分治-快排》--43.颜色分类,44.排序数组

🔥小叶-duck个人主页

❄️个人专栏《Data-Structure-Learning》

《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--优选算法

未择之路,不须回头
已择之路,纵是荆棘遍野,亦作花海遨游


目录

43.颜色分类

题目链接:

题目描述:

题目示例:

解法(快排思想——三指针法使数组分三块):

算法思路:

C++算法代码:

算法总结及流程解析:

44.排序数组

题目链接:

题目描述:

题目示例:

解法(数组分三块思想+随机选择基准元素的快速排序):

算法思路:

C++算法代码:

算法总结及流程解析:

结束语


43.颜色分类

题目链接:

75. 颜色分类 - 力扣(LeetCode)

题目描述:

题目示例:

解法(快排思想——三指针法使数组分三块):

算法思路:

      类比数组分两块的算法思想,这里是将数组分成三块,那么我们可以再添加一个指针,实现数组分三块。

      设数组大小为 n ,定义三个指针 left,cur,right:

left:用来标记0序列的末尾,因此初始化为-1;

cur:用来扫描数组,初始化为0;

right:用来标记2序列的起始位置,因此初始化为n 。

在 cur 往后扫描的过程中,保证:

[ 0,left ]内的元素都是0;

[ left + 1,cur - 1 ]内的元素都是1 ;

[ cur, right - 1 ]内的元素是待定元素; 

[ right,n - 1 ]内的元素都是2。

C++算法代码:

class Solution { public: void sortColors(vector<int>& nums) { int left = -1, right = nums.size(), i = 0; while(i < right) { if(nums[i] > 1) { swap(nums[i], nums[--right]); } else if(nums[i] < 1) { swap(nums[i++], nums[++left]); } else { i++; } } } };

算法总结及流程解析:

44.排序数组

题目链接:

912. 排序数组 - 力扣(LeetCode)

题目描述:

题目示例:

解法(数组分三块思想+随机选择基准元素的快速排序):

算法思路:

      我们在数据结构阶段学习的快速排序的思想可以知道,快排最核心的一步就是 Partition (分割数据):将数据按照一个标准,分成左右两部分。

      如果我们使用荷兰国旗问题的思想,将数组划分为左中右三部分:左边是比基准元素小的数据,中间是与基准元素相同的数据,右边是比基准元素大的数据。然后再去递归的排序左边部分和右边部分即可(可以舍去大量的中间部分)。

      在处理数据量有很多重复的情况下,效率会大大提升。

C++算法代码:

class Solution { public: void quicksort(vector<int>& nums, int l, int r) { if(l >= r) { return; } int ra = rand(); int key = nums[ra % (r - l + 1) + l]; //控制随机数的范围在[left, right] int i = l; int left = l - 1; int right = r + 1; while(i < right) { if(nums[i] > key) { swap(nums[i], nums[--right]); } else if(nums[i] < key) { swap(nums[i++], nums[++left]); } else { i++; } } quicksort(nums, l, left); quicksort(nums, right, r); } vector<int> sortArray(vector<int>& nums) { srand(time(NULL)); //种下一个随机数种子 quicksort(nums, 0, nums.size() - 1); return nums; } };

      这里提一句,之前我们学习快排原理数据结构之排序-选择排序&交换排序中实现快排代码使用的获取key的方法是三数取中,这里也能通过,但不进行展示了,只是把三数取中的代码放在下面供大家查看:
      而且相较于之前实现快排的代码,这里使用的数组分三块在效率上是非常快的。因为之前所学的实现快排只是将数组分成两块,如果一个数组相同元素过多就会导致算法复杂度退化,而分成三块后则相同的key则会被忽略。

算法总结及流程解析:

结束语

      到此,43.颜色分类,44.排序数组 这两道算法题就讲解完了。颜色分类:采用三指针法将数组分为0、1、2三个区间,通过left、cur、right指针实现高效分区。排序数组:在传统快排基础上引入荷兰国旗问题的三区划分思想,配合随机基准选择,有效处理重复元素,提升排序效率。希望大家能有所收获!

Read more

【希尔排序算法】详解:原理、实现与优化

【希尔排序算法】详解:原理、实现与优化

【希尔排序算法】详解:原理、实现与优化 * 一、算法概述 * 基本特性 * 二、算法原理详解 * 核心思想 * 增量序列选择 * 三、算法流程图示 * 示例数组:[8, 9, 1, 7, 2, 3, 5, 4, 6, 0] * 初始状态 * 第一轮:gap=5 * 第二轮:gap=2 * 第三轮:gap=1(标准插入排序) * 四、完整Java实现 * 五、算法分析 * 时间复杂度分析 * 空间复杂度 * 稳定性 * 六、实际应用场景 * 七、与其他排序算法的对比 * 八、总结 🌺The Begin�

By Ne0inhk

傅里叶变换 | FFT 与 DFT 原理及算法

注:本文为 “傅里叶变换 | FFT 与 DFT” 相关合辑。 英文引文,机翻未校。 中文引文,略作重排。 图片清晰度受引文原图所限。 如有内容异常,请看原文。 Fast Fourier Transform (FFT) 快速傅里叶变换(FFT) In this section we present several methods for computing the DFT efficiently. In view of the importance of the DFT in various digital signal processing applications, such as linear filtering,

By Ne0inhk
链表进阶核心 | LeetCode 92 区间反转:吃透递归反转与哨兵技巧

链表进阶核心 | LeetCode 92 区间反转:吃透递归反转与哨兵技巧

✨链表进阶核心 | LeetCode 92 区间反转:吃透递归反转与哨兵技巧🎯 * 视频地址 * 🚀 开篇引论:链表反转的进阶之路 * 🔄 基础筑基:链表【前n个节点】递归反转 * 1. 函数定义与核心功能 * 2. 递归实现思路拆解 * 3. 直观调用示例 * 4. 关键代码实现(C++)与详解 * 🎯 实战攻坚:LeetCode 92 链表区间反转 * 1. 题目问题描述 * 2. 神器加持:虚拟头节点(哨兵)技巧 * 3. 整体解题思路 * 4. 完整代码实现(C++)与逐行解析 * 5. 算法复杂度分析 * 📚 算法原理深度剖析 * 1. 递归反转的核心原理 * 2. 虚拟头节点的底层逻辑 * 💡 算法学习核心建议 * 结语 * ✅ 关键点回顾 视频地址

By Ne0inhk
贪心算法(局部最优实现全局最优)第一篇

贪心算法(局部最优实现全局最优)第一篇

目录 1. 什么是贪心算法 2. 贪心算法的解题步骤 3. 具体例题及代码 3.1 LeetCode860. 柠檬水找零 3.2 LeetCode2208. 将数组和减半的最少操作次数 3.3 LeetCode179. 最大数 从这篇文章开始,我们开始讲解贪心算法。 1. 什么是贪心算法 贪心算法是算法设计中的经典思想,核心逻辑用一句话就能概括 ——每一步都做出当前情况下的最优选择,不回头、不纠结,最终期望得到全局最优解。它不像动态规划那样依赖中间状态存储,也不用回溯尝试所有可能,凭借 “直来直往” 的思路,成为解决特定问题的高效方案。 2. 贪心算法的解题步骤 1. 问题拆解:将复杂问题拆分成多个连续的局部决策步骤。 2. 确定贪心策略:明确每一步的 “最优标准”(比如 “选最小”“选最大”“选最早结束”)。 3. 验证可行性:

By Ne0inhk