【算法】贪心算法

一、贪心算法基本思想

  1. 贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从
    整体最优考虑
    ,它所作出的选择只是在某种意义上的局部最优选择。

  2. 我们希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不
    能对所有问题都得到整体最优解(Optimal Solution),但对许多问
    题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。

  3. 某些情况下,即使贪心算法不能得到整体最优解,但通常能获得近似
    最优解
    (Near-Optimal Solution)。

  4. 贪心算法有两个基本要素
    贪心选择性质
    最优子结构性质

二、简单案例

2.1. 找零钱问题

【问题描述】找零钱时,每次尽可能地选取最大面额的钞票
实例:
10元−3元=7元,找零:5 + 2
100元−3元=97元,找零:50 + 20 + 20 + 5 + 2
100元−14元=86元,找零:50 + 20 + 10 + 5 + 1 (没有更优的找钱方案)
在这里插入图片描述
最优性证明

  1. 若x的值为1, 2, 5,那么所需的零钱为1张,这显然是最少的。
  2. 否则,所需的钱数至少为2张。算法对3, 4, 6, 7生成的找钱方案分别为 2+1, 2+2, 5+1, 5+2,这显然也是最少的。
  3. 若x的值为8 和 9,算法生成的找钱方案分别为5+2+1和5+2+2;而用 2 张钞票不能找出8元或9元的零钱,因此算法的结果也是最少的。

如果将x的值扩大到100以内,并增加面值为50, 20和10元的钞票,那么使用贪心算法仍然能够得到最优的找零钱方案,即每次尽可能地选取最大面额的零钞。

在找零问题每一步的贪心选择中,在不超过应付款金额的条件下,只选择面值最大的货币,而不去考虑在后面看来这种选择是否合理,而且它还不会改变决定:一旦选出了一张货币,就永远选定。

找零问题的贪心选择策略是尽可能使付出的货币最快地满足支付要求,其目的是使付出的货币张数最慢地增加,这正体现了贪心法的设计思想

三、贪心算法

贪心算法:在问题求解的过程中采用“贪婪”的策略来构造目标解。
实现起来较为简单,难点通常在于算法的正确性证明。

可以用贪心算法求解的问题中看到这类问题一般具有2个重要的性质:贪心选择性质最优子结构性质

3.1. 贪心算法的基本要素

3.1.1.贪心选择性质,与动态规划的区别和共同点

所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别

动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每作一次贪心选择就将所求问题简化为规模更小的子问题

对于一个具体问题,要确定它是否具有贪心选择性质,必须证明每一步所作的贪心选择最终导致问题的整体最优解。

3.1.2. 最优子结构性质

当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。

贪心算法和动态规划算法要求问题具有最优子结构性质,这是两类算法的一个共同点

四、案例

4.1 背包问题

【0-1背包问题】

  1. 给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。
  2. 问题:应如何选择装入背包的物品,使得装入背包中物品的总价值最大
  3. 物品i给要么装入背包,要么不装入背包。不能部分装入、不能装入多次。

【背包问题】
与0-1背包问题类似,所不同的是在选择物品i装入背包时,可以选择物品i
的一部分,而不一定要全部装入背包,1≤i≤n 。

这两类问题都具有最优子结构性质,极为相似,但背包问题可以用贪心算法求解,而0-1背包问题却不能用贪心算法求解

4.1.1用贪心算法解背包问题的基本步骤

首先计算每种物品单位重量的价值vi / wi;然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。

void Knapsack(int n,float M,float v[],float w[],float x[])
{Sort(n,v,w);int i;for (i=1;i<=n;i++) x[i]=0;float c=M;for (i=1;i<=n;i++) {if (w[i]>c) break;x[i]=1;c-=w[i];}if (i<=n) x[i]=c/w[i];
}

算法knapsack的主要计算时间在于将各种物品依其单位重量的价值从大到小排序。因此,算法的计算时间上界为O(nlogn)

为了证明算法的正确性,还必须证明背包问题具有贪心选择性质。

4.1.2 背包问题 示例

0-1背包问题
有三种物品,背包容量为50公斤。物品1重10公斤,价值60元,物品2重20公斤,价值100元,物品3重30公斤,价值120元。因此,物品1每公斤价值6元,物品2每公斤价值5元,物品3每公斤价值4元。

若依贪心选择策略,应首先物品1装入背包,然后装入物品2。然而从图b的可以看出,最优选择方案是选择物品2和3装入背包。首选物品1的方案不是最优的

