算法-归并应用

题目:给你一个整数数组 nums 以及两个整数 lowerupper 。求数组中,值位于范围 [lower, upper] (包含 lowerupper)之内的 区间和的个数

区间和 S(i, j) 表示在 nums 中,位置从 ij 的元素之和,包含 ij (ij)。

https://leetcode.cn/problems/count-of-range-sum/description/?utm_source=LCUS&utm_medium=ip_redirect&utm_campaign=transfer2china

思路:求区间和问题,将原始数组转换为累加和数组,任意两个区间范围,使用递归方式将求解范围划分为更新的部分,类似归并排序思路。

public static int countRangeSum240215(int[] nums, int lower, int upper) {if(nums == null || nums.length<=0)return  0;// 累加数组int[] acc = new int[nums.length];acc[0] = nums[0];for (int i = 1; i < nums.length; i++) {acc[i] = nums[i]+acc[i-1];}return process240215(acc,0,acc.length-1,upper,lower);}// 递归作用是将数组范围划分为更小的部分public static int process240215(int[] acc,int left,int right,int upper,int lower){if (left == right){return acc[left]<=upper && acc[right]>=lower?1:0;}int m = left + ((right-left)>>1);// 将问题范围划分为更小部分,在调用之后 [left,mid] [mid+1,right] 是递增的int sub = process(acc,left,m,upper,lower)+process(acc,m+1,right,upper,lower);// 当前范围计算符合问题的数量int cur = merge240215(acc,left,m,right,upper,lower);return cur+sub;}// 以mid为分界线前后都是递增的,计算复合条件的数量,同时将前后两个部分合并为一个递增序列// 左边的部分为[left,mid] 右边的部分为[mid+1,right] 因为递归调用的时候mid放在前面部分// mid左右两部分合并为递归序列不影响最终结果,因为求的是原始数组两个位置子区间累加和public static int merge240215(int[] acc,int left,int mid ,int right,int upper,int lower){int ans = 0;int winL = left;int winR = left;for(int i = mid+1;i<=right;i++){// acc[i] - acc[winL] <= upperwhile (acc[i]-acc[winL]>upper){winL++;}// acc[i] - acc[winR] >= lowerwhile (acc[i]-acc[winR]>=lower){winR++;}// winR-winL 就是最终的数量 不用+1 因为计算大于等于lower的时候最终的winR是小于lower的位置,所以直接相减不用加一// 下一次进入该for遍历 acc[i] 比acc[i-1] 大,所以可以接着上次计算的winL 和 winR继续用ans += (winR-winL);}// 合并为递增序列int l = left;int r = mid;int index = 0;int[] help = new int[right - left + 1];for (;l<=mid && r<=right;){if(acc[l]<acc[r]){help[index] = acc[l++];}else{help[index] = acc[r++];}index++;}while (l<=mid){help[index++] = acc[l++];}while (r<=right){help[index++] = acc[r++];}return ans;}

问题:归并排序

思路:将待排序范围划分为更小的部分,如果只有一个代表当前范围的子数组已排序直接返回,在上次对子范围进行合并为排序数组.两种实现方式:递归方式,另外使用栈模拟递归调用

// 归并排序// 递归方式实现// 将数组划分为更小的范围,然后再合并的时候对子数组进行排序public static void mergeSort1(int[] arr) {if(arr == null || arr.length<=0)return;process(arr, 0,arr.length-1);}public static void process(int[] arr,int left,int right){if(left >= right)return;int index = ((int)(Math.random()*(right-left+1)))+left;process(arr,left,index);process(arr,index+1,right);merge(arr,left,index,right);}// 将[left,mid] (mid,right] 合并为排序数组// 两个子范围是已经排序了的public static void merge(int[] arr,int left,int mid,int right){int index = 0;int[] help = new int[right - left + 1];int l = left;int r = mid+1;while (l<=mid && r<=right){if(arr[l]<arr[r]){help[index] = arr[l++];}else {help[index] = arr[r++];}index++;}while (l<=mid){help[index++] = arr[l++];}while (r <= right) {help[index++] = arr[r++];}index = 0;for (int i = 0; i < help.length; i++) {arr[left+i] = help[i];}}// 非递归方式// 栈模拟递归调用public static void mergeSort2(int[] arr) {if(arr == null || arr.length<=1)return;Stack<Flash> stack = new Stack<>();Flash flash = new Flash(0, arr.length - 1, 1);stack.add(flash);while (!stack.isEmpty()){Flash cur = stack.pop();if(cur.count == 1){// cur对应的递归范围第一次访问,对应的是该范围的process方法第一次访问// 创建左右子范围然后push到stackint left = cur.left;int right = cur.right;if(left >= right)continue;int index = ((int)(Math.random()*(right-left+1)))+left;// 这里给子范围的count赋值1 实际上这里不算调用子范围,也就是未进入到范围对应的process方法体里Flash l = new Flash(left, index, 1);Flash r = new Flash(index + 1, right, 1);// 用于合并已排序子数组cur.setMid(index);cur.count++;// 先将当前的压入堆栈 因为在左右子范围处理完后需要回到当前范围,将来左右已排序子数组合并stack.push(cur);stack.push(r);stack.push(l);}else if (cur.count == 2){// 啥也不做cur.count++;stack.push(cur);}else {// 左右子范围的process方法都执行完成// 左右子范围子数组都是有序的,将两个子数组合并为一个有序数组int left = cur.left;int right = cur.right;int index = cur.getMid();merge(arr,left,index,right);}}}static class Flash{private int left;private int right;private int count;private int mid;public Flash(int left, int right, int count) {this.left = left;this.right = right;this.count = count;}public int getMid(){return mid;}public void setMid(int mid){this.mid = mid;}}

题目:在一个数组中,一个数左边比它小的数的总和,叫数的小和,所有数的小和累加起来,叫数组小和。求数组小和。
例子: [1,3,4,2,5]
1左边比1小的数:没有
3左边比3小的数:1
4左边比4小的数:1、3
2左边比2小的数:1
5左边比5小的数:1、3、4、 2
所以数组的小和为1+1+3+1+1+3+4+2=16

思路:归并排序,在合并子范围的时候计算小数和,归并在这里作用就是缩小范围,而左右子范围排序后并不影响最终结果,并且排序后可以加快计算速度不用重新从左子数组开始遍历

public static int smallSum(int[] arr) {if(arr == null|| arr.length<=0)return 0;return process(arr,0,arr.length-1);}public static int process(int[] arr,int left,int right){if(left >= right)return 0;int index = ((int)(Math.random()*(right-left+1)))+left;int l = process(arr,left,index);int r = process(arr,index+1,right);int cur = merge(arr,left,index,right);return l+r+cur;}// 将[left,mid] (mid,right] 合并为排序数组// 两个子范围是已经排序了的public static int merge(int[] arr,int left,int mid,int right){int ans = 0;// 计算[left,mid] (mid,right] 范围的小数和int wind = mid+1;int L = left;int pre = 0;while (wind<=right){// 因为左右两个子数组是递增的 所以pre是定义在while外边 // 每次更新wind,在上次计算的pre基础上累加while (L <= mid && arr[L]<arr[wind]){pre+=arr[L++];}ans+=pre;wind++;}// 将两子数组合并为一个排序数组int index = 0;int[] help = new int[right - left + 1];int l = left;int r = mid+1;while (l<=mid && r<=right){if(arr[l]<arr[r]){help[index] = arr[l++];}else {help[index] = arr[r++];}index++;}while (l<=mid){help[index++] = arr[l++];}while (r <= right) {help[index++] = arr[r++];}index = 0;for (int i = 0; i < help.length; i++) {arr[left+i] = help[i];}return ans;}

问题:

在一个数组中,
任何一个前面的数a,和任何一个后面的数b,
如果(a,b)是降序的,就称为逆序对
返回数组中所有的逆序对

思路:归并算法逻辑,用于将数组划分为更新的逻辑,在合并的时候处理大小比较逻辑

public static int reverPairNumber(int[] arr) {if(arr == null || arr.length<=0)return 0;return process(arr,0,arr.length-1);}public static int process(int[] arr,int left,int right){if(left >= right)return 0;int index = left + ((right - left)>>1);int l = process(arr,left,index);int r = process(arr,index+1,right);int cur = merge(arr,left,index,right);return l+r+cur;}// 将[left,mid] (mid,right] 合并为排序数组// 两个子范围是已经排序了的public static int merge(int[] arr,int left,int mid,int right){int ans = 0;// 计算[left,mid] (mid,right] 范围的小数和int wind = right;int L = mid;while (wind>mid&&L>=left){if(arr[wind]<arr[L]){ans += (wind-mid);L--;}else{wind--;}}// 将两子数组合并为一个排序数组int index = 0;int[] help = new int[right - left + 1];int l = left;int r = mid+1;while (l<=mid && r<=right){if(arr[l]<arr[r]){help[index] = arr[l++];}else {help[index] = arr[r++];}index++;}while (l<=mid){help[index++] = arr[l++];}while (r <= right) {help[index++] = arr[r++];}index = 0;for (int i = 0; i < help.length; i++) {arr[left+i] = help[i];}return ans;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/692269.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法——数值算法——牛顿迭代法

目录 牛顿迭代法 一、1021: [编程入门]迭代法求平方根 牛顿迭代法 迭代法&#xff08;Iteration&#xff09;是一种通过反复递推计算来逼近解的方法。而牛顿迭代法&#xff08;Newtons method&#xff09;则是一种特定的迭代法&#xff0c;用于求解方程或函数的根、最小值、最…

MySQL数据库基础(十):DQL数据查询语言

文章目录 DQL数据查询语言 一、数据集准备 二、select查询 三、简单查询 四、条件查询 1、比较查询 2、范围查询 3、逻辑查询 4、模糊查询 5、非空查询 五、排序查询 六、聚合查询 七、分组查询与having子句 1、分组查询介绍 2、group by的使用 3、group by 聚…

【设计模式】23种设计模式笔记

设计模式分类 模板方法模式 核心就是设计一个部分抽象类。 这个类具有少量具体的方法&#xff0c;和大量抽象的方法&#xff0c;具体的方法是为外界提供服务的点&#xff0c;具体方法中定义了抽象方法的执行序列 装饰器模式 现在有一个对象A&#xff0c;希望A的a方法被修饰 …

前端基础Document

前端基础Document 在浏览器的JavaScript环境中&#xff0c;document是默认的全局变量之一&#xff0c;提供对当前网页文档&#xff08;HTML文档&#xff09;的访问和操作。 document对象是Document接口的一个实例&#xff0c;表示整个HTML文档。它作为全局变量存在于浏览器的…

单片机学习笔记---红外遥控红外遥控电机调速(完结篇)

目录 低电平触发中断和下降沿触发中断的区别 红外遥控 Int0.c Int.h Timer0.c Timer0.h IR.c IR.h main.c 红外遥控电机调速 Timer1.c Timer.h Motor.c Motor.h main.c 上一节讲了红外发送和接收的工作原理&#xff0c;这一节开始代码演示&#xff01; 提前说…

闭包----闭包的理解、优点

1、闭包的理解 闭包就是能够读取其他函数内部变量的函数。 由于在 javascript 中&#xff0c;只有函数内部的子函数才能读取局部变量&#xff0c;所以说&#xff0c;闭包可以简单理 解成 “ 定义在一个函数内部的函数 “ 。 所以&#xff0c;在本质上&#xff0c;闭包是将…

微服务中的熔断、降级和限流

在现代微服务架构中,熔断、降级和限流是保障系统稳定性和可靠性的重要手段。本文将深入探讨这三种机制在微服务架构中的作用、原理以及实践方法。 1. 熔断(Circuit Breaker) 1.1 作用和原理 熔断器是一种可以在服务发生故障时快速中断请求的机制,防止故障蔓延到整个系统…

微信小程序-表单提交和校验

一、使用vant组件生成如下页面 二、前端代码如下 <form bindsubmit"submitForm"><view class"cell-group"><van-cell-group><van-field value"{{ title }}" label"商品名称" placeholder"请输入商品名称&qu…

Dubbo框架admin搭建

Dubbo服务监控平台&#xff0c;dubbo-admin是图形化的服务管理界面&#xff0c;从服务注册中心获取所有的提供者和消费者的配置。 dubbo-admin是前后端分离的项目&#xff0c;前端使用Vue&#xff0c;后端使用springboot。因此&#xff0c;前端需要nodejs环境&#xff0c;后端需…

淘宝店内商品列表接口api

淘宝店内商品列表接口api代码对接如下&#xff1a; 1.公共参数 名称 类型 必须 描述 key String √ get请求方式拼接在url中&#xff0c;点击获取 api_name String √ api接口名称 cache String 默认否 result_type String 否 json lang String 默认cn 简…

复高斯分布的随机变量的模方的分布

文章目录 复高斯分布的随机变量的模方的分布问题的源头矩阵服从复高斯分布向量服从复高斯分布 复高斯分布的随机变量的模方的分布 已知 X ∼ C N ( μ , Σ ) X \sim \mathcal{C N}(\boldsymbol{\mu}, \boldsymbol{\Sigma}) X∼CN(μ,Σ) 则 ∥ X ∥ 2 \|X\|^2 ∥X∥2的分布为…

如何在本地服务器部署TeslaMate并远程查看特斯拉汽车数据无需公网ip

文章目录 1. Docker部署TeslaMate2. 本地访问TeslaMate3. Linux安装Cpolar4. 配置TeslaMate公网地址5. 远程访问TeslaMate6. 固定TeslaMate公网地址7. 固定地址访问TeslaMate TeslaMate是一个开源软件&#xff0c;可以通过连接特斯拉账号&#xff0c;记录行驶历史&#xff0c;统…

QTextStream读写文件

QTextStream 类是 Qt 框架中用于文本读写的一个非常强大的类&#xff0c;它提供了丰富的接口用于方便地进行文本文件的输入输出。QTextStream 可以用于读取和写入文本文件&#xff0c;同时也支持字符串&#xff08;如 QString&#xff09;的操作。它自动处理各种不同的字符集编…

LeetCode354. Russian Doll Envelopes——动态规划

文章目录 一、题目二、题解 一、题目 You are given a 2D array of integers envelopes where envelopes[i] [wi, hi] represents the width and the height of an envelope. One envelope can fit into another if and only if both the width and height of one envelope …

关于Android下gralloc,hwcompoer以及surface模块的重新认识

关于Android下gralloc&#xff0c;hwcompoer以及surface模块的重新认识 引言 欠债还钱天经地义&#xff0c;知识的债也是如此&#xff01;这不必须得将我前面欠下来的债给补上&#xff01;对于任何复杂的知识点&#xff0c;我们都可以采用庖丁解牛的学习方式&#xff0c;一步步…

CCF NOI 2024四川省代表队评测活动比赛环境来源:6547网 www.6547.cn

附件1&#xff1a; CCF NOI 2024四川省代表队评测活动比赛环境 一、操作系统&#xff1a;Windows 10或Windows 11 二、Windows 下软件及版本&#xff1a; Dev-C 5.11 TDM-GCC 4.9.2 Codeblocks 20.03 MinGW 8.1.0 Gvim v8.0.69 AdobeReader zh_CN 11.0.0.379.1410747856…

美易官方《机构投资者正将创纪录资金投入美国农田》

长期稳赢美股 机构投资者正将创纪录资金投入美国农田 近年来&#xff0c;随着全球经济的不断变化和投资市场的波动&#xff0c;越来越多的机构投资者开始将目光投向了一个相对较为冷门但稳定的投资领域——美国农田。据最新数据显示&#xff0c;机构投资者正以前所未有的速度将…

文献速递:GAN医学影像合成--双向映射生成对抗网络用于脑部 MR 到 PET 合成

文献速递&#xff1a;GAN医学影像合成–双向映射生成对抗网络用于脑部 MR 到 PET 合成 01 文献速递介绍 作为精准医学的基石&#xff0c;多模态医学图像已成为必备要素。稿件收到日期&#xff1a;2021年6月26日&#xff1b;修改日期&#xff1a;2021年8月6日&#xff1b;接受…

常用的消息中间件RabbitMQ

目录 一、消息中间件 1、简介 2、作用 3、两种模式 1、P2P模式 2、Pub/Sub模式 4、常用中间件介绍与对比 1、Kafka 2、RabbitMQ 3、RocketMQ RabbitMQ和Kafka的区别 二、RabbiMQ集群 RabbiMQ特点 RabbitMQ模式⼤概分为以下三种: 集群中的基本概念&#xff1a; 集…

Linux系统安全:安全技术和防火墙

目录 一、安全技术和防火墙 1.安全技术 2.防火墙的分类 二、防火墙 1.iptables四表五链 2.黑白名单 3.iptables基本语法 4.iptables选项 5.控制类型 6.隐藏扩展模块 7.显示扩展模块 8.iptables规则保存 9.自定义链使用 一、安全技术和防火墙 1.安全技术 入侵检测系…