归并分治 计算数组的小和 + 图解 + 笔记

news2025/1/17 21:47:29

 归并分治 前置知识:讲解021-归并排序

归并排序 图解 递归 + 非递归 + 笔记-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_41987016/article/details/134338789?spm=1001.2014.3001.5501原理:

  • (1)思考一个问题在大范围上的答案,是否等于,左部分的答案 + 右部分的答案 + 跨越左右产生的答案
  • (2)计算“跨越左右产生的答案”时,如果加上左、右各自有序这个设定,会不会获得计算的便利性
  • (3)如果以上两点都成立,那么该问题很可能被归并分治解决(话不说满,因为总有很毒的出题人)
  • (4)求解答案的过程中只需要加入归并排序的过程即可,因为要让左、右各自有序,来获得计算的便利性

补充:

  • (1)一些用归并分治解决的问题,往往也可以用线段树,树状数组等解法。时间复杂度也都是最优解,这些数据结构都会在【扩展】
  • (2)本书讲述的题目都是归并分治的常规题,难度不大。归并分治不仅可以解决简单问题,还可以解决很多较难的问题,只要符合上面说的特征。比如二维空间里任何两点间的最短距离问题,这个内容会在【挺难】课程阶段里讲述。顶级公司考这个问题的也很少,因为很难,但是这个问题本身并不冷门,来自《算法导论》原题
  • (3)还有一个常考的算法:“整块分治”。会在【必备】课程阶段讲到

举个栗子】假设数组 s = [1,3,5,2,4,6],给定一个数组arr,实现函数返回arr的“小和”

    在s[0]的左边所有 <= s[0]的数的总和为0
    在s[1]的左边所有 <= s[1]的数的总和为1
    在s[2]的左边所有 <= s[2]的数的总和为4
    在s[3]的左边所有 <= s[3]的数的总和为1
    在s[4]的左边所有 <= s[4]的数的总和为6
    在s[5]的左边所有 <= s[5]的数的总和为15
所以s数组的 “小和” 为:0 + 1 + 4 + 1 + 6 + 15 = 27

  • "小和"问题是,当我 j 来到一个位置的时候,你的左侧 i 去给我划答案  

C++代码:

#include <iostream>
using namespace std;
#include <vector>

// 返回跨左右产生的小和累加和,左侧有序、右侧有序,让左右两侧整体有序
// arr[left...mid] arr[mid+1...right]
long merge(vector<int>& arr,int left, int mid, int right) {
	int n = right - left + 1;
	vector<int> help(n, 0);
	// 统计部分
	long ans = 0;
	for (int j = mid + 1, i = left, sum = 0; j <= right; j++) {
		while (i <= mid && arr[i] <= arr[j]) {
			sum += arr[i++];
		}
		ans += sum;
	}
	// 正常merge
	int i = 0;
	int a = left;
	int b = mid + 1;
	while (a <= mid && b <= right) {
		help[i++] = arr[a] <= arr[b] ? arr[a++] : arr[b++];
	}
	while (a <= mid) {
		help[i++] = arr[a++];
	}
	while (b <= right) {
		help[i++] = arr[b++];
	}
	for (i = 0; i < n; i++) {
		arr[i+left] = help[i];
	}
	return ans;
}

// 结果比较大,用 int 会溢出的,所以返回 long 类型
// 特别注意溢出这个点,笔试常见坑
// 返回arr[left...right]范围上,小和的累加和,同时把arr[left...right]变有序
long smallSum(vector<int>&arr, int left, int right) {
	if (left == right) return 0;
	//int mid = (left + right) / 2;
	int mid = left + ((right - left) >> 1);
	return smallSum(arr,left, mid) + smallSum(arr,mid + 1, right) + merge(arr,left, mid, right);
}

int main() {
	vector<int>arr = { 7,7,6,2,6,5,4,9 };
	//vector<int>arr = { 1, 3, 5, 2, 4, 6 };
	int n = arr.size();
	cout<<"该数组的小和为:"<<smallSum(arr,0, n - 1)<<endl;
	system("pause");
	return 0;
}

计算数组的小和__牛客网 (nowcoder.com)icon-default.png?t=N7T8https://www.nowcoder.com/questionTerminal/edfe05a1d45c4ea89101d936cac32469?f=discussion

  •  实战牛客网[编程题]计算数组的小和
