淘宝网店运营策划方案seo排名优化首页
web/
2025/10/4 17:39:31/
文章来源:
淘宝网店运营策划方案,seo排名优化首页,创建手机网站模版,网页设计新手制作的网站代码快速排序算法 (1) 快速排序法 (2) 快排前后指针 (3) 快排挖坑法 颜色分类 题目解析 算法原理 算法原理和移动零非常相似 简述移动零的算法原理 cur 在从前往后扫描的过程中#xff0c;如果扫描的数符合 f 性质#xff0c;就把这个数放到 dest 之… 快速排序算法 (1) 快速排序法 (2) 快排前后指针 (3) 快排挖坑法 颜色分类 题目解析 算法原理 算法原理和移动零非常相似 简述移动零的算法原理 cur 在从前往后扫描的过程中如果扫描的数符合 f 性质就把这个数放到 dest 之前的区域符合 g 性质则不管知道 cur 遍历到最后dest 指针就可以把数组划分成两个部分 解法三指针 当 i 遍历结束数组后整个数组就被排好序了并且数组以 leftright 两个指针为分界线分成三个部分 在遍历的过程中整个数组会被划分成四个部分 对遍历到的 nums[ i ] 的不同元素的分类处理 nums[ i ] 0 对于上面这种情况我们只需要 swap( nums[ left 1] , nums [ i ] ) lefti 即可要注意nums[left1]1 但是有一种极端情况就是如果 i left 1并且也符合 nums[ i ] 0 的情况我们依旧要执行 swap( nums[ left 1] , nums [ i ] ) 虽然这种极端情况是变成自己和自己交换但是处理方法不变交换完成后left , i nums[ i ] 1 此时我们令 i 即可 nums[ i ] 2 对于这种情况我们可以 swap( nums[ i ] , nums[ right - 1 ] ) 然后 right-- ; 此时需要特别注意swap( nums[ i ] , nums[ right - 1 ] ) 后i 是不可以 的因为 [ i ,right-1 ] 是待扫描区域交换后nums[ i ] 依旧是待扫描元素所以 i 如果是和 right -1交换的情况i 是一定不可以的 处理细节问题 循环终止条件 当待扫描区域已经没有元素说明此时数组所有元素已经全部被扫描并且分好类了结束循环即可所以循环终止条件是 i ! right 指针初始化 根据我们上面的算法原理为了保证 left 指向 0 区域的最右边 right 区域指向 2 区域的最左边我们交换元素是不会让 nums[ left ] nums[ right ] 亲自和 nums[ i ] 进行交换的 所以我们的指针初始化的值如下 这样的操作是为了避免漏掉对 nums[ 0 ] nums [ n - 1 ] 的扫描 编写代码 报错原因 交换元素的方法不对并且初始化 left和 right 的操作没有处理好会漏掉对 nums[ 0 ] nums [ n - 1 ] 的扫描 使用快速排序来排序数组 题目解析 算法原理 解法原始快速排序 原始快速排序 而原始快速排序的方法最核心的步骤就在于根据基准元素进行数据划分的过程这个步骤的名字是 partation 但是如果使用快速排序的数组有重复元素那么快排的时间复杂度就会退化 解法用 数组分三块 的思想实现快速排序 这是基于原始快速排序的优化策略用于应对快速排序的数组有大量重复元素的情况从对数组分成两块划分为分成三块 在数组出现大量重复元素时通过把数组分成三段可以把时间复杂度从 O(N^2) 降到 O(N) 分类讨论 我们通过递归不断对划分的小区域排序最终得到排好序的数组 优化用随机的方式选择基准元素 如果要想让快排的时间复杂度趋于 O(N* logN) 就需要随机地选择基准元素 随机选择基准元素就是给我们一个数组我们要等概率地返回区间上的任意一个数 如何随机地选择一个基准元素呢 编写代码 准备工作 传入要排序的左区间和右区间 如果 L R则说明排序的区间要么只有一个要么这个区间没有元素说明整个数组已经排序完毕 随机生成基准元素 初始化下标 要记一下如何生成随机数下标以及要特别注意这里的初始化 left ! -1 right ! nums.length 把数组分三块 [ left 1 , right - 1 ] 这块区域用于存与生成的随机基准元素值相同的元素 并且以这块区域为基准把其他数组元素分到这三块区域对应的区域 可以记一下这个 partation 的过程这是快排的核心逻辑 [ L , left ] [ right , R ] 进行排序 根据 nums[ i ] 与 key 的大小关系把所有元素放到 [ left 1 , right - 1 ] 的两边两边还是乱序的再对两边区域进行递归排序即可 快速选择算法 数组中的第K个最大元素 题目解析 算法原理 解法基于快排实现快速选择算法 快速排序 Partation 本题是要找出数组中第 K 大的元素 KthLarges那么我们可以根据基准元素来判断 KthLarges 是落在上面三个区域的哪一个区域然后对这个区域进行继续进行 Partation继续找 KthLarges; 根据 K 的值分情况讨论确定 KthLarges 的区间位置 我们先分别设三个区间的元素个数 处理细节问题 我们解释一下这种情况 编写代码 先根据快排 partation 原理把数组分三块 根据 k 的值来决定递归三块中的哪一块区域 最小的k个数 题目解析 算法原理 解法一直接排序 时间复杂度 O( N * logN) 解法二使用大根堆( 求最小的前K个数) 时间复杂度 O( N * logK ) 解法三快速选择算法 时间复杂度趋于 O( N ) 因为是随机选择基准元素步骤如下 对 K 的值分类讨论 (1) a k (2) b k 这种情况我们直接返回前面两个区域的前 k 个小的元素即可不用关心 [ L , right ] 区间的顺序 (3) k bc 通过这三种情况我们就能明显的感受到快速选择排序是最优的解法;
比如第三种情况此时[ L right ] 区间是没有排序的但是我们依旧已经找到了最小的 k 个元素的一部分而其他两种情况都是要对数组的每一个元素进行排序 编写代码 我们是对 nums 的前 k个元素进行排序把然后把 nums 的前 k 个元素赋值个 ret然后返回 报错原因粗心导致 left right 指针的初始值写错了 归并排序 当数组块被分成每一块都只有一个元素分块结束用双指针合并两个有序数组归并排序的决策树非常像二叉树的后续遍历( 左右根 )而快排则类似前序遍历(先对数组整体粗糙分一遍再去两边区域细分) 使用归并排序来排序数组 题目解析 编写代码 优化辅助数组设置为全局变量 把 tmp 设置为全局就不用在每次递归时创建一个新的 tmp 减少时间开销 int[] nums, tmp ;public int[] sortArray(int[] _nums) {nums _nums;tmp new int[nums.length]; mergeSort(0, nums.length - 1);return nums;}public void mergeSort(int left ,int right){if(left right) return;int mid (left right) / 2;mergeSort(left , mid);mergeSort(mid 1 , right);int cur1 left; int cur2 mid 1; int i 0 ; while(cur1 mid cur2 right){tmp[i] nums[cur1] nums[cur2] ? nums[cur1] : nums[cur2] ; }while(cur1 mid) tmp[i] nums[cur1];while(cur2 right) tmp[i] nums[cur2];for(int j left ; j right ; j ) nums[j] tmp[j - left]; } 数组中的逆序对 题目解析 算法原理 解法一暴力枚举 固定其中一个数在这个数后面区间找比这个数小的数来构成一个逆序对 使用两层 for 循环即可但是会超时 解法二归并排序 算法原理 (1) 左半部分 右半部分 一左一右 本质还是暴力枚举逆序对个数 a b c (2) 左半部分 左排序 右半部分 右排序 一左一右 排序 对左右两边排好序再一左一右挑数组成逆序对并不影响结果 本题为什么可以利用归并排序解决问题 并且通过这步操作我们得出本题最终的解法就是需要通过归并排序求逆序对个数 我们在找出左右两边的逆序对个数时先对两边排序再一左一右会非常快 一左一右查找逆序对策略优化 我们在之前找左右两边区域的所有逆序对时就刻意地对左右两边进行排序找完左右两边的逆序对时nums 的两边区域的顺序已经被排序成升序此时我们需要一左一右寻找逆序对 策略一 : 判断 nums[cur1]nums[cur2] 升序 统计一左一右逆序对的固定策略 固定 cur2, 只要 cur1 一移动到 nums[cur1]nums[cur2]位置就统计符合要求的区间的元素个数cur2 假设我们固定 cur2要在左边找有多少个比 nums[ cur2 ] 大的元素 令 cur1 在左边区域中从左到右扫描找出第一个 nums[ cur1 ] nums[ cur2 ] 的 cur1 (1) nums[ cur1 ] nums[ cur2 ] 我们直接让 cur1 并且为了让数组有序我们要把 nums[cur1] 放入辅助数组中方便后续排序继续往后找即可 (2) nums[ cur1 ] nums[ cur2 ] 出现这种情况对于两边升序区域当 nums[ cur1 ] nums[ cur2 ] 说明此时 cur1 指向的元素是左边区域第一个比 nums[ cur2 ] 大的元素cur1 后面所有元素都比 nums[ cur2 ] 大 也因为是升序排序在 cur1 一走到第一个合法位置时 ret mid - cur1 1即可
本轮 cur2 的所有能拿到的逆序对就已经统计好了此时 cur2 即可 如果策略一使用降序排列会出现的问题 对于降序排序我们依旧是需要固定 cur2 我们依旧需要采取【 只要 cur1 一移动到 nums[cur1]nums[cur2] 的位置就统计符合这个要求的区间的元素个数】的策略 如下图的情况
因为是降序排序的所以 cur2 不能因为 nums[cur1]nums[cur2] 就马上 还必须看下一个 cur1 能否满足 nums[cur1]nums[cur2] : 因为采取了【 只要 cur1 一移动到 nums[cur1]nums[cur2] 的位置就统计符合这个要求的区间的元素个数】的策略因此就会造成大量的重复计算 cur1 一移动判断是否大于 cur2如果判断成立马上就让 ret cur1 - left 1所以会出现多次重复计算 所以使用策略一在排序数组时不能用降序避免大量重复计数所以只能用升序 策略二 : nums[cur1]nums[cur2] 降序 统计一左一右逆序对的固定策略 固定 cur2, 只要 cur1 一移动到 nums[cur1]nums[cur2]位置就统计符合要求的区间的元素个数cur2 编写代码 策略一 升序 准备工作 主逻辑 策略二 降序 计算右侧小于当前元素的个数 题目解析 算法原理 这道题的本质还是类似于求逆序对的个数 解法归并排序左半部分 左排序 右半部分 右排序 一左一右 排序 一左一右策略nums[ cur1 ] nums[ cur2 ] 降序上一题策略二 nums[ cur1] nums[ cur2 ] cur2修改对应的辅助数组nums[ cur1 ] nums[ cur2 ]把 nums[ cur1 ] 对应 ret[ ] 下标的元素加上 right - cur2 1 修改对应的辅助数组 处理细节问题 我们要找到 nums[ cur1 ] 对应 ret[ ] 的对应下标 因为我们排序的时候下标已经乱了 如果我们使用哈希表来设置 nums 元素 , ret 下标 的映射如果 nums有重复元素哈希表无法存储重复元素就无法解决下标混乱的问题 所以我们设置与 nums 同等规模的数组 index[ ]表示 nums 未排序时元素的原始下标 不管 nums 因为排序里面的元素怎么移动index 对应的元素绑定移动 那如何让 nums[] 和 index[] 绑定移动呢我们需要创建两个辅助数组 tmp来让它们同步移动
最后让 ret [ index[ i ] ] right - cur2 1 即可 编写代码 准备工作 核心逻辑 报错原因对于降序排序的一左一右操作不熟练判断条件写错了 翻转对 拓展 直接插入排序 选择排序 冒泡排序
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/86897.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!