当前位置: 首页 > news >正文

算法奇妙屋(四)-归并分治

文章目录

  • 一. 力扣 912. 排序数组
    • 1. 题目
    • 2. 算法原理
    • 3.代码
  • 二. 力扣 LCR 170. 交易逆序对的总数
    • 1. 题目
    • 2. 算法原理
      • (1) 方法一
      • (2) 方法二
    • 3. 代码
      • (1) 方法一代码:
      • (2) 方法二代码:
  • 三. 力扣 315. 计算右侧小于当前元素的个数
    • 1. 题目
    • 2. 算法原理
    • 3. 代码
  • 四. 力扣 493. 翻转对
    • 1. 题目
    • 2. 算法原理
      • (1) 方法一(降序):
      • (2) 方法二(升序):
    • 3. 代码
      • (1) 方法一(降序)代码:
      • (2) 方法二(升序)代码:

这个篇章我们基于归并排序,并结合分治思想来解决问题

一. 力扣 912. 排序数组

1. 题目

在这里插入图片描述

2. 算法原理

归并排序我们应该不陌生, 这里我们只是复习归并排序的算法原理
在这里插入图片描述

3.代码

    public int[] sortArray(int[] nums) {mergeSort(nums,0,nums.length-1);return nums;}public void mergeSort(int[] nums, int s, int e) {if (s >= e) {return;}int mid = (s + e) / 2;// 递归左区间mergeSort(nums,s,mid);// 递归右区间mergeSort(nums,mid + 1,e);// 递归完成后, 给两个数组排序(数组并不是真实数组,而是可以看成两个数组)int left1 = s;int left2 = mid + 1;int i = 0;int[] tmp = new int[e - s + 1];while (left1 <= mid && left2 <= e) {if (nums[left1] <= nums[left2]) {tmp[i++] = nums[left1++];}else {tmp[i++] = nums[left2++];}}while(left1 <= mid) {tmp[i++] = nums[left1++];}while(left2 <= e) {tmp[i++] = nums[left2++];}// 将tmp数组的值放入nums中for (int j = 0; j < e - s + 1; j++) {nums[j + s] = tmp[j];}}

二. 力扣 LCR 170. 交易逆序对的总数

1. 题目

在这里插入图片描述

2. 算法原理

(1) 方法一

在这里插入图片描述

(2) 方法二

在这里插入图片描述

3. 代码

(1) 方法一代码:

    int ret = 0;int[] tmp ;public int reversePairs(int[] nums) {tmp = new int[nums.length];mergeSort(nums, 0,nums.length - 1);return ret;}public void mergeSort(int[] nums, int start, int end) {if (start >= end) {return;}int mid = (end + start) / 2;// 递归左面[s,mid]mergeSort(nums, start, mid);// 递归右面[mid+1,e]mergeSort(nums, mid + 1, end);// 递归结束, 开始排序, 并统计int left1 = start;int left2 = mid + 1;int i = 0;while (left1 <= mid && left2 <= end) {if (nums[left1] <= nums[left2]) {tmp[i++] = nums[left1++];}else {ret += mid - left1 + 1;tmp[i++] = nums[left2++];}}while (left1 <= mid) {tmp[i++] = nums[left1++];}while (left2 <= end) {tmp[i++] = nums[left2++];}for (int j = 0; j < end - start + 1; j++) {nums[j + start] = tmp[j];}}

(2) 方法二代码:

    int ret = 0;int[] tmp ;public int reversePairs(int[] nums) {tmp = new int[nums.length];mergeSort(nums, 0,nums.length - 1);return ret;}public void mergeSort(int[] nums, int start, int end) {if (start >= end) {return;}int mid = (end + start) / 2;// 递归左面[s,mid]mergeSort(nums, start, mid);// 递归右面[mid+1,e]mergeSort(nums, mid + 1, end);// 递归结束, 开始排序, 并统计int left1 = start;int left2 = mid + 1;int i = 0;while (left1 <= mid && left2 <= end) {if (nums[left1] <= nums[left2]) {tmp[i++] = nums[left2++];}else {ret += end - left2 + 1;tmp[i++] = nums[left1++];}}while (left1 <= mid) {tmp[i++] = nums[left1++];}while (left2 <= end) {tmp[i++] = nums[left2++];}for (int j = 0; j < end - start + 1; j++) {nums[j + start] = tmp[j];}}

三. 力扣 315. 计算右侧小于当前元素的个数

1. 题目

在这里插入图片描述

2. 算法原理

在这里插入图片描述

3. 代码

    int[] tmpNums;int[] tmpIndex;int[] index;int[] ret;public List<Integer> countSmaller(int[] nums) {List<Integer> list = new ArrayList<>();int n = nums.length;tmpNums = new int[n];tmpIndex = new int[n];index = new int[n];ret = new int[n];for (int i = 0; i < n; i++) {index[i] = i;}mergeSort(nums, 0, n - 1);for (int x : ret) {list.add(x);}return list;}public void mergeSort(int[] nums, int start, int end) {if (start >= end) {return;}int mid = (start + end) / 2;// 计算左面个数mergeSort(nums, start, mid);// 计算右面个数mergeSort(nums, mid + 1, end);// 计算一左一右int left1 = start;int left2 = mid + 1;int i = 0;while (left1 <= mid && left2 <= end) {if (nums[left1] <= nums[left2]) {tmpNums[i] = nums[left2];tmpIndex[i++] = index[left2++];}else {ret[index[left1]] += end - left2 + 1;tmpNums[i] = nums[left1];tmpIndex[i++] = index[left1++];}}while (left1 <= mid) {tmpNums[i] = nums[left1];tmpIndex[i++] = index[left1++];}while (left2 <= end) {tmpNums[i] = nums[left2];tmpIndex[i++] = index[left2++];}// 将tmp数组的值放回到原数组其中, 排序工作for (int j = start; j <= end; j++) {nums[j] = tmpNums[j - start];index[j] = tmpIndex[j - start];}}

四. 力扣 493. 翻转对

1. 题目

题目意思大白话解释就是前面有多少数大于后面数值的2倍
在这里插入图片描述

2. 算法原理

(1) 方法一(降序):

在这里插入图片描述

(2) 方法二(升序):

在这里插入图片描述

3. 代码

(1) 方法一(降序)代码:

我们要注意,这道题里面的测试用例输入数组中的所有数字都在32位整数的表示范围内, 但是我们×2后那么就会超出32位, 所以我们用除以2的方式

    int[] tmp;public int reversePairs(int[] nums) {int n = nums.length;tmp = new int[n];return mergeSort(nums, 0, n - 1);}public int mergeSort(int[] nums, int start, int end) {if (start >= end) {return 0;}int ret = 0;int mid = (start + end) / 2;// 先计算左面ret += mergeSort(nums, start, mid);// 再计算右面ret += mergeSort(nums, mid + 1, end);// 最后计算一左一右int left1 = start;int left2 = mid + 1;while (left1 <= mid && left2 <= end) {if (nums[left1] / 2.0 >  nums[left2]) {ret += end - left2 + 1;left1++;}else {left2++;}}// 放入tmp中排序left1 = start;left2 = mid + 1;int i = 0;while (left1 <= mid && left2 <= end) {tmp[i++] = nums[left1] > nums[left2] ? nums[left1++] : nums[left2++];}while (left1 <= mid) {tmp[i++] = nums[left1++];}while (left2 <= end) {tmp[i++] = nums[left2++];}// 合并数组for (int j = start; j <= end; j++) {nums[j] = tmp[j - start];}return ret;}

(2) 方法二(升序)代码:

    int[] tmp;public int reversePairs(int[] nums) {int n = nums.length;tmp = new int[n];return mergeSort(nums, 0, n - 1);}public int mergeSort(int[] nums, int start, int end) {if (start >= end) {return 0;}int ret = 0;int mid = (start + end) / 2;// 先计算左面ret += mergeSort(nums, start, mid);// 再计算右面ret += mergeSort(nums, mid + 1, end);// 最后计算一左一右int left1 = start;int left2 = mid + 1;while (left1 <= mid && left2 <= end) {if (nums[left1] / 2.0 >  nums[left2]) {ret += mid - left1 + 1;left2++;}else {left1++;}}// 放入tmp中排序left1 = start;left2 = mid + 1;int i = 0;while (left1 <= mid && left2 <= end) {tmp[i++] = nums[left1] <= nums[left2] ? nums[left1++] : nums[left2++];}while (left1 <= mid) {tmp[i++] = nums[left1++];}while (left2 <= end) {tmp[i++] = nums[left2++];}// 合并数组for (int j = start; j <= end; j++) {nums[j] = tmp[j - start];}return ret;}
http://www.dtcms.com/a/422741.html

相关文章:

  • 【嵌入式硬件实例】-晶体管放大器
  • ArcGIS数据迁移问题汇总(postgresql)
  • SQLyog:一款功能强大、简单易用的MySQL管理工具
  • Boost 搜索引擎
  • 紧跟大数据技术趋势:食物口味分析系统Spark SQL+HDFS最新架构实现
  • c2c网站的建设做企业网站有哪些好处
  • 从AI角度深入解析和论述哲学的终极答案‘语言即世界‘
  • 网站开发实训报告织梦手机网站建设
  • python做网站开发免费公司企业建站代理
  • 科技信息差(9.29)
  • ES如何基于Linux配置开机自启动
  • DeepSeek Java 单例模式详解
  • 单例模式入门
  • PMON failed to acquire latch 的报错及sqlplus / as sysdba 无法连接
  • Vibe Coding - MCP Feedback Enhanced(交互反馈 MCP)
  • Elasticsearch 搭建(亲测)
  • Java 设计模式在 Spring 框架中的实践:工厂模式与单例模式
  • 手机网站被禁止访问怎么打开网页软件应用大全
  • SQL注入与防御:从攻击原理到预编译防御
  • 【MySQL】Oracle与MySQL,跨库数据转储
  • 营销型网站建设的步骤附近公司
  • 【Java】网络编程(5)
  • 实现VLAN间通信
  • OSPF 和 IS-IS的路由过滤对比
  • Eclipse 透视图(Perspective)
  • 【Linux操作系统】简学深悟启示录:动静态库
  • 网站搭建设计筑龙网怎么免费下载
  • 网站制作哪家好网站建设中期目标
  • 前端开发时npm install报错解决方案
  • C#中 单线程使用 CancellationTokenSource 进行线程管理