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

 归并分治 前置知识:讲解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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux文件系统——重定向

文章目录 1. 文件描述符分配规则2. 重定向接口dup2自定义shell重定向(补充) 3. 标准输出和标准错误4. 如何理解一切接文件 本章代码gitee地址&#xff1a;文件重定向 1. 文件描述符分配规则 文件描述符的分配规则是从0下标开始&#xff0c;寻址最小的没有使用的数组位置&#…

可以体现Python语法精妙的十个例子!

文章目录 前言1.for - else2.一颗星*和两颗星**3.三元表达式4.with - as5.列表推导式6.列表索引的各种骚操作7.lambda函数8.yield 以及生成器和迭代器9.装饰器10.巧用断言assertPython技术资源分享1、Python所有方向的学习路线2、学习软件3、精品书籍4、入门学习视频5、实战案例…

Linux JumpServer 堡垒机远程访问

文章目录 前言1. 安装Jump server2. 本地访问jump server3. 安装 cpolar内网穿透软件4. 配置Jump server公网访问地址5. 公网远程访问Jump server6. 固定Jump server公网地址 前言 JumpServer 是广受欢迎的开源堡垒机&#xff0c;是符合 4A 规范的专业运维安全审计系统。JumpS…

野火i.MX6ULL开发板检测按键evtest(Linux应用开发)

之前一直查找不到evtest&#xff0c;因为没有下载成功&#xff0c;很可能是网络不好&#xff0c;下次可以软件源可以换成国内大学镜像网站。 重新断开板子电源启动&#xff0c;再次连接网络&#xff0c;下载evtest成功&#xff01;&#xff01;

PHP中传值与引用的区别

在PHP中&#xff0c;变量的传递方式主要分为传值和传引用两种。这两种方式在操作中有一些重要的区别&#xff0c;影响着变量在函数调用或赋值操作中的表现。下面详细解释一下这两种传递方式的区别。 传值&#xff08;By Value&#xff09; 传值是指将变量的值复制一份传递给函…

VB.NET—Bug调试(参数话查询、附近语法错误)

目录 前言: BUG是什么&#xff01; 事情的经过: 过程: 错误一: 错误二: 总结: 前言: BUG是什么&#xff01; 在计算机科学中&#xff0c;BUG是指程序中的错误或缺陷&#xff0c;它通过是值代码中的错误、逻辑错误、语法错误、运行时错误等相关问题&#xff0c;这些问题…

CL-MVSNet论文精读

本文是对CL-MVSNet: Unsupervised Multi-View Stereo with Dual-Level Contrastive Learning Kaiqiang Xiong, Rui Peng, Zhe Zhang, Tianxing Feng, Jianbo Jiao, Feng Gao, Ronggang Wang的阅读记录 Proceedings of the IEEE/CVF International Conference on Computer Visio…

miniconda安装

1.下载&#xff1a; Miniconda — miniconda documentation 点击选择对应版本下载&#xff1a; 2.安装 点击next 注意&#xff01;&#xff01;&#xff01; 在选择为谁安装的时候建议选择just me&#xff08;这会让你构建的虚拟环境默认保存在安装路径的envs下&#xff0c…

Nacos入门到运行-超详细~windwos

&#x1f4da;目录 ⚙️简介:⚡️Nacos下载⌛解压到文件⚙️配置信息☘️修改 application.properties ⛵运行程序☘️安全问题☄️程序出现问题查看方式 ⛳Nacos开启鉴权⚡️跳过Token获取数据⚓接口请求&#xff1a; ✍️结束&#xff1a; ⚙️简介: Nacos:正如官网说的,一个…

使用 HTTP Client 轻松进行 API 测试

在开发过程中&#xff0c;我们经常需要测试 API 接口以确保其正常工作。JetBrains 的集成开发环境&#xff08;IDE&#xff09;如 CLion、IntelliJ IDEA、PyCharm 等&#xff0c;默认内置了 HTTP Client 插件&#xff0c;可以方便地进行API测试。本文将介绍如何使用HTTP Client…