#include <iostream>
#include <vector>
using namespace std;
// 返回跨左右产生的小和累加和,左侧有序、右侧有序,让左右两侧整体有序
// arr[left...mid] arr[mid+1...right]
long merge(vector<int>& arr, int left, int mid, int right) {
	int n = right - left + 1;
	vector<int> help(n, 0);
	// 统计部分
	long ans = 0;
	for (int j = mid + 1, i = left, sum = 0; j <= right; j++) {
		while (i <= mid && arr[i] <= arr[j]) {
			sum += arr[i++];
		}
		ans += sum;
	}
	// 正常merge
	int i = 0;
	int a = left;
	int b = mid + 1;
	while (a <= mid && b <= right) {
		help[i++] = arr[a] <= arr[b] ? arr[a++] : arr[b++];
	}

	while (a <= mid) {
		help[i++] = arr[a++];
	}
	while (b <= right) {
		help[i++] = arr[b++];
	}
	for (i = 0; i < n; i++) {
		arr[i + left] = help[i];
	}
	return ans;
}


// 结果比较大,用 int 会溢出的,所以返回 long 类型
// 特别注意溢出这个点,笔试常见坑
// 返回arr[left...right]范围上,小和的累加和,同时把arr[left...right]变有序
long smallSum(vector<int>& arr, int left, int right) {
	if (left == right) return 0;
	//int mid = (left + right) / 2;
	int mid = left + ((right - left) >> 1);
	return smallSum(arr, left, mid) + smallSum(arr, mid + 1, right) + merge(arr, left, mid, right);
}

int main() {
	int n;
	cin >> n;
	vector<int> arr(n, 0);
	for (int i = 0; i < n; i++) cin >> arr[i];
	cout << smallSum(arr, 0, n - 1) << endl;
	return 0;
}

参考和推荐视频:

算法讲解022【必备】归并分治_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1L14y1B7ef/?spm_id_from=333.788.recommend_more_video.-1&vd_source=a934d7fc6f47698a29dac90a922ba5a3

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

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

相关文章

Flink之Table API SQL连接器

连接器 Table API & SQL连接器1.概述2.支持连接器 DataGen连接器1.概述2.SQL客户端执行3.Table API执行 FileSystem连接器1.创建FileSystem映射表2.创建source数据源表3.写入数据4.解决异常5.查询fileTable6.查看HDFS Kafka连接器1.添加kafka连接器依赖2.重启yarn-session、…

微软和Red Hat合体:帮助企业更方便部署容器

早在2015年&#xff0c;微软就已经和Red Hat达成合作共同为企业市场开发基于云端的解决方案。时隔两年双方在企业市场的多个方面开展更紧密的合作&#xff0c;今天两家公司再次宣布帮助企业更方便地部署容器。 双方所开展的合作包括在微软Azure上部署Red Hat OpenShift&#xf…

实战Leetcode(四)

Practice makes perfect&#xff01; 实战一&#xff1a; 这个题由于我们不知道两个链表的长度我们也不知道它是否有相交的节点&#xff0c;所以我们的方法是先求出两个链表的长度&#xff0c;长度长的先走相差的步数&#xff0c;使得两个链表处于同一起点&#xff0c;两个链…

运筹说 第102期 | 非线性规划—制约函数法

通过上期学习&#xff0c;大家已经了解了非线性规划中约束极值问题的最优性条件。本期小编将为大家介绍约束极值问题的求解方法&#xff1a;制约函数法&#xff0c;包括概念以及最基本的两种制约函数法&#xff1a;罚函数法、障碍函数法等内容。 制约函数法是通过构造某种制约函…

tomcat下载与使用教程

1. tomcat下载 官网&#xff1a;https://tomcat.apache.org/ 镜像地址&#xff1a;https://mirrors.huaweicloud.com/apache/tomcat/ 1、选择一个版本下载&#xff0c;官网下载速度缓慢&#xff0c;推荐镜像 2、对压缩包进行解压&#xff0c;无需进行安装&#xff0c;解压放…

PyTorch技术和深度学习——三、深度学习快速入门

文章目录 1.线性回归1&#xff09;介绍2&#xff09;加载自由泳冠军数据集3&#xff09;从0开始实现线性回归模型4&#xff09;使用自动求导训练线性回归模型5&#xff09;使用优化器训练线性回归模型 2.使用torch.nn模块构建线性回归模型1&#xff09;使用torch.nn.Linear训练…

智能指针,c++11,单例,类型转换

c11 unique_ptr 防拷贝 shared_ptr / weak_ptr: 引用计数,支持拷贝 面试 手写shared_ptr 各种ptr的特性对比, 不会问定制删除器和weak_ptr,但是问shared_ptr时,可以往这边延展. 单例 保证一写数据在一个进程中,只有一份,并且方便访问修改. 饿汉模式 在main函数之前就创…

Java中的多态究竟是什么?

目录 一.概念二.使用条件三.重写1.概念2.使用条件3.与重载对比4.举例5.为什么需要重写1.重写规则 2.静态绑定--重载3.动态绑定--重写 四.向上转型第一种传参方式&#xff1a;直接赋值第二种传参方式&#xff1a;通过传参优缺点 五.向下转型举例缺点 六.多态的优缺点优点缺点 一…

