分治算法区

分治

  • 一.分治
  • 二.经典应用案例
  • 三.快速排序
    • (1)颜色分类
    • (2)排序数组
    • (3)数组中第K个最大的元素
  • 四.归并排序
    • 1.排序数组
    • 2.交易逆序对总数
    • 3.计算右侧小于当前元素的个数
    • 4.翻转对

一.分治

分治算法是一种通过将复杂问题分解为多个结构相似的子问题,递归求解后再合并结果来解决原问题的算法设计范式。其核心思想可概括为三个步骤:

  • 分(Divide):将原问题分解为若干规模较小的子问题。

  • 治(Conquer):递归或直接求解子问题。

  • 合(Combine):将子问题的解合并为原问题的解。

二.经典应用案例

  • 归并排序(Merge Sort):将数组分为两半分别排序,再合并有序子数组。

  • 快速排序(Quick Sort):通过枢轴划分子数组,递归排序后合并。

  • 二分查找(Binary Search):每次将搜索区间减半,定位目标值。

  • Strassen矩阵乘法:通过分块矩阵运算,将时间复杂度从 O(n3)优化至 O(n2.81 )。

  • 最近点对问题:分解点集,分别求解后合并邻近区域的解。

三.快速排序

(1)颜色分类

颜色分类

思路:将数组分为三个小数组,第一个数组的数据为0的区域,第二个数组的数据为1的区域,第三个数组的数据为2的数据。简单地说,就是通过三个指针分成四个区域,[0,left]是0区域,[left + 1,i-1]是1的区域,[i,right-1]是带扫描区域,[right,n-1]是2的区域
分为四个区域之后,将中间区域作为key值进行比较,当扫描区域的值小于key值,则先让left+1后,修改此时left和i位置上的数据,再让i进行++;如果此时扫描的数据和key相等,则直接i++,继续扫描后面的区域。
如果此时扫描的值大于key值,先让right-1后,再进行i和right位置上的值进行交换,需要注意的是,此时i不能++,因为此时数据换了之后,无法确定此时i位置换后的数据等于key,所以应该再扫描一次i位置的数据,再进行一次比较,和上述的方法一样不再赘述。
还需要注意的是,left的下标是-1,right的下标是n,补药记成left的下标为0,right的下标为n-1

自我心得:一个新的排序算法思路,最重要的是理解下图中的扫描位置后交换位置细节。

在这里插入图片描述

class Solution {public void sortColors(int[] nums) {int left = -1,right = nums.length, i = 0;while(i < right) {if(nums[i] == 0) {swap(nums,++left,i++);               }else if(nums[i] == 1) {i++;   }else {swap(nums,--right,i);}  }}public void swap(int[] nums,int x ,int y){int tmp = nums[x];nums[x] = nums[y];nums[y] = tmp;}
}

(2)排序数组

排序数组

思路:
使用的是快排的递归思路,只不过其中的partation是使用三指针,也就是上一道题中的颜色分类中的思想进行划分。

细节:
我认为最重要的是进行递归的时候,要区分l和left,r和right,这样写代码时更容易理解,其中left和right则就是颜色分类中的思想中的left和right
还需要注意的是,这里的key值不像颜色分类中的key值直接给了具体的数字,所以需要通过随机值获取一个数据,在算法导论中概率随机数的随机值需要的时间复杂度更小,这个随机值的取法需要注意其中Random括号中的细节,要记住加上偏移量l

自我反思:要知道每次排序后,排序的区域是哪一块,而不是直接凭感觉写,更不是背记住代码,还需要知道取随机数时,要注意是r-l后还要+1,但是具体的情况下看你如何进行取值,使用r-l+1是为了等概率的获取[0,n - 1]的下标,再加上偏移量L,就能够选取一个中间的key值(个人理解,有误请指出)

