【基础算法总结】分治—归并
分治—归并
- 1.排序数组
- 2.交易逆序对的总数
- 3.计算右侧小于当前元素的个数
- 4.翻转对
点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃
1.排序数组
题目链接:912. 排序数组
题目描述:
算法原理:
归并排序的核心思想就是,选一个中间节点,将数组分成左右两区间,先将左边排排序相当于又是一个归并过程,选一个中间节点然后在把左边排序,当区间只有一个元素就可以向上返回。左边拍完序,在对右边排排序,当左右排好序后在合并,选择小的插入,然后拷贝回原数组。
快速排序就是选择一个key将数组分块,然后左右继续指向数组分块的核心操作,当数组被分成一个元素或者没有元素就结束分块。
所以说快排和归并非常类似,无非就是处理数组时间不一样。归并画成树就是一个后序,先处理左在处理右然后将左右合并,快排就是一个前序,先把数组分两块,然去搞左边,左边还是找一个key然后分成左和右。。。
class Solution {
public:vector<int> tmp;vector<int> sortArray(vector<int>& nums) {int n = nums.size();tmp.resize(n);Mergesort(nums, 0, n-1);return nums;}void Mergesort(vector<int>& nums, int left, int right){if(left >= right) return;// 1. 选择中间点划分区间int mid = left + (right - left) / 2;//[left ,mid] [mid+1, right]// 2.把左右区间排序Mergesort(nums, left, mid);Mergesort(nums, mid + 1, right);// 3.合并两个有序数组int cur1= left, cur2 = mid + 1, i = 0;while(cur1 <= mid && cur2<= right)tmp[i++] = nums[cur1] < nums[cur2] ? nums[cur1++] : nums[cur2++];while(cu1 <= mid) tmp[i++] = nums[cur1++];while(cur2<= right) tmp[i++] = nums[cur2++];// 4.拷贝回原数组for(int i = left; i <= right; ++i)nums[i] = tmp[i - left];}
};
2.交易逆序对的总数
题目链接:LCR 170. 交易逆序对的总数
题目分析:
逆序对是两个数前面的数比后面的大就是逆序对。
算法原理:
解法一:暴力解法->暴力枚举
把所有二元组枚举出来看看是不是逆序对。两层for循环,但是超时。
如果想求整个数组的逆序对的时候,我把数组按照中间点分成两部分,然后求整个数组逆序对的时候,先求出左边逆序对的个数假设是a,在求出右边逆序对的个数假设是b,然后左边挑一个数右边挑一个数求出一左一右的逆序对个数假设是c。那a+b+c 就是整个逆序对个数。因为本质还是暴力枚举。
接下来我们在扩展一下,左半部分挑完之后排个序,右半部分跳完之后也排个序,然后左右都有序了在一左一右挑。这也是正确的,因为左半部分挑出来a后在排序不会影响结果, 右半部分挑出来b后在排序也不会影响结果。无非影响的是一左一右。但是我们左边挑一个右边挑一个是不管顺序的。我们从左边挑选一个数,然后在从右边挑选比我小的数的个数就行了,从右边挑选一个数,然后在从左边挑选比我大的数的个数就行了,至于有没有序和我没关系。
当到这里的时候你会发现其实就是一个归并排序。
解法二:利用归并排序解决问题
选择中间点把数组分成两份,先去左区间找,如果左区间太大还可以在选个中间点在把数组分开直到不能分了就找逆序对,同理右边也是。最后一左一右去找逆序对,这个策略正好对应归并的过程。左半部分和右边部分可以在递归中完成,我们的核心就是解决一左一右。同样左边部分+左排序放在一起递归中完整,右半部分+右排序放在一起递归完成,我们核心还是处理一左一右。因为递归都是的统一,所以一左一右后面在加一个排序。
左半部分 + 左排序 + 右半部分 + 右排序 + 一左一右 + 排序
这个时候有个小问题为什么非要排序呢?
虽然会有空间的开销,但是会变得非常快。
利用归并排序后,数组左右区间已经是有序的了。假设是升序的。cur1和cur2之前的都是都是比cur1和cur2小的元素。
此时统计逆序对的话,按照如下策略可以一次找到一堆逆序对。
策略一:找出该数之前,多少个数比我大
此时我们固定的是cur2,因为我们是一左一右找,想要找比我大的数,盯的是后面的数,去看看左半部分有多少个比我大。此时就和归并排序完美契合。无非就是三种情况。
当 nums[cur1] < nums[cur2],说明还没有在左边找到比cur2大,所以cur1++
当 nums[cur1] == nums[cur2],还是没有在左边找到比cur2大,所以cur1++
上面两种情况可以合在一起
nums[cur1] <= nums[cur2], cur1++,注意别忘记放进归并数组里。
当 nums[cur1] > num[cur2] ,当前cur1比cur2元素大,别忘记我们可是升序数组,而且cur1比cur2的时候是cur1第一次出现比cur2大,cur1后面的元素都是比cur2大的!此时我们就是根据归并排序的一次比较就找到一堆cur1比cur2大的数。此时用一个变量记录一下cur1位置到左边结束的位置的个数就可以了。ret += mid - cur1 + 1,一次就统计出来一大堆。而且cur1比cur2大的时候,我们下一次想让cur2向后移,这正好和归并排序一样,让小的往后移。
时间复杂度O(nlogn)
当前策略 找出该数之前,多少个数比我大,对于数组升序是没问题的,那这个数组是降序的能不能解决这个问题,只要找比我大的不管升序还是降序都是固定cur2,在左边找比cur2大的。
此时如果nums[cur1] > nums[cur2] ,要统计左边开始到cur1有多个元素,但是有一个致命问题,cur1往前走一步的位置可能继续比cur2大,还是要统计左边开始到cur1有多个元素。然后你就会发现重复了。
因此 策略一 :找出该数之前,多少个数比我大 只能是升序,不能是降序!
固定cur2
那降序就没有用武之地了嘛?并不是。
策略二 :找出该数之后,有多少个数比我小 只能是降序
固定cur1,在右边部分找比cur1小的。当cur1比cur2大的时候,cur2是第一个出现的因为又是降序所以cur1比cur2后面元素都大,此时直接统计个cur2到右区间的个数 ret += right - cur2 + 1。而且统计完个数之后,已经把比cur1小的都找到了,此时让cur1右移,而且正好和归并排序是一样的。
如果是升序的话也会有重复计算的问题。
至此算法原理就结束了,其实就是利用前两部分析出来这道题可以用分治的方法来做。想求整个数组的逆序数,我可以先求左区间逆序数,在求右区间逆序数,然后一左一右挑一个求逆序数。所以这就是一个分支。然后发现数组有序的话可以通过一次比较统计一大推,因此可以用归并排序来解决这个问题。
class Solution {vector<int> tmp;
public:int reversePairs(vector<int>& record) {int n = record.size();tmp.resize(n);return Mergesort(record, 0, n - 1);}int Mergesort(vector<int>& nums, int left, int right){if(left >= right) return 0;int ret = 0;// 1.找中间节点,将数组分成两部分int mid = (left + right) >> 1;//[left,mid] [mid+1,right]// 2. 左边的个数 + 排序 + 右边的个数 + 排序ret += Mergesort(nums, left, mid);ret += Mergesort(nums, mid + 1, right);// 3. 一左一右的个数int cur1 = left, cur2 = mid + 1, i = 0;// while(cur1 <= mid && cur2 <= right) //升序// {// if(nums[cur1] <= nums[cur2])// {// tmp[i++] = nums[cur1++];// }// else// {// ret += mid - cur1 + 1;// tmp[i++] = nums[cur2++];// }// }while(cur1 <= mid && cur2 <= right) //降序{if(nums[cur1] <= nums[cur2]){tmp[i++] = nums[cur2++];}else{ret += right - cur2 + 1;tmp[i++] = nums[cur1++];}}// 4. 处理一下排序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];return ret;}
};
3.计算右侧小于当前元素的个数
题目链接:315. 计算右侧小于当前元素的个数
题目分析:
给一个nums数组,返回一个count数组,count[i] 的值是 对应nums[i] 右侧小于 nums[i] 的元素的数量。
这也是求逆序对,但并不是求总体的逆序对个数,而是每个数的逆序对个数。
就是给一个数看看右边比我少的有多少个。我们也是可以按照归并排序来处理这个问题,但难得就是这返回数组怎么搞。
算法原理:
解法:归并排序
选择一个中间点,将数组分成左右两部分,先在左半部分找,在到右半部分找,然后一左一右找。
左半部分 + 排序 + 右半部分 + 排序 + 一左一右 + 排序
策略二: 找出该数之后,有多少个数比我小 只能是降序
固定cur1
当 nums[cur1] <= nums[cur2] ,因为是降序此时并没有找到有多少个元素比cur1小,所以不更新结果让cur2++
当 nums[cur1] > nums[cur2] ,第一次出现cur1比cur2,因为是降序所以此时cur2后面所有元素都比cur1小,此时可以统计一大堆,但是我们这里可不是搞一个ret来记录,而是搞一个数组,要把nums[cur1] 对应的 index(下标) 里面的 ret += right - cur2 +1
就比如这个数组,当计算出比当前位置元素小的个数是要把结果记录到这个元素对应的位置上的。
因此当算出nums[cur1]右边有多少个比我小的时候,最终加的结果是这个值对应的原始下标对应的值 += right - cur2 + 1。
所以我们着重要解决的问题是,当我们找到当前位置的值右边有多少个比我小的时候,我要能找到这个值得原始下标。 找到 nums 中当前元素的原始下标是多少? 因为排完序后原本数对应的下标就已经乱了!当前位置cur1 可能并不是我真实的下标。
可能你会想到用哈希表,但是,如果数组里面有重复元素,就难搞了。所以我们直接搞一下和原始数组大小的index数组,记录当前元素的原始下标。不管nums里面怎么办,就把index和nums里面对应的值绑定!nums里面的值动,index里面的值也动! 这样就可以通过index里面值找到当前值原始下标在哪里,然后就可以加了。
回归上面的问题 把nums[cur1] 对应的 index(下标) 里面的 ret += right - cur2 +1 就可以变成这样 ret[index[cur1]] += ret += right - cur2 +1。
当归并排序移动nums时,我们要合并两个有序数组,别忘记我们需要一个tmp辅助数组帮助我们合并。那如何让nums合并,index也同步绑定呢? 因此需要两个tmp辅助数组!
class Solution {vector<int> ret; vector<int> tmpNum;vector<int> tmpIndex;vector<int> index; // 记录 nums 中当前元素的原始下标
public:vector<int> countSmaller(vector<int>& nums) {int n = nums.size();ret.resize(n);tmpNum.resize(n);tmpIndex.resize(n);index.resize(n);for(int i = 0; i < n; ++i) index[i] = i; // 初始化 index 数组Mergesort(nums, 0, n - 1);return ret;}void Mergesort(vector<int>& nums, int left, int right){if(left >= right) return;// 1. 根据中间点,划分区间int mid = left + (right - left) / 2;//[left, mid] [mid+1, right]// 2. 先处理左右两部分Mergesort(nums, left, mid);Mergesort(nums, mid + 1, right);// 3. 处理一左一右的情况int cur1 = left, cur2 = mid + 1, i = 0;while(cur1 <= mid && cur2 <= right) // 降序{if(nums[cur1] <= nums[cur2]){tmpNum[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}else{ret[index[cur1]] += right - cur2 + 1;tmpNum[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}}// 4.处理剩下排序过程while(cur1 <= mid){tmpNum[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}while(cur2 <= right){tmpNum[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}for(int i = left; i <= right; ++i){nums[i] = tmpNum[i - left];index[i] = tmpIndex[i- left];}}
};
4.翻转对
题目链接:493. 翻转对
题目分析:
当 i < j 且 nums[i] > 2*nums[j],才是翻转对。
算法原理:
解法:分治
这个问题你会发现和求逆序对非常相似的,想求整个数组的翻转对,先求左半部分的翻转对记为a,在求右半部分的翻转对记为b,然后求一左一右的翻转对记为c。a+b+c就是整个数组的翻转对。
这个就有个致命的问题,逆序对的题和归并排序完美契合,仅需比较
i < j,nums[i] > nums[j] 。但是这道题要比较的是 i < j,nums[i] > 2 * nums[j]。这个时候就不能按照归并排序的流程求翻转对了,我们要重新想一个策略来求翻转对。
我们依旧用的是分治的策略来解决,但是并不是用的是归并排序里面的一个过程来解决我们的问题,我们是在归并排序之前来计算翻转对个数。因为我们要利用两个区间有序的性质,我们可以在一次归并中用O(N)的时间复杂度搞定这一层的翻转对的个数
计算翻转对
策略一:计算当前元素后面,有多少元素的两倍比我小。 降序
固定cur1
整个数组都是降序的,固定cur1,当 2 * nums[cur2] >= nums[cur1] cur2往后移,
当 2 * nums[cur2] < nums[cur1] ,因为是降序的,cur2后面一堆元素2倍都比cur1小,所以 ret += right - cur2 +1, cur1的翻转对都找完了所以往后移动就行了。注意cur2此时是不用回溯的!因为数组是降序的,cur2之前的元素都比cur1还没有移动的2倍大,cur1往后走一步元素变小了,那cur2之前不就比当前cur1位置更大嘛,所以不用回溯,如果回溯时间复杂度 计算翻转对就是O(n^2),那整体时间复杂度就变成O(n ^2 logn)。直到cur1到尾或者cur2到尾就结束了。
计算翻转对:利用单调性,使用同向双指针。
策略二:计算当前元素之前,有多少元素的一半比我大。 升序
固定cur2
整个数组都是升序的,固定cur2,当 nums[cur1] / 2 <= nums[cur1] cur1往后移,
当 nums[cur1] / 2 > nums[cur2] ,因为是升序的,cur1后面一堆元素的一半都比cur2大,所以 ret += mid - left +1, cur2的翻转对都找完了所以往后移动就行了。此时cur1也不需要回溯。因为是数组是升序的,cur2往后走一步是变大的,cur1还没有往后移动之前前面的元素一半都比cur2小,现在cur往后走一步变大,肯定比cur1还没有往后移动之前更大,所以cur1不需要回溯。
注意上面只是计算翻转对,别忘记还要还要合并两个有序数组。
降序
class Solution {vector<int> tmp;
public:int reversePairs(vector<int>& nums) {int n = nums.size();tmp.resize(n);return Mergesort(nums, 0, n - 1);}int Mergesort(vector<int>& nums, int left, int right){if(left >= right) return 0;int ret = 0;// 1. 选择中间点将数组划分区间int mid = (left + right) >> 1;// 2. 先计算左右两侧的翻转对ret += Mergesort(nums, left, mid);ret += Mergesort(nums, mid + 1, right);// 3. 先计算翻转对的数量int cur1 = left, cur2 = mid + 1; while(cur1 <= mid && cur2 <= right)//降序{//if(2 * nums[cur2] < nums[cur1]) //乘法溢出 改成 除法if(nums[cur2] < nums[cur1] / 2.0){ret += right - cur2 + 1;cur1++;}else cur2++;}// 4. 合并两个有序数组cur1 = left, cur2 = mid + 1;int i = left;while(cur1 <= mid && cur2 <= right){if(nums[cur2] < nums[cur1]) tmp[i++] = nums[cur++];else tmp[i++] = 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];return ret; }
};
升序
class Solution {vector<int> tmp;
public:int reversePairs(vector<int>& nums) {int n = nums.size();tmp.resize(n);return Mergesort(nums, 0, n - 1);}int Mergesort(vector<int>& nums, int left, int right){if(left >= right) return 0;int ret = 0;// 1. 选择中间点将数组划分区间int mid = (left + right) >> 1;// 2. 先计算左右两侧的翻转对ret += Mergesort(nums, left, mid);ret += Mergesort(nums, mid + 1, right);// 3. 先计算翻转对的数量int cur1 = left, cur2 = mid + 1; while(cur1 <= mid && cur2 <= right)//升序{//if(2 * nums[cur2] < nums[cur1]) //乘法溢出 改成 除法if(nums[cur2] < nums[cur1] / 2.0){ret += mid - cur1 + 1;cur2++;}else cur1++;}// 4. 合并两个有序数组cur1 = left, cur2 = mid + 1;int i = left;while(cur1 <= mid && cur2 <= right){if(nums[cur2] < nums[cur1]) tmp[i++] = nums[cur2++];else tmp[i++] = nums[cur1++];}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];return ret; }
};
相关文章:

【基础算法总结】分治—归并
分治—归并 1.排序数组2.交易逆序对的总数3.计算右侧小于当前元素的个数4.翻转对 点赞👍👍收藏🌟🌟关注💖💖 你的支持是对我最大的鼓励,我们一起努力吧!😃😃 1.排序数组 …...

基于Java+SpringMvc+Vue技术的实验室管理系统设计与实现(6000字以上论文参考)
博主介绍:硕士研究生,专注于信息化技术领域开发与管理,会使用java、标准c/c等开发语言,以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年,拥有近12年的管理工作经验,拥有较丰富的技术架…...

19_谷歌GoogLeNet(InceptionV1)深度学习图像分类算法
1.1 简介 GoogLeNet(有时也称为GoogleNet或Inception Net)是一种深度学习架构,由Google的研究团队在2014年提出,主要设计者为Christian Szegedy等人。这个模型是在当年的ImageNet大规模视觉识别挑战赛(ILSVRC…...

clickhouse高可用可拓展部署
clickhouse高可用&可拓展部署 1.部署架构 1.1高可用架构 1.2硬件资源 部署服务 节点名称 节点ip 核数 内存 磁盘 zookeeper zk-01 / 4c 8G 100G zk-02 / 4c 8G 100G zk-03 / 4c 8G 100G clikehouse ck-01 / 32c 128G 2T ck-02 / 32c 128G 2T ck-03 / 32c 128G 2T ck-04 /…...

QT中QDomDocument读写XML文件
一、XML文件 <?xml version"1.0" encoding"UTF-8"?> <Begin><Type name"zhangsan"><sex>boy</sex><school>Chengdu</school><age>18</age><special>handsome</special>&l…...

sql盲注
文章目录 布尔盲注时间盲注 布尔盲注 介绍:在网页只给你两种回显的时候是用,类似于布尔类型的数据,1表示正确,0表示错误。 特点:思路简单,步骤繁琐且麻烦。 核心函数: length()函数substr()函…...

星网安全产品线成立 引领卫星互联网解决方案创新
2024年6月12日,盛邦安全(688651)成立星网安全产品线,这是公司宣布全面进入以场景化安全、网络空间地图和卫星互联网安全三大核心能力驱动的战略2.0时代业务落地的重要举措。 卫星互联网技术的快速发展,正将其塑造为全球…...

Adam自适应动量优化算法
Adam(Adaptive Moment Estimation)是一种结合了动量法和自适应学习率思想的优化算法,特别适用于训练神经网络和深度学习模型。以下是对Adam调整学习率的详细介绍及具体例子。 一、Adam调整学习率介绍 自适应学习率: Adam算法的核…...

Mac OS系统中Beyond Compare 4破解方式
文章出处 https://blog.csdn.net/qq_42418042/article/details/137544113 前言 记录实操过程,以防以后找不到了~ 实际原理是启动时删除文件,实现无限试用 实操过程 下载安装包 官网链接 https://www.scootersoftware.com/download.php 解压、移动到应…...

6000元最好的家用投影仪:当贝X5S Pro六千元配置最高画质最强
数码家电品牌发展迅速,投影同样也是一种更新迭代较快的产品类型,有时候去年还比较火的产品,今年就会被别的产品取代,就比如之前灯泡投影一直被认为是好产品的代表,但是现在国产激光投影的销量反而更高。一般来说6000元…...

#### golang中【堆】的使用及底层 ####
声明,本文部分内容摘自: Go: 深入理解堆实现及应用-腾讯云开发者社区-腾讯云 数组实现堆 | WXue 堆(Heap)是实现优先队列的数据结构,Go提供了接口和方法来操作堆。 应用 package mainimport ("container/heap&q…...

OpenAI Gym Atari on Windows
题意:在Windows系统上使用OpenAI Gym的Atari环境 问题背景: Im having issues installing OpenAI Gym Atari environment on Windows 10. I have successfully installed and used OpenAI Gym already on the same system. It keeps tripping up when t…...

Java进阶----接口interface
接口 接口概述 接口是一种规范,使用接口就代表着要在程序中制定规范. 制定规范可以给不同类型的事物定义功能,例如: 利用接口,给飞机、小鸟制定飞行规范,让其都具备飞行的功能;利用接口,给鼠…...

【网络协议】ISIS
ISIS IS-IS(Intermediate System to Intermediate System,中间系统到中间系统)协议是一种用于在自治系统(AS)内部进行路由选择的链路状态路由协议。它最初是为OSI(开放系统互连)网络设计的&…...

一.4 处理器读并解释储存在内存中的指令
此刻,hello.c源程序已经被编译系统翻译成了可执行目标文件hello,并被存放在硬盘上。要想在Unix系统上运行该可执行文件,我们将它的文件名输入到称为shell的应用程序中: linux>./hello hello, world linux> shell是一个命令…...

【Android面试八股文】Android性能优化面试题:怎样检测函数执行是否卡顿?
文章目录 卡顿一、可重现的卡顿二、不可重现的卡顿第一种方案: 基于 Looper 的监控方法第二种方案:基于 Choreographer 的监控方法第三种方案:字节码插桩方式第四种方案: 使用 JVMTI 监听函数进入与退出总结相关大厂的方案ArgusAPMBlockCanaryQQ空间卡慢组件Matrix微信广研参…...

C语言7 控制语句
目录 1. 条件语句 if 语句 if-else 语句 if-else if-else 语句 switch 语句 2. 循环语句 for 循环 while 循环 do-while 循环 3. 跳转语句 break 语句 continue 语句 return 语句 goto 语句 1. 条件语句 if 语句 if语句根据给定条件的真或假来决定是否执行某段…...

go mod 依赖管理补充2
依赖包的版本问题,别的开发语言有没有类似的问题?是怎么解决的? 举例:java java的依赖包的版本问题,通过Maven模块来操作,可以指定依赖包版本号,如下: go.mod 文件 go.mod文件是G…...

【Git】取消追踪多个文件或目录
文章目录 场景方法1. 添加到 .gitignore2. 从暂存区移除 示例1. 编辑 .gitignore 文件2. 从暂存区移除文件或目录 场景 清理:不再希望某些文件被 Git 追踪。配置忽略文件:通常配合 .gitignore 文件使用,以便以后这些文件不会被重新添加到索引…...

【Linux详解】进程等待 | 非阻塞轮询
引入: 为什么?是什么?怎么办 是什么? 进程等待是指父进程暂停自己的执行,直到某个特定的子进程结束或发生某些特定的事件。 为什么? 僵尸进程刀枪不入,不可被杀死,存在内存泄露…...

聊一下Maven打包的问题(jar要发布)
文章目录 一、问题和现象二、解决方法(1)方法一、maven-jar-pluginmaven-dependency-plugin(2)方法二、maven-assembly-plugin 一、问题和现象 现在的开发一直都是用spring boot,突然有一天,要自己开发一个…...

JavaScript中,正则表达式所涉及的api,解析、实例和总结
JS中正则的api包括以下: String#searchString#splitString#matchString#replaceRegExp#testRegExp#exec 1. String#search 查找输入串中第一个匹配正则的index,如果没有匹配的则返回-1。g修饰符对结果无影响 var string "abbbcbc"; var r…...

【计算机】同步/异步
同步/异步 在计算机科学和编程中,“同步”(Synchronization)是一种机制,用于协调不同进程或线程之间的操作,以避免竞态条件(race conditions)、死锁(deadlocks)和其他并…...

谈大语言模型动态思维流程编排
尽管大语言模型已经呈现出了强大的威力,但是如何让它完美地完成一个大的问题,仍然是一个巨大的挑战。 需要精心地给予大模型许多的提示(Prompt)。对于一个复杂的应用场景,编写一套完整的,准确无误的提示&am…...

工厂自动化相关设备工业一体机起到什么作用?
在当今的制造业领域,工厂自动化已成为提高生产效率、保证产品质量和降低成本的关键。在这一进程中,工业一体机作为一种重要的设备,发挥着不可或缺的作用。 工业一体机是自动化生产线上的控制中心。它能够整合和处理来自各个传感器、执行器和其…...

哈佛大学 || 概念空间中学习动态的涌现:探索隐藏能力
获取本文论文原文PDF,请在公众号【AI论文解读】留言:论文解读 今天主要看一个问题:在模型中的学习动态是如何涌现的。 在现代生成模型的研究与应用中,不断发现这些模型在处理训练数据时展现出了惊人的能力,这些能力很…...

Dockerfile打包部署常用操作
文章目录 1、Dockerfile部署java程序(jar包)1.1、创建Dockerfile1.2、将Dockerfile和要上传的jar包放到一个目录下,构建镜像1.3、创建启动容器 2、Dockerfile部署vue2.1、创建dockerfile文件2.2、将打包的dist文件放到dockerfile同文件目录下…...

ArcGIS:探索地理信息系统的强大功能与实际应用
ArcGIS是一款功能强大的地理信息系统(GIS)软件,由Esri公司开发。它广泛应用于各个领域,包括城市规划、环境保护、资源管理、交通运输等。作为一名长期使用ArcGIS的用户,我深感这款软件在数据分析、地图制作和空间信息管…...

Python 全栈体系【三阶】(二)
第一章 Django 五、模板 1. 概述 Django中的模板是指可以动态生成任何基于文本格式文件的技术(如HTML、CSS等)。 Django中内置了自己的模板系统,称为DTL(Django Template Language), Django模板语言。 2. 配置 settings.py中关于模板的…...

【VUE】 深入理解 Vue 动态路由:简介、实际开发场景与代码示例
深入理解 Vue 动态路由:简介、实际开发场景与代码示例 Vue.js 是一个用于构建用户界面的渐进式框架,它拥有丰富的生态系统,其中 Vue Router 是其官方的路由管理库。动态路由是 Vue Router 的一个强大特性,允许我们在应用运行时根…...