【Python 千题 —— 基础篇】账号登录

题目描述 题目描述 简易登录系统。你的账号密码分别是 “student”&#xff0c;“123456”&#xff1b;请使用 if-else 设计一个简易登录系统&#xff0c;输入账号密码。登陆成功输出 “Welcome !”&#xff0c;登录失败输出 “Login failed !” 输入描述 输入账号和密码。…

分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测

分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测 目录 分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现PSO-LSTM粒子群算法优化长短…

vue3+vite搭建后台项目-1 引入element-plus 中文包,打包时报错问题

vue3vite搭建后台项目-1 引入element-plus 中文包,打包时报错问题 终端报错 If theelement-pluspackage actually exposes this module, try adding a new declaration (.d.ts) file containing are moduleelement-plus/dist/locale/zh-cn.mjsdec import zhCn fromelement-plus…

VS c++多文件编译

前言&#xff1a;记录下我这个菜鸡学习的过程&#xff0c;如有错误恳请指出&#xff0c;不胜感激&#xff01; 1.简单多文件编译调试 文件目录&#xff1a; 编译&#xff1a; -g选项是告诉编译器生成调试信息&#xff0c;这样可以在程序崩溃或出现错误时更容易地进行调试。这…

思维模型 多看效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。越熟悉&#xff0c;越喜欢。 1 多看效应的应用 1.1 多看效应在广告和营销领域的应用 1 可口可乐之歌 可口可乐公司在 20 世纪 60 年代推出了“可口可乐之歌”广告&#xff0c;这个广告通…

华为ensp:交换机接口划分vlan

现在要把 e0/0/1 接口放入vlan1 e0/0/2 接口放入vlan2 e0/0/3 接口放入vlan3 默认所有接口都在vlan1所以 e0/0/0 接口不用动 1.创建vlan 进入系统视图模式 直接输入 vlan 编号 即可创建对应vlan vlan 编号 vlan 2 创建vlan2 vlan 3 创建vlan3 2.将接口进入vlan…

【java:牛客每日三十题总结-5】

java:牛客每日三十题总结 总结如下 总结如下 -Xmx&#xff1a;最大堆大小 -Xms&#xff1a;初始堆大小 -Xmn:年轻代大小 -XXSurvivorRatio&#xff1a;年轻代中Eden区与Survivor区的大小比值 年轻代5120m&#xff0c; Eden&#xff1a;Survivor3&#xff0c;Survivor区大小102…

【Git】的分支和标签的讲解及实际应用场景

目录 一、讲解 1. 环境讲述 2. 应用原因 3. 分支标签的区别 二、分支 1. 命令 2. 场景应用 三、标签 1. 命令 2. 标签规范 3. 应用场景 每篇一获 一、讲解 1. 环境讲述 当软件从开发到正式环境部署的过程中&#xff0c;不同环境的作用如下&#xff1a; 开发环境&a…

电脑清灰涂硅脂后电脑CPU温度不降反升

目录 一.问题描述二.问题解决三.拆机注意事项四.影响散热的主要因素说明1.通风差2.硅脂材料差3.硅脂涂抹方式错误 一.问题描述 电脑型号&#xff1a;暗影精灵5 测温工具&#xff1a;硬件狗狗&#xff08;只要是测温软件都可以&#xff0c;比如omen hub和Core Temp…&#xff0…

LeetCode146.LRU缓存

写了一个小时&#xff0c;终于把示例跑过了&#xff0c;没想到啊提交之后第19/22个测试用例没过 我把测试用例的输出复制在word上看看和我的有什么不同&#xff0c;没想到有18页的word&#xff0c;然后我一直检查终于找出了问题&#xff0c;而且这个bug真的太活该了&#xff0c…

Sprint Boot 学习路线 4

微服务 Spring Microservices是一个框架&#xff0c;它使用Spring框架更容易地构建和管理基于微服务的应用程序。微服务是一种架构风格&#xff0c;其中一个大型应用程序被构建为一组小型、独立可部署的服务。每个服务具有明确定义的职责&#xff0c;并通过API与其他服务通信。…

CCNA课程实验-13-PPPoE

目录 实验条件网络拓朴需求 配置实现基础配置模拟运营商ISP配置ISP的DNS配置出口路由器OR基础配置PC1基础配置 出口路由器OR配置PPPOE拨号创建NAT(PAT端口复用) PC1测试结果 实验条件 网络拓朴 需求 OR使用PPPoE的方式向ISP发送拨号的用户名和密码&#xff0c;用户名&#xf…