人工智能与教育:未来的技术融合

人工智能与教育&#xff1a;未来的技术融合 随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;逐渐渗透到我们生活的方方面面&#xff0c;包括教育领域。AI与教育的结合&#xff0c;有望引发一场教育变革&#xff0c;提高教学效果&#xff0c;实现个性化学习&…

Python 列表元素里面含有字典或者列表进行排序

大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 示例1&#xff1a;列表里面含有列表进行排序 s [[1, 2], [100, 2], [33, 3], [25, 6]] s.sort(keylambda k: k[0]) print(s)结果&#xff1a; [[1, 2], [25, 6], [33, 3…

SplayTree高分测试用例

测试用例结果展示 覆盖率 变异得分 测试注意点 从SplayTree测起&#xff0c;然后再测SubSplayTree&#xff0c;因为前者调用后者。SplaySubTree的remove方法大部分内容需要通过反射才能测到。value和index在SplayTree当中都不是唯一的。一个index可能对应多个value。 不足之…

[西湖论剑 2022]real_ez_node

文章目录 前置知识EJS模板注入&#xff08;CVE-2022-29078&#xff09;原型链污染漏洞 &#xff08;CVE-2021-25928&#xff09;HTTP响应拆分攻击&#xff08;CRLF&#xff09; 解题过程代码审计构造payload 前置知识 EJS模板注入&#xff08;CVE-2022-29078&#xff09; EJS…

ChatGPT 如何改变科研之路

《Nature》全球博士后调查[1]中约有三分之一的受访者正在使用人工智能聊天机器人来帮助完善文本、生成或编辑代码、整理其领域的文献等等。 来自巴西的 Rafael Bretas 在日本生活了十多年&#xff0c;日语说得很好。书面日语的各个方面&#xff0c;例如严格的礼貌等级制度&…

【蓝桥每日一题]-快速幂,倍增,滑动窗口(保姆级教程 篇1) #麦森数 #青蛙跳

之前是考试准备&#xff0c;所以有几天没更新&#xff0c;今天开始继续更新 目录 快速幂模板 题目&#xff1a;麦森数 思路&#xff1a; 题目&#xff1a;青蛙跳 思路&#xff1a; 快速幂模板 #include <bits/stdc.h> #define ll long long using namespa…

如何知道一个程序为哪些信号注册了哪些信号处理函数?

https://unix.stackexchange.com/questions/379694/is-there-a-way-to-know-if-signals-are-present-in-your-application-and-which-sign 使用 strace

数据结构与算法【二分查找】Java实现

需求&#xff1a;在有序数组 A 内&#xff0c;查找值target 如果找到返回索引如果找不到返回 -1 前提 给定一个内含 n 个元素的有序数组 A&#xff0c;一个待查值 target 1 设置 i0&#xff0c;jn-1 2 如果 i \gt j&#xff0c;结束查找&#xff0c;没找到 3 设置 m (…

只会CRUD程序员朋友,你开始拥抱云计算技术了吗

阅读建议 嗨&#xff0c;伙计&#xff01;刷到这篇文章咱们就是有缘人&#xff0c;在阅读这篇文章前我有一些建议&#xff1a; 本篇文章大概6000多字&#xff0c;预计阅读时间长需要6分钟。本篇文章的理论性较强&#xff0c;是一篇质量分数较高的技术文章&#xff0c;建议收藏…

STM32F407的看门狗

文章目录 看门狗时钟两种看门狗IWDG结构图作用 寄存器IWDG_KR键值寄存器IWDG_PR预分频寄存器2-0 PR预分频器系数 IWDG_RLR重装载寄存器IWDG_SR状态寄存器1RVU 重载值更新0 PVU 预分频值更新注意 写保护超时时间使用步骤取消寄存器 写保护设置预分频系数和重装载值看门狗溢出时间…