class Solution {public int[] sortArray(int[] nums) {qsort(nums,0,nums.length-1);return nums;}public void qsort(int[] nums,int l,int r) {//递归出口if(l >= r) return;//数组分三块int left = l - 1,right = r + 1, i = l;int key  = nums[new Random().nextInt(r - l + 1) + l];//执行完后,[left + 1, right - 1]排序完成while(i < right) {if(nums[i] < key) swap(nums,++left,i++);else if(nums[i] == key) i++;else swap(nums,--right,i);}//区域分为[l,left] [left + 1, right - 1] [right, r]qsort(nums,l,left);//比当前key值小的区域排序qsort(nums,right,r);//比当前key值大的区域排序}public void swap(int[] nums, int x, int y) {int tmp = nums[x];nums[x] = nums[y];nums[y] = tmp;}
}

(3)数组中第K个最大的元素

数组中第K个最大的元素

思路:通过前面学习的颜色分类+排序数组中的思想进行查找第N个大的数,这里不能使用top-k问题的堆解法是因为超时了,top-k的时间需要N*logN。与上两道题不同的是,这里需要的是一个数值,所以简单分析一下。
数组会被分为3块,此时每一块都进行计算其中元素的个数(从左到右依次为a,b,c),因为是升序的排列,所以只需要判断k和a,b,c的三者大小即可,第一种情况则是c >= k的时候,此时只需要在大于key值的数组中寻找,如果此时b + c >= k,此时就是为key值的数组,此时直接返回key就行了。如果此时b + c < k,就直接在小于key值的数组中寻找第k - b - c大的值
需要注意的是,这里可以不需要递归出口,因为不是对其全部进行排列,只是通过k三个区域数组的长度来进行寻找需要的第K大的数。还需要注意的是,此时找到第K大的数时,不需要做其他的返回,因为找打第K大的数值时,它就是key值。
反思:写题的时候不知道key值的返回是通过找到第K大的值为key的值时返回的,做题时的深入不够多,一直在思考找到第K大所在的区域后,通过第K大数的k值也就是第K大数的下标进行计算出它在原数组中的位置来进行返回,我感觉是不可行的,因为好像越界了。还是要去多思考每个返回带来的效果,而不是再次的凭感觉写。

class Solution {public int findKthLargest(int[] nums, int k) {return qsort(nums,0,nums.length-1,k);}public int  qsort(int[] nums, int l, int r, int k) {if(l >= r) return nums[l];int left = l - 1, right = r + 1, i = l;int key = nums[new Random().nextInt(r - l + 1) + l];while(i < right) {if (nums[i] > key) {swap(nums,--right,i);}else if (nums[i] == key) {i++;}else {swap(nums,++left,i++);}}   int b = right - 1 - left, c =  r - right + 1;if(c >= k) {return qsort(nums,right,r,k);      }else if (b + c >= k) {return key;}else {return qsort(nums,l,left,k - b - c);}}public void swap(int[] nums, int x, int y) {int tmp = nums[x];nums[x] = nums[y];nums[y] = tmp;}
}

四.归并排序

1.排序数组

排序数组

思路:
简单的复习一下归并排序的写法,归并排序通过中间点将数组分成两块区域,再将中点的左右两侧通过递归将数组排序成有序数组后,再将整个数组进行合并后,再通过临时数组进行还原数组的操作。
细节:
不断地通过递归将数组分为两块区域,直到数组只有一个数据时,此时则返回,并且先进行完左边的递归后,再进行右边的递归,两处的递归执行完后,对这两块有序数组进行合并,合并的方式通过双指针的方式按照大小的顺序合并,并且使用临时数组进行存储后,再将数据还原给原数组。
还需要注意的是,合并的时候选择数组中小数据进行合并后,在两块数组区域比大小的循环中,会存在有一块数组先达到数组的长度后退出循环,此时就需要在写一个循环判断是哪一块数组还没合并完,将没有合并完的数组拼接到临时数组上。

class Solution {int tmp[];public int[] sortArray(int[] nums) {tmp = new int[nums.length];//归并mergesort(nums,0,nums.length - 1);return nums;}public void mergesort(int[] nums, int left, int right) {if(left >= right) return;//1.根据中间点分成两块区域int mid = (right + left) / 2;//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(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= right) tmp[i++] = nums[cur2++];//4.覆盖数据for (int j = left; j <= right; j++) {nums[j] = tmp[j - left];}}}

2.交易逆序对总数

交易逆序对总数

思路:逆序数需要用前面的数字和后面小的数字比较,如果前面的数字大,则逆序数+1,反之则逆序数不变。类似于这样的场景可以通过归并将数组不断划分成两个区域进行比较,于是便可以使用归并排序。
可以使用两个策略:
策略一:右边区域的数组块中指定数据后,在左边区域的数组块中找到比右边区域数组块大的数据就行,又因为左边区域数组块进行归并排序时就进行了升序的排序操作,此时在左边区域数组块中的数据的mid - cur1+ 1个数据都比右边数组块指定的数据大,也有对应个数的逆序数。在这里插入图片描述

策略二:左右两块区域通过降序进行排列,此时将左边区域的数据中指定一个后,在右边区域块中找到一个比左边区域块小的数据后,就会有right - cur2 + 1 个数的数据比左边区域的指定数据小。在这里插入图片描述
注意:
在cur1和cur2的为下标的数组值进行比较时,相等的情况出现时,应该让被指定数据的区域数组块进行下标向右移动的操作,不然是不行的。
还需要注意的是,在策略1中只能通过升序来进行计数,如果通过降序就会出现,当cur1下标向右时,只能使用策略二的方式来进行计数,按照策略一中指定左边区域数组块作为指定数据区就没办法进行计数了。如果非要使用cur1 - left + 1进行计数的话,那么此时前面计算过的区域都被重复计算了,如果通过ret++的行为进行计数,是不行的,因为你会循环遍历右边区域的数组块。
反思:
在递归时不能习惯性的将left传入0,而是要注意传入left就应该传入left而不是习惯传入0,这样的错误还是太低级了,不太注意细节,还需要多多仔细的掌握算法。

class Solution {int[] tmp;int ret = 0;public int reversePairs(int[] record) {tmp = new int[record.length];mergesort(record, 0, record.length - 1);return ret;}public void mergesort(int[] record, int left, int right) {if(left >= right) return ;//进行分块int mid = (left + right) / 2;//递归排序mergesort(record, left, mid);mergesort(record, mid + 1, right);int cur1 = left, cur2 = mid + 1, i = 0;//合并并计算逆序对(使用升序)while(cur1 <= mid && cur2 <= right) {if(record[cur1] <= record[cur2]) {tmp[i++] = record[cur1++];}else {tmp[i++] = record[cur2++];ret += mid - cur1 + 1;}}//合并并计算逆序对(使用降序)while(cur1 <= mid && cur2 <= right) {if(record[cur1] <= record[cur2]) {tmp[i++] = record[cur2++];}else {tmp[i++] = record[cur1++];ret += right - cur2 + 1;}}while(cur1 <= mid) tmp[i++] = record[cur1++];while(cur2 <= right) tmp[i++] = record[cur2++];//还原到原数组for(int j = left; j <= right; j++) {record[j] = tmp[j - left];}}
}

3.计算右侧小于当前元素的个数

计算右侧小于当前元素的个数

思路:
这里需要上述第2题中讲到的策略二的方法,降序进行找值。但是不同的是,返回的数据是一个链表每个原始元素下标对应满足题意的个数(也就是这个原始元素下标的右侧有几个元素的值比它小,记录下比它小的元素的个数)。

这里就增加了难度,因为进行归并排序时,原数组中原始元素的下标肯定是发生变化了,此时需要搞一个index数组记住原始元素的下标。

index数组,这个数组本身的下标就是原始元素的下标,而index这个数组下标对应的元素就是原始元素排序后的下标,就可以让原始元素的下标和index下标对应的元素进行绑定。
注意:
还原数据之前,index数组也需要创建一个临时数组进行对原始元素的下标进行更新。
反思:
没有搞清楚index下标中的数据和数组本身的下标哪个代表什么,没有搞明白,理解的时候非常吃力,根据自己画图几次后,就理解到了里面的原理,总结就是还得多加练习,这个题又做了2个小时。

class Solution {int[] tmp;//更新降序排好的数组位置int[] tmpIndex;//更新原数组中元素现在所处位置的新下标int[] index;//记录原始数组下标位置的数组,该数组中的数据代表原始数组中元素现在的位置int[] ret;public List<Integer> countSmaller(int[] nums) {ret = new int[nums.length];tmp = new int[nums.length];tmpIndex = new int[nums.length];index = new int[nums.length];//先把原始数组下标的位置记录到数组中for (int i = 0; i < nums.length; i++) {index[i] = i;}List<Integer> l = new ArrayList<>();mergesort(nums, 0, nums.length - 1);for (int x : ret) {l.add(x);}return l;}public void mergesort(int[] nums, int left, int right) {if (left >= right) return;//进行分区域int mid = (left + right) / 2;//左右递归排序并计数mergesort(nums, left, mid);mergesort(nums, mid + 1, right);//进行计数操作int cur1 = left, cur2 = mid + 1, i = 0;while (cur1 <= mid && cur2 <= right) {if (nums[cur1] <= nums[cur2]) {tmp[i] = nums[cur2];tmpIndex[i++] = index[cur2++];//因为元素进行排序后就会导致原数组的元素的下标发生改变,为了记住原数组的下标//就通过index数组中的数据将原数组中的元素的现在的下标记录下来,所以在元素进行交换位置时,也需要进行对index数据的改变}else {tmp[i] = nums[cur1];ret[index[cur1]] += right - cur2 + 1;//由于index数组自己的下标就是原数组元素对应的下标//则通过cur1这个原始元素的下标就可以在index中找到此时这个原始元素下标现在的下标是什么//知道下标后就在ret中进行计算,原始元素下标这个位置的右侧比它小的原始数据有几个。tmpIndex[i++] = index[cur1++];//也要对index数组的数据进行临时保存,方便后续对index数组元素的还原操作}}//剩余的也添加到临时数组中while (cur1 <= mid) {tmp[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}while (cur2 <= right) {tmp[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}//还原操作for (int j = left; j <= right; j++) {nums[j] = tmp[j - left];index[j] = tmpIndex[j - left];}}
}

4.翻转对

翻转对

思路:
这道题和上面的题不同的是,计算翻转对时,不会在进行左右数组合并的时候计算翻转对数。这道题是先将翻转对数计算完后,再进行数组的合并,并且策略一和二都可以使用只是需要注意其中使用的细节。
细节:
里面会需要使用到乘以2倍,或者除以2,这里需要注意的是,使用乘时,会达到int类型的最大值。因为int类型的值达到最大值时,此时进行加或者乘操作就会导致实际数字减小。
因为int类型的范围是:-2147483648~2147483647,此时如果值为2147483647,加1或者乘2,都会变成比2147483647小的数,此时判断的逻辑就错误了。
如果出现这样的情况,可以使用long类型先获取int类型的值后,再对此时的值进行乘以2操作就不会造成超过范围了。
还有除以2的时候要使用2.0才是浮点数,不然不会出现小数,也会对判断进行干扰。

class Solution {int[] tmp;int ret = 0;public int reversePairs(int[] nums) {if(nums.length < 2) {return 0;}tmp = new int[nums.length];mergesort(nums, 0, nums.length - 1);return ret;}public void mergesort(int[] nums, int left, int right) {if (left >= right) return;//找中点分块int mid = (left + right) / 2;//左右递归进行排序mergesort(nums, left, mid);mergesort(nums, mid + 1, right);int cur1 = left, cur2 = mid + 1, i = 0;// //计算翻转对(升序计算)// while (cur1 <= mid && cur2 <= right) {//     double n1 = nums[cur1] / 2.0;//     if(n1 > nums[cur2]) {//         ret += mid - cur1 + 1;//         cur2++;//     }else {//         cur1++;//     }// }// //合并两个数组(升序)// cur1 = left;// cur2 = mid + 1;// while (cur1 <= mid && cur2 <= right) {//     if (nums[cur1] > nums[cur2]) {//         tmp[i++] = nums[cur2++];//     }else {//         tmp[i++] = nums[cur1++];//     }// }// //剩余的未合并完的数组//  while (cur1 <= mid) tmp[i++] = nums[cur1++];//  while (cur2 <= right) tmp[i++] = nums[cur2++];//计算翻转对(降序计算)while (cur1 <= mid && cur2 <= right) {long n1 = nums[cur1];long n = nums[cur2];long n2 = 2 * n;if(n1 > n2) {ret += right - cur2 + 1;cur1++;}else {cur2++;}}//合并两个数组(降序)cur1 = left;cur2 = mid + 1;while (cur1 <= mid && cur2 <= right) {if (nums[cur1] > nums[cur2]) {tmp[i++] = nums[cur1++];}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 - left];}}
}

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

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

相关文章

设计模式C++

针对一些经典的常见的场景, 给定了一些对应的解决方案&#xff0c;这个就叫设计模式。 设计模式的作用&#xff1a;使代码的可重用性高&#xff0c;可读性强&#xff0c;灵活性好&#xff0c;可维护性强。 设计原则&#xff1a; 单一职责原则&#xff1a;一个类只做一方面的…

零成本搭建Calibre个人数字图书馆支持EPUB MOBI格式远程直读

文章目录 前言1.网络书库软件下载安装2.网络书库服务器设置3.内网穿透工具设置4.公网使用kindle访问内网私人书库 前言 嘿&#xff0c;各位书虫们&#xff01;今天要给大家安利一个超级炫酷的技能——如何在本地Windows电脑上搭建自己的私人云端书库。亚马逊服务停了&#xff…

Qt 数据库操作(Sqlite)

数据库简介 关于数据库的基础知识这里就不做介绍了&#xff0c;相关博客可以查看&#xff1a; SQL基础知识 数据库学霸笔记 上面博客都写的比较详细&#xff0c;本文主要介绍如何使用Qt进行数据库相关操作&#xff0c;数据库分为关系型数据库和非关系型数据&#xff0c;关系…

hackme靶机详细攻略

扫描ip arp-scan -l 访问网站后&#xff0c;点击sign up now注册 注册后登录 点击search显示全部数据 尝试sql注入 确认闭合方式 OSINTand 12# 确定列数 OSINT order by 3# 显示正常 OSINT order by 4# 显示异常 确认回显位置 -1 union select 1,2,3# 确认数据库名 -…

Tweak Power:全方位电脑系统优化的高效工具

在日常使用电脑时&#xff0c;系统性能的下降、垃圾文件的堆积以及硬盘的老化等问题常常困扰着用户。为了提升电脑性能、优化系统运行&#xff0c;许多人会选择系统优化工具。然而&#xff0c;国内一些系统优化软件常常因为广告过多或功能冗杂而让人望而却步。此时&#xff0c;…

element-plus中Autocomplete自动补全输入框组件的使用

目录 1.基本使用 ①从官网赋值如下代码 ②查看运行效果 ③代码解读 2.调用后端接口&#xff0c;动态获取建议数据 结语 1.基本使用 ①从官网赋值如下代码 <template> <div><!-- 自动补全输入框 --><el-autocompletev-model"state":fetc…

SSM基础专项复习6——Spring框架AOP(3)

系列文章 1、SSM基础专项复习1——SSM项目整合-CSDN博客 2、SSM基础专项复习2——Spring 框架&#xff08;1&#xff09;-CSDN博客 3、SSM基础专项复习3——Spring框架&#xff08;2&#xff09;-CSDN博客 4、SSM基础专项复习4——Maven项目管理工具&#xff08;1&#xff…

MATLAB基于ResNet18的交通标志识别系统

1. 数据准备 数据集&#xff1a;该数据集包含了大量标注好的交通标志图片&#xff0c;每类标志都有不同的样本。数据预处理&#xff1a;图像需要进行一些基本的预处理&#xff0c;如调整大小、归一化等&#xff0c;以适应ResNet18的输入要求。 2. 网络设计 使用MATLAB自带的…

【2步解决】phpstudy开机自启(自动启动phpstudy、mysql、nignx或apache、自动打开网址)

重启执行最终效果图&#xff1a; 一、场景 线下部署&#xff0c;需要开启自动动&#xff0c;并打开网址http://localhost/。 二、操作步骤 ①、新建start.txt&#xff0c;并修改为start.bat&#xff0c;使用记事本编辑&#xff0c;粘贴上方代码如下&#xff1a; echo off:…

C++20 `<bit>` 中的整数 2 的幂运算和 `std::bit_cast`:由浅入深的探索

文章目录 引言 1\. 整数 2 的幂运算1.1 检测是否为 2 的幂&#xff1a;std::has_single_bit1.2 计算不小于 x 的最小 2 的幂&#xff1a;std::bit_ceil1.3 计算不大于 x 的最大 2 的幂&#xff1a;std::bit_floor 2\. std::bit_cast2.1 基本用法2.2 实用场景&#xff1a;字节序…

阿里巴巴发布 R1-Omni:首个基于 RLVR 的全模态大语言模型,用于情感识别

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Ubuntu24.04 LTS 版本 Linux 系统在线和离线安装 Docker 和 Docker compose

一、更换软件源并更新系统 在 Ubuntu 24.04 LTS 中&#xff0c;系统引入了全新的软件源配置格式。现在的源配置文件内容更加结构化且清晰&#xff0c;主要包含了软件类型 (Types)、源地址 (URIs)、版本代号 (Suites) 以及组件 (Components) 等信息。 # cat /etc/apt/sources.li…

ALSA vs OSS:Linux 音频架构的演变与核心区别

在 Linux 音频系统的发展过程中&#xff0c;OSS&#xff08;Open Sound System&#xff09; 和 ALSA&#xff08;Advanced Linux Sound Architecture&#xff09; 曾分别在不同阶段承担着音频管理的角色。OSS 是 Linux 早期的音频架构&#xff0c;而 ALSA 作为其继任者&#xf…

DeepSeek-R1深度解读

deepseek提出了一种通过强化学习&#xff08;RL&#xff09;激励大语言模型&#xff08;LLMs&#xff09;推理能力的方法&#xff0c;个人认为最让人兴奋的点是&#xff1a;通过RL发现了一个叫“Aha Moment”的现象&#xff0c;这个时刻发生在模型的中间版本中。在这个阶段&…

【鸿蒙开发】Hi3861学习笔记- GPIO之直流电机

00. 目录 文章目录 00. 目录01. GPIO概述02. 直流电机概述03. ULN2003模块概述04. 硬件设计05. 软件设计06. 实验现象07. 附录 01. GPIO概述 GPIO&#xff08;General-purpose input/output&#xff09;即通用型输入输出。通常&#xff0c;GPIO控制器通过分组的方式管理所有GP…

图的存储--十字链表与邻接多重表

一、十字链表&#xff08;存储有向图&#xff09; (邻接表找顶点的入度不方便 邻接矩阵的时间复杂度高) 用十字链表可以解决查找入度不方便的问题 1.十字链表中对于弧节点总共有4个节点 A、B、C、D、分别指向弧尾顶点的编号、弧头顶点的编号、弧头相同的下一条弧、弧尾相同…

DataEase:一款国产开源数据可视化分析工具

DataEase 是由飞致云开发的一款基于 Web 的数据可视化 BI 工具&#xff0c;支持丰富的数据源连接&#xff0c;能够通过拖拉拽方式快速制作图表&#xff0c;帮助用户快速分析业务数据并洞察其趋势&#xff0c;为企业的业务改进与优化提供支持。 DataEase 的优势在于&#xff1a;…

Matlab:矩阵运算篇——矩阵数学运算

目录 1.矩阵的加法运算 实例——验证加法法则 实例——矩阵求和 实例——矩阵求差 2.矩阵的乘法运算 1.数乘运算 2.乘运算 3.点乘运算 实例——矩阵乘法运算 3.矩阵的除法运算 1.左除运算 实例——验证矩阵的除法 2.右除运算 实例——矩阵的除法 ヾ(&#xffe3;…

学习率调整策略

学习率衰减策略是深度学习优化过程中的一个关键因素&#xff0c;它决定了训练过程中学习率的调整方式&#xff0c;从而影响模型收敛的速度和效果。不同的衰减策略在不同的任务和模型上可能有不同的表现&#xff0c;下面从我用到过的几个衰减策略进行记录&#xff0c;后续慢慢跟…

BIG_EVENT

环境准备: 开发: 跨域问题: 只有浏览器才存在跨域问题, 此时浏览器的地址和前端服务一致,所以不存在跨域问题, 但是当浏览器中的js代码需要向8080发送请求时就会由于存在跨域问题而失败. 简单的说前端和浏览器的地址端口是一致的,浏览器只能向前端服务发送请求, 所以可以使用配…