对于背包问题,贪心选择最终可得到最优解,其选择方案如图c所示
在这里插入图片描述
分析
对于0-1背包问题,贪心选择之所以不能得到最优解是因为在这种情况下,它无法保证最终能将背包装满,部分闲置的背包空间使每公斤背包空间的价值降低了。

事实上,在考虑0-1背包问题时,应比较选择该物品和不选择该物品所导致的最终方案,然后再作出最好选择。由此就导出许多互相重叠的子问题。这正是该问题可用动态规划算法求解的另一重要特征。

实际上也是如此,动态规划算法可以有效地解0-1背包问题。

背包问题示例
有一个背包,背包容量是M=150。有7个物品,物品的重量及价值见下表。物品可以分割成任意大小。
要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
在这里插入图片描述
如果分别采用以下贪心策略求解,是否可以得到最优解
(1)每次挑选价值最大的物品装入背包
(2)每次挑选所占重量最小的物品装入背包
(3)每次选取单位重量价值最大的物品装入背包

贪心算法是常见的算法之一,这是由于它简单易行,构造贪心策略不是很困难。但是,它需要证明后才能真正运用到题目的算法中。

一般来说,贪心算法的证明围绕着:整个问题的最优解一定由在贪心策略中存在的子问题的最优解得来的。(最优子结构性质)

4.2 活动安排问题

【问题描述】 活动安排问题就是要在所给的活动集合中选出最大的相容活动子集合。

设有n个活动的集合E={1,2,…,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si <fi。如果选择了活动i,则它在半开时间区间[si, fi)内占用资源。若区间[si, fi)与区间[sj, fj)不相交,则称活动i与活动j是相容的。也就是说,当si≥fj或sj≥fi时,活动i与活动j相容。

活动安排问题就是要在某一时间段安排尽可能多的活动。

活动安排问题是可以用贪心算法有效求解的很好例子。该问题要求高效地安排一系列争用某一公共资源的活动。贪心算法提供了一个简单、漂亮的方法使得尽可能多的活动能兼容地使用公共资源。

贪心策略:每次选择具有最早完成时间的相容活动,使剩余的可安排时间段极大化,以便安排尽可能多的相容活动。

实例:设待安排的11个活动的开始时间和结束时间按结束时间的非减序排列如下
在这里插入图片描述

下图中每行相应于一次迭代。阴影长条表示的活动是已选入集合的活动,而空白长条表示的活动是当前正在检查相容性的活动。
在这里插入图片描述
贪心算法伪代码

void GreedySelector(int n, s[], f[], boolean a[])
{a[1]=true;int j=1;for (int i=2;i<=n;i++) {if (s[i]>=f[j]) {a[i]=true;j=i;}else a[i]=false;}
}

【算法正确性证明】
若被检查的活动i的开始时间si小于最近选择的活动j的结束时间fi,则不选择活动i,否则选择活动i加入集合A中。

贪心算法并不总能求得问题的整体最优解。但对于活动安排问题,贪心算法greedySelector 却总能求得的整体最优解,即它最终所确定的相容活动集合A的规模最大。这个结论可以用数学归纳法证明

【算法效率】
当输入的活动已按结束时间的非减序排列,算法GreedySelector只需O(n)的时间安排n个活动,使最多的活动能相容地使用公共资源。

如果所给出的活动未按结束时间非减序排列,可以用O(nlogn)的时间先排序,然后再使用算法GreedySelector安排活动。

4.3 最大装载问题

【问题描述】输入:总重量限制W,以及n个物品的重量A = {a0, a1,… ,an−1}输出:A的一个子集A*,其和不大于W,且元素数量尽可能大

每次尽可能地选取重量最小的物品

实例
W = 1000, A = {400, 350, 300, 250, 240, 180, 150, 120}
选取 120 + 150 + 180 + 240 + 250

最大装载问题贪心算法伪代码:

Algorithm MaxLoad(int W; int A[])
beginSort(A); // 将物品按重量排序  O(nlogn)let i = 0;while (W>0) doif (A[i] ≤ W) then  // O(n)W <- W - A[i];i <- i + 1;return A[0..i];
end

4.4 哈夫曼编码

解决数据压缩问题(如何采取有效的数据压缩技术来节省数据文件的存储空间和传输时间)

在数据通信、数据压缩问题中,需要将数据文件转换成由二进制字符0、1组成的二进制串,称之为编码

如何设计有效的用于数据压缩的二进制编码?(一般等长编码方案并不是最优的编码方案。)

因为每个字符出现的频率不同。如果在编码时考虑字符出现的频率,使频率高的字符采用尽可能短的编码,频率低的字符采用稍长的编码,则会获得更好的空间效率。

考虑到解码问题,若要设计长短不等的编码,任何一个字符的编码都不能是其它字符的编码的前缀。这种编码称之为前缀码

反例:非前缀码的例子
a: 001, b: 00, c: 010, d: 01
解码存在歧义,例如字符串 0100001
解码1: 01, 00, 001 可以解读为 d, b, a
解码2: 010, 00, 01 可以解读为 c, b, d

4.4.1 前缀码的二叉树表示

示例:前缀码:{00000, 00001, 0001, 001, 01,100,101,11}
在这里插入图片描述给定字符集C={x1,x2 ,…,xn } 和每个字符的频率f(xi) ,i=1,2,…,n。字符集C的一个前缀码编码方案对应于一颗二叉树T。字符xi在树T中的深度记为d(xi),d(xi)称为字符xi的前缀码长。

该编码方案的平均码长定义为
在这里插入图片描述
平均码长亦称作平均传输位数

【问题】 给定字符集C={x1,x2 ,…,xn } 和每个字符的频率f(xi) ,i=1,2,…,n. 。求关于C 的一个最优前缀码(平均码长最小)。

哈夫曼(Huffman)提出了构造最优前缀码的贪心算法,由此产生的编码方案称为哈夫曼编码。
哈夫曼算法以自底向上的方式构造表示最优前缀码的二叉树T。算法以|C|个叶结点开始,执行|C|-1次的“合并”运算后产生最终所要求的树T。

哈夫曼算法伪码:
在这里插入图片描述
示例:字符串C包含字符及出现次数为:a:45; b:13; c:12; d:16; e:9; f:5。
在这里插入图片描述
深度: a:1; b:3; c:3; d:3; e:4; f:4

在这里插入图片描述
0 - 左子树
1 - 右子树
码对应一片树叶

平均码长: 4×(0.05+0.09)+3×(0.16+0.12+0.13)+1×0.45=2.24

哈夫曼编码 正确性证明
【引理1】 设C是字符集,C中任一字符c的频率为f©。假设x,y∈C,且f(x), f(y) 是频率中最小的两个, 那么存在最优二元前缀码使得 x, y具有相同码长且仅在最后一位编码不同。

引理1的证明思路:设二叉树T表示字符集C的一个最优前缀码。如果对T做适当修改后得到一颗新的二叉树T’,使得在新树中,x和y 是最深叶子且为兄弟。同时,新树T’表示的前缀码也是C的最优前缀码。如此即可证明引理1。

【引理2】 设T是字符集C的一个最优前缀码的完全二叉树。C中任一字符c的频率为f©。假设x和y是C中树T的两个叶子且为兄弟, z是它们的父亲。若将z看作是具有频率f(z) =f(x)+ f(y) 的字符,则树T’=T-{x, y}表示的字符集C’=C- {x, y}∪{z}的一个最优前缀码。

4.5 单源最短路径

【问题描述】 给定带权有向图G =(V,E,W),其中每条边e=<i,j>的权w(e)是非负实数,表示从i到j的距离。另外,给定V中的一个顶点s,称为源。现在要计算从源s到所有其他各顶点的最短路径。这个问题通常称为单源最短路径问题。

在这里插入图片描述
源点:1
在这里插入图片描述
Dijkstra算法是求解单源最短路径问题的一个贪心算法。

【算法基本思想】:
设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。

  1. 初始时,S中仅含有源。
  2. 设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。
  3. Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u
    添加到S中,同时对数组dist作必要的修改。
  4. 一旦S包含了所有V中顶点,dist就记录了从源到所有其他顶点之间
    的最短路径长度。

输入:有向图G =(V,E,W),V={1,2,…,n}, s=1
输出:从源s到所有其他各顶点的最短路径

【 Dijkstra算法设计思想】

  1. 初始S={1}
  2. 对于i∈V−S , 计算1到i 的相对 S 的最短路,长度 dist [i]
  3. 选择 V−S 中的dist值最小的j,将j加入S,修改V−S中顶点的dist值
  4. 继续上述过程,直到 S=V

Dijkstra算法 伪码
在这里插入图片描述

输入:有向图G =(V,E,W),V={1,2,3,4,5,6}, s=1
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Dijkstra算法 正确性证明
证明对于i∈V, dist[i]=short[i]

归纳法证明Dijkstra算法
首先证明第1步时,Dijkstra算法成立。接下来,假设Dijkstra算法进行到第k 步时命题成立,归纳证明k+1时命题也成立。

(1) k=1时,S={s}, dist [s]=short[s]=0。
(2) 假设Dijkstra算法进行到第k 步时命题成立,k+1步时选择顶点v(边<u,v>)。需要证明dist [v]=short[v]。若存在另一条 s-v 路径 L ( 绿色) ,最后一次出 S 的顶点为x, 经过V−S 的第一个顶点 y,再由 y 经过一段在V−S中的路径到达 v
在k+1步时选择顶点v而不是y,则dist [v]≤ dist [y] 令y到v的路径长度为d(y,v) ,则dist [y]+d(y,v)≤L于是dist [v] ≤L,即dist [v]=short[v]。

【算法时间复杂度分析】
对于具有n个顶点和e条边的带权有向图,如果用带权邻接矩阵表示这个图,那么Dijkstra算法的主循环体需要O(n)时间。这个循环需要执行n-1次,所以完成循环需要O(n2)时间。算法的其余部分所需要时间不超过O(n2)。

4.6 最小生成树

【问题描述】
设G =(V,E)是无向连通带权图,即一个网络。E中每条边(v,w)的权为c[v][w]。如果G的子图G’是一棵包含G的所有顶点的树,则称G’为G的生成树。生成树上各边权的总和称为该生成树的耗费。在G的所有生成树中,耗费最小的生成树称为G的最小生成树。

Prim算法和Kruskal算法都是应用贪心策略获得最小生成树的例子。
尽管这2个算法做贪心选择的方式不同,但它们都利用了下面的最小生成树性质:

设G=(V,E)是连通带权图,U是V的真子集。如果(u,v)∈E,且u∈U,v∈V − U,且在所有这样的边中,(u,v)的权c[u][v]最小,那么一定存在G的一棵最小生成树,它以(u,v)为其中一条边。

最小生成树 Prim算法:

Prim算法的基本思想:
首先置S={1},
然后,只要S是V的真子集,就作如下的贪心选择:选取满足条件i∈S,j∈V-S,且c[i][j]最小的边,将顶点j添加到S中。
这个过程一直进行到S=V时为止。
在这个过程中选取到的所有边恰好构成G的一棵最小生成树。

Prim算法 伪代码:
在这里插入图片描述

实例:如图所示的带权图,按Prim算法选取边的过程如下所示。
在这里插入图片描述
在这里插入图片描述
在Prim算法中,还应当考虑如何有效地找出满足条件i∈S, j∈V−S,且权c[i][j]最小的边(i,j)

实现这个目的的较简单的办法是设置2个数组closest和lowcost。
对于每一个j∈V−S,closest[j]是j在S中的邻接顶点,它与j在S中的其它邻接顶点k相比较有c[j][closest[j]]≤c[j][k]。lowcost[j]的值就是c[j][closest[j]]。

在Prim算法执行过程中,先找出V − S中使lowcost值最小的顶点j,然后根据数组closest选取边(j,closest[j]),最后将j添加到S中,并对closest和lowcost作必要的修改。

用这个办法实现的Prim算法,算法步骤执行O(n)次,每次找连接S与V-S的最短边用时O(n),因此所需的计算时间为O(n2)。

最小生成树 Kruskal算法

Kruskal算法的基本思想:
首先将G的n个顶点看成n个孤立的连通分支。将所有的边按权从小到大排序

然后从第一条边开始,依边权递增的顺序查看每一条边,并按下述方法连接2个不同的连通分支:当查看到第k条边(v,w)时,

  1. 如果端点v和w分别是当前2个不同的连通分支T1和T2中的顶点时,就用边(v,w)将T1和T2连接成一个连通分支,然后继续查看第k+1条边;
  2. 如果端点v和w在当前的同一个连通分支中,就直接再查看第k+1条边。
  3. 这个过程一直进行到只剩下一个连通分时为止。

Kruskal算法伪代码:
在这里插入图片描述
例如对于如图所示的带权图,按Kruskal算法选取边的过程如下图所示。
在这里插入图片描述
在这里插入图片描述

4.7 多机调度问题

**【问题描述】**多机调度问题要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。

约定:每个作业均可在任何一台机器上加工处理,但未完工前不允
许中断处理。作业不能拆分成更小的子作业。

这个问题是NP完全问题,到目前为止还没有有效的解法。对于这一类问题,用贪心选择策略有时可以设计出较好的近似算法。

  1. 当n≤m 时,只要将机器i的[0, ti]时间区间分配给作业i即可,算法只需要O(1)时间
  2. 当n>m时,首先将n个作业依其所需的处理时间从大到小排序。然后依此顺序将作业分配给空闲的处理机。算法所需的计算时间为O(nlogn)

【示例】设7个独立作业{1,2,3,4,5,6,7}由3台机器M1,M2和M3加工处理。各作业所需的处理时间分别为{2,14,4,16,6,5,3}。按贪心算法产生的作业调度如下图所示,所需的加工时间为17。
在这里插入图片描述

五、总结

  1. 贪心法适用于组合优化问题。
  2. 求解过程是多步判断过程,最终的判断序列对应于问题的最优解。
  3. 判断依据某种“短视的”贪心选择性质,性质的好坏决定了算法的正确性。贪心性质的选择往往依赖于直觉或者经验。
  4. 贪心法的优势:算法简单,时间和空间复杂性低。

贪心法正确性证明方法:
(1) 直接计算优化函数,贪心法的解恰好取得最优值
(2) 数学归纳法(对算法步数或者问题规模归纳)

证明贪心策略不对:举反例

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

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

相关文章

MySQL事务与锁机制详解:确保数据一致性的关键【MySQL系列】

本文将系统讲解 MySQL 中事务的四大特性、隔离级别与实现原理&#xff0c;深入拆解锁机制的种类与应用场景&#xff0c;并结合典型死锁案例进行分析&#xff0c;为你构建起应对复杂一致性问题的坚实基础。 一、什么是事务&#xff1f; 事务&#xff08;Transaction&#xff09…

UE5 Mat HLSL - Load

特性Load()Sample()输入类型整数索引&#xff08;int2/int3&#xff09;浮点 UV 采样器状态&#xff08;SamplerState&#xff09;数据获取精确读取指定位置的原始数据基于 UV 插值和过滤后的数据典型用途精确计算、非过滤访问&#xff08;如物理模拟&#xff09;纹理贴图渲染…

基于vue框架的独居老人上门护理小程序的设计r322q(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,护理人员,服务预约,服务评价,服务类别,护理项目,请假记录 开题报告内容 基于Vue框架的独居老人上门护理小程序的设计开题报告 一、研究背景与意义 &#xff08;一&#xff09;研究背景 随着社会老龄化的加剧&#xff0c;独居老…

鸿蒙如何引入crypto-js

import CryptoJS from ohos/crypto-js 报错。 需要先安装ohom&#xff1a;打开DevEco&#xff0c;点击底部标签组&#xff08;有Run, Build, Log等&#xff09;中的Terminal&#xff0c;在Terminal下执行&#xff1a; ohpm install 提示 install completed in 0s 119ms&…

【C++】入门基础知识(1.5w字详解)

本篇博客给大家带来的是一些C基础知识&#xff01;包含函数栈帧的详解&#xff01; &#x1f41f;&#x1f41f;文章专栏&#xff1a;C &#x1f680;&#x1f680;若有问题评论区下讨论&#xff0c;我会及时回答 ❤❤欢迎大家点赞、收藏、分享&#xff01; 今日思想&#xff1…

二.MySQL库的操作

一.创建数据库create database 名称; 字符集和校验规则 一、字符集&#xff08;Character Set&#xff09; 表示数据库中可以使用哪些字符。 例如&#xff1a;utf8 可以存储包括中文在内的多种语言字符&#xff0c;gbk 更适合中文字符环境。 功能举例控制支持哪些语言字符utf…

【Linux 学习计划】-- 命令行参数 | 环境变量

目录 命令行参数 环境变量 环境变量的本质是什么&#xff1f; 相关配置文件 修改环境变量的相关操作 代码获取env —— environ 内建命令 结语 命令行参数 试想一下&#xff0c;我们的main函数&#xff0c;也是一个函数&#xff0c;那么我们的main函数有没有参数呢&am…

具有离散序列建模的统一多模态大语言模型【AnyGPT】

第1章 Instruction 在人工智能领域、多模态只语言模型的发展正迎来新的篇章。传统的大型语言模型(LLM)在理解和生成人类语言方面展现出了卓越的能力&#xff0c;但这些能力通常局限于 文本处理。然而&#xff0c;现实世界是一个本质上多模态的环境&#xff0c;生物体通过视觉、…

git查看commit属于那个tag

1. 快速确认commit原始分支及合入tag # git describe 213b4b3bbef2771f7a1b8166f6e6989442ca67c8 查看commit合入tag # git describe 213b4b3bbef2771f7a1b8166f6e6989442ca67c8 --all 查看commit原始分支 2.查看分支与master关系 # git show --all 0.5.67_0006 --stat 以缩…

day10机器学习的全流程

浙大疏锦行 1.读取数据 import pandas as pd import pandas as pd #用于数据处理和分析&#xff0c;可处理表格数据。 import numpy as np #用于数值计算&#xff0c;提供了高效的数组操作。 import matplotlib.pyplot as plt #用于绘制各种类型的图表# 设置中文字体…

基于对比学习的推荐系统开发方案,使用Python在PyCharm中实现

以下是一个基于对比学习的推荐系统开发方案,使用Python在PyCharm中实现。本文将详细阐述技术原理、系统设计和完整代码实现。 基于对比学习的推荐系统开发方案 一、技术背景与原理 1.1 对比学习核心思想 对比学习(Contrastive Learning)通过最大化正样本相似度、最小化负…

2025山东CCPC题解

文章目录 L - StellaD - Distributed SystemI - Square PuzzleE - Greatest Common DivisorG - Assembly Line L - Stella 题目来源&#xff1a;L - Stella 解题思路 签到题&#xff0c;因为给出的字母不是按顺序&#xff0c;可以存起来赋其值&#xff0c;然后在比较。 代码…

某航参数逆向及设备指纹分析

文章目录 1. 写在前面2. 接口分析3. 加密分析4. 算法还原5. 设备指纹风控分析与绕过 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享…

Python训练营---Day41

DAY 41 简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 …

【Netty系列】Reactor 模式 2

目录 流程图说明 关键流程 以下是 Reactor 模式流程图&#xff0c;结合 Netty 的主从多线程模型&#xff0c;帮助你直观理解事件驱动和线程分工&#xff1a; 流程图说明 Clients&#xff08;客户端&#xff09; 多个客户端&#xff08;Client 1~N&#xff09;向服务端发起连…

前端开发中 <> 符号解析问题全解:React、Vue 与 UniApp 场景分析与解决方案

前端开发中 <> 符号解析问题全解&#xff1a;React、Vue 与 UniApp 场景分析与解决方案 在前端开发中&#xff0c;<> 符号在 JSX/TSX 环境中常被错误解析为标签而非比较运算符或泛型&#xff0c;导致语法错误和逻辑异常。本文全面解析该问题在不同框架中的表现及解…

【Web应用】 Java + Vue 前后端开发中的Cookie、Token 和 Swagger介绍

文章目录 前言一、Cookie二、Token三、Swagger总结 前言 在现代的 web 开发中&#xff0c;前后端分离的架构越来越受到欢迎&#xff0c;Java 和 Vue 是这一架构中常用的技术栈。在这个过程中&#xff0c;Cookie、Token 和 Swagger 是三个非常重要的概念。本文将对这三个词进行…

投稿Cover Letter怎么写

Cover Letter控制在一页比较好&#xff0c;简短有力地推荐你的文章。 Dear Editors: Small objects detection in remote sensing field remains several challenges, including complex backgrounds, limited pixel representation, and dense object distribution, which c…

创建型设计模式之Prototype(原型)

创建型设计模式之Prototype&#xff08;原型&#xff09; 摘要&#xff1a; Prototype&#xff08;原型&#xff09;设计模式通过复制现有对象来创建新对象&#xff0c;避免重复初始化操作。该模式包含Prototype接口声明克隆方法、ConcretePrototype实现具体克隆逻辑&#xff…

spark在执行中如何选择shuffle策略

目录 1. SortShuffleManager与HashShuffleManager的选择2. Shuffle策略的自动选择机制3. 关键配置参数4. 版本差异(3.0+新特性)5. 异常处理与调优6. 高级Shuffle服务(CSS)1. SortShuffleManager与HashShuffleManager的选择 SortShuffleManager:默认使用,适用于大规模数据…