深入流行推荐引擎3:Spotify音乐推荐系统

深入流行推荐引擎3:Spotify音乐推荐系统

  • Spotify音乐推荐系统
    • 通过矩阵分解发现每周(Discover Weekly via Matrix Factorization)
      • Discover Weekly 如何运作?(How Discover Weekly Works?)
      • 矩阵分解(Matrix Factorization)
      • 交替最小二乘法(Alternating Least Squares)
    • 用于音乐发现的 RNN(RNNs for Music Discovery)
    • 使用强化学习的播放列表推荐(Playlist Recommendation Using Reinforcement Learning)
      • 概述(Overview)
      • 世界模型设计(World Model Design)
      • 行动负责人 DQN 方法(Action Head DAN Approach)
  • 总结
  • 参考

互联网彻底改变了人们发现、消费和与音乐互动的方式。摆脱了 DVD、磁带和录音带的麻烦,现在可以通过流媒体平台(例如 Spotify、Amazon Music、Apple Music 等)随时随地收听音乐。

Spotify 在全球拥有超过 2 亿用户,已成为音频流媒体服务的行业领导者。它们已经从音乐扩展到播客和有声读物,吸引了具有不同偏好和兴趣的用户。

Spotify 最先进的音乐推荐引擎,可根据用户的兴趣、偏好和当前心情向用户推荐音乐或播客。 推荐系统在提供良好的用户体验方面发挥了重要作用,这为 Spotify 带来了如此大的成功。

这篇博客将涵盖 Spotify 推荐的几个方面(例如,音乐推荐、播放列表推荐)以及它们在幕后的工作原理。
推荐引擎3 部分系列的最后一节课深入探讨流行音乐推荐引擎 :

  1. 推荐系统基础
  2. 亚马逊产品推荐系统
  3. YouTube 视频推荐系统
  4. Spotify 音乐推荐系统(本文)

Spotify音乐推荐系统

尽管音乐推荐的任务可能感觉类似于电影推荐(正如在 Netflix 推荐系统中学到的那样),但两者的工作方式存在一些差异:

  • 与电影相比,歌曲目录相当大。同一首歌可以有多种变体(例如低保真、混音、慢速、混响、不同的歌手、乐队等)。但是,电影不太可能有变化。
  • 歌曲具有重复的消费模式,因为您可能会更频繁地听自己喜欢的歌曲。然而电影并非如此。
  • 与电影相比,音乐更小众。有些人可能喜欢民谣、1990 年代的歌曲、流行或摇滚,或者某个乐队或歌手。
  • 电影的收视率更为明确。但是对于歌曲反馈隐藏在用户的流模式中。

Spotify 拥有数百万首歌曲、用户口味、流媒体音乐和用户生成的播放列表的数据。现在将研究Spotify 如何使用这些数据源和先进的机器学习技术来解决音乐推荐问题。

通过矩阵分解发现每周(Discover Weekly via Matrix Factorization)

Discover Weekly 如何运作?(How Discover Weekly Works?)

Spotify 的 Discover Weekly是一个算法生成的播放列表,每周一发布,为听众提供定制的、精心策划的音乐推荐。在幕后Discover Weekly使用协作过滤来利用用户收听历史和具有相似历史的用户喜欢的歌曲。回想一下,协作筛选会根据具有相似兴趣的其他用户喜欢的项目向用户推荐项目。

Spotify 还通过将用户经常听的音乐分组来建立品味档案。这些集群不是基于明确的属性(例如,流派、艺术家等),而是基于歌曲的作曲相似性。

除了明确的反馈,如库保存和“从广播中点赞”,Spotify还依靠隐式反馈(例如歌曲重复、跳过歌曲、歌曲点击等)来训练他们的算法。它使用基于矩阵分解的方法,将用户项目评分矩阵分解为两个部分。第一部分根据潜在因素来描述用户,每个因素的权重不同。第二部分描述歌曲,艺术家与用户部分处于同一潜在空间。

矩阵分解(Matrix Factorization)

为了清楚地理解,假设有:

  • 一组 N N N 用户 U = ( u 1 , u 2 , … , u N ) U = (u_1, u_2,\dots,u_N) U=(u1,u2,,uN)
  • 一组 M M M 歌曲项目, I = ( i 1 , i 2 , … , i M ) I = (i_1,i_2,\dots, i_M) I=(i1,i2,,iM)
  • 用户项目观察矩阵 R = ( r u i ) n × m ) R = (r_{ui})_{n \times m}) R=(rui)n×m) 哪里 r u i ≥ 0 r_{ui} \geq 0 rui0 表示用户次数 u u u 与项目交互 i i i

用户-项目观察矩阵的设计取决于问题的性质。与隐性反馈相比可以选择更多地权衡显性反馈。此外,人们可能会选择将较新的用户流的权重高于较旧的流,因为用户的口味可能会随着时间的推移而略有变化。

请注意,矩阵 R型 通常是稀疏的,因为大多数用户只与目录中有限数量的项目进行交互。对于用户-项目组合,其中用户 u u u 尚未与项目交互 i i i r u i r_{ui} rui 设置为零。矩阵分解旨在近似于这些 r u i r_{ui} rui 未知用户-项目组合的值。

该方法分解观察矩阵 R R R 为两个矩阵:
用户矩阵: X N × f = [ x 1 , x 2 , … , x N ] X_{N \times f} = [x_1, x_2,\dots,x_N] XN×f=[x1,x2,,xN],通过未定义的潜在因素描述N个用户中的每一个
项目矩阵: Y M × f = [ y 1 , y 2 , … , y M ] Y_{M \times f} = [y_1, y_2,\dots,y_M] YM×f=[y1,y2,,yM],通过同样未定义的潜在因素描述M歌曲。
换句话说,
R ≈ X Y T R \approx XY^T RXYT
r u i = < x u , y i > r_{ui}=<x_u,y_i> rui=<xu,yi>
其中 < . , . > <.,.> <.,.>表示向量内积运算。

为了学习 X X X Y Y Y 的矩阵,Spotify最小化了未定义的观测值和未定义预测值之间的以下RMSE(均方根误差 Root Mean Square Error)损失
未定义的
m i n x , y ∑ u , i ( r u i − x u T y i − b u − b i ) 2 − λ ( ∑ u ∣ ∣ x u ∣ ∣ 2 + ∑ i ∣ ∣ y i ∣ ∣ 2 ) min_{x,y}\textstyle\sum_{u,i} (r_{ui}-x_u^Ty_i-b_u-b_i)^2-\lambda(\textstyle\sum_{u} ||x_u||^2+\textstyle\sum_{i} ||y_i||^2) minx,yu,i(ruixuTyibubi)2λ(u∣∣xu2+i∣∣yi2)

其中 λ \lambda λ 是控制正则化的超参数: b i b_i bi b u b_u bu 都是项 i i i 和 用户 u u u 的偏差。

交替最小二乘法(Alternating Least Squares)

X X X Y Y Y 的矩阵使用如下交替最小二乘算法进行优化:

  1. 随机初始化 X X X Y Y Y
  2. 修复未定义的项目向量 y i y_i yi ,并为未定义的用户向量 x u x_u xu 求解。取上述损失函数相对于未定义的用户向量 x u x_u xu 的导数,并将其设置为零,这给出
    x u = ( Y T C u Y + λ I ) − 1 Y T R ( u ) x_u=(Y^TC^uY+\lambda I)^{-1}Y^TR(u) xu=(YTCuY+λI)1YTR(u)
    其中 C u C_u Cu 是常数乘法器,undefine是观测矩阵R的未定义行型。
  3. 固定用户向量并求解项目向量(使用与步骤2相同的过程)。取上述损失函数相对于未定义的项向量的导数,并将其设置为零,这给出
    y i = ( X T C i X + λ I ) − 1 X T R ( i ) y_i=(X^TC^iX+\lambda I)^{-1}X^TR(i) yi=(XTCiX+λI)1XTR(i)
    其中 C i C^i Ci 是常数乘法器,$ R ( i ) R(i) R(i) 是观测矩阵R的第i个 i t h i^{th} ith 义列型。
  4. 重复直到收敛。

用于音乐发现的 RNN(RNNs for Music Discovery)

在音乐消费中,用户行为不断变化,可以用不同艺术家和流派的时间轨迹来描述。例如,想象一个用户听了一段时间艺术家的专辑,然后过渡到下一张专辑或同一音乐流派的汇编播放列表。Spotify使用递归神经网络(RNN)来利用用户的收听模式,将用户表示为其物品消费的函数。

RNN是最先进的神经网络,它处理可变长度的时间序列数据来学习丰富的项目表示。像任何神经网络一样,它们可以通过基于梯度的优化来学习。它们已被广泛用于对文本、语音和音频的非线性时间动态进行建模,因此是Spotify音乐发现问题的一个很好的候选者。

通常在 RNN 中,在每个时间步长 t t t、输入 x t x_t xt 用于更新隐藏的表示 h t − 1 h_{t-1} ht1 h t h_t ht 通过非线性映射。 同样,在每个时间步长,RNN 都会产生一个输出 y t y_t yt 作为输入的非线性函数 x t x_t xt 和以前的隐藏状态 h t − 1 h_{t-1} ht1

如何训练 RNN 来预测用户将来可能听的歌曲。主要有3个步骤:

  1. 管道的构建块是歌曲矢量表示,这些表示已经从目录中学习。为了学习这些矢量表示,Spotify 在目录中排名前 N 位的最流行歌曲中使用了 Google 的 Word2vec 套件。

    更具体地说,他们使用具有负采样的连续词袋 (CBoW) 算法。作为 Word2vec 算法的输入,它们采用用户创建的歌曲播放列表。在这种情况下,每个播放列表都被视为歌曲的有序“文档”。 通过以窗口方式扫描所有播放列表,Word2vec 将为每首歌曲学习具有固定维度的分布式矢量表示。

  2. RNN 输出一个味觉向量,它是从用户收听历史中学习的歌曲向量的函数,因此可以被视为用户音乐品味的表示。味觉向量应捕捉聆听行为如何随时间变化。因此RNN 预测用户将来可能会听的歌曲。为了对此进行建模,RNN 首先采用 N N N 特定用户的连续歌曲 u u u 已经听过并尝试预测下一首歌的向量。换言之,

s ^ n + 1 = RNN ( s 1 , s 2 , s 3 , … , s n ) \hat{s}_{n+1} = \text{RNN}(s_1, s_2,s_3,\dots,s_n) s^n+1=RNN(s1,s2,s3,,sn)

其中 s i s_i si 是用户在 i th i^\text{th} ith timestamp 和 s ^ n + 1 \hat{s}_{n+1} s^n+1 是未来时间戳的预测味觉向量 n + 1 n+1 n+1

作为损失函数,它们最小化了预测味觉向量之间的 L2 距离 s ^ n + 1 \hat{s}_{n+1} s^n+1 和未来的歌曲矢量 s n + 1 s_{n+1} sn+1

  1. 这些口味矢量现在可以生成歌曲推荐。由于已经训练了 RNN 来预测与用户未来可能播放的歌曲(以 L2 距离为单位)接近的味觉向量,因此可以在该向量空间中查询附近的歌曲以生成新的歌曲推荐。

为了促进高效采样,Spotify 利用了 Annoy 树,这是一种数据结构,它使用局部敏感的哈希随机投影技术将向量空间迭代划分为多个区域,从而实现近似最近邻查询。

使用强化学习的播放列表推荐(Playlist Recommendation Using Reinforcement Learning)

概述(Overview)

协作过滤方法的一个缺点是,它们依赖于显式或隐式反馈信号来判断用户是否喜欢播放列表。 因此他们往往难以考虑其他重要因素(例如,声学连贯性、聆听会话的背景以及最佳项目序列的存在)。这可能会导致离线指标与用户满意度指标(想要优化的指标)不匹配。

例如,协作过滤可以建议评分较高但包含成人和儿童音乐的混合播放列表,这不会带来良好的用户满意度。因此,播放列表生成是一项艰巨的任务。

强化学习 (RL) 是一个高级机器学习领域,它不需要明确的反馈信号,而是可以通过直接与用户交互来学习。因此,RL代理可以交互并学习重要的播放列表生成方面,以提高用户满意度指标。

RL 问题包括一个由状态、动作空间和奖励以及 RL 代理组成的环境。RL 代理查看环境的当前状态,并根据学习的策略建议操作。然后,环境会根据操作将其当前状态更改为另一种状态。除了更改其状态外,环境还会返回与此操作关联的奖励。然后,RL 代理会消耗此奖励,以优化其策略以获得更高的奖励。

现在,为了将RL应用于播放列表生成,问题陈述应该表述为马尔可夫决策过程,其中:

  • 状态对总结用户侦听会话的上下文信息进行编码
  • 操作空间表示所有可能的播放列表的空间
  • 奖励是期望的用户满意度指标

操作空间 A \mathcal{A} A 是所有可能的播放列表的空间,这在组合上是复杂的。例如,从 1000 个候选曲目池中生成包含 30 首曲目的播放列表会生成一个操作空间,其中大约 1 0 89 10^{89} 1089 可能性,使现成的RL算法不适用。为了解决这个问题,建议一次只播放一首曲目(来自候选池),而不是完整的播放列表。

世界模型设计(World Model Design)

为了准确地学习生成播放列表,RL 代理应该从模拟实际用户收听会话的环境中学习。为此Spotify提出了一种世界模型设计,该设计利用历史数据(例如,曲目特征和收听历史)来模拟过渡函数,该转换函数根据特定动作产生新状态及其奖励。

在模拟实际的用户收听会话时,世界模型还应该能够启动用户会话,跟踪所有收听的曲目,并终止会话。为了预测与操作相关的奖励,世界模型应用了一个经过训练的用户模型,该模型可以准确预测用户对项目(在例子中为音轨)的反应。 这种模型是在通过实验从真实用户那里收集的监督数据上训练的。

训练数据是通过随机随机播放来自各种收听会话的歌曲并收集用户完成的曲目(如果流式传输)的百分比及其在收听会话中的位置来生成的。然后将这些数据与以下数据相结合:

  • 上下文特征: 用户信息(例如,与个人兴趣和过去互动相关的特征)
  • 项目功能: 与用户正在与之交互的内容相关的信息

用户模型采用用户的上下文特征 在 和项目特征 i t i_t it 的轨道 t th t^\text{th} tth 在侦听会话中的位置以预测以下三个用户响应:

  • 完成候选人跟踪
  • 跳过候选人轨道
  • 收听曲目超过特定秒数(先验指定)

从数学上讲,用户模型采用以下形式:

p ( y t ∣ u , i t ) = f ( u , i t ) p(y_t | u,i_t)= f(u, i_t) p(ytu,it)=f(u,it)

f f f 是一种深度神经网络,它采用上下文和项目特征来预测用户响应。然后,每个用户响应都映射到一个奖励,供 RL 代理在训练期间使用。

行动负责人 DQN 方法(Action Head DAN Approach)

候选曲目池会随着时间的推移而不断变化,因为它们取决于用户的收听历史和品味。这使得整个操作空间是动态的。

为了解决这个问题,Spotify 提出了一个 Action Head Deep-Q-Network (AH-DQN) 代理来采取行动 a a a(例如,要推荐的曲目)和当前状态 s s s (即用户监听会话)作为推荐质量的输入和输出 Q ( s , a ) Q(s,a) Q(s,a)

AH-DQN 代理使用深度神经网络来输出推荐质量 Q ( s , a ) Q(s,a) Q(s,a)。根据每个磁道的 Q Q Q 值,智能体选择具有最高值的磁道。环境返回的奖励用于指示操作的好坏,并更新 Q-相应地网络。

总结

Spotify 是领先的音频流媒体平台,提供个性化的音乐和播客推荐。在这篇博客中了解了 Spotify 如何使用各种数据源和机器学习技术来创建不同的推荐(例如,每周发现、播放列表推荐和音乐发现(Discover Weekly, playlist recommendation, and music discovery)。

  • 通过矩阵分解发现每周(Discover Weekly via Matrix Factorization) :Spotify 如何使用矩阵分解创建符合用户口味的每周歌曲播放列表,该矩阵将用户与歌曲交互的大型矩阵分解为较小的用户和歌曲特征矩阵。
  • 用于音乐发现的 RNN(RNNs for Music Discovery) : Spotify 如何使用递归神经网络 (RNN) 来模拟音乐聆听的顺序性质,并生成与用户先前选择相似的新歌曲。
  • 使用强化学习的播放列表推荐(Playlist Recommendation Using Reinforcement Learning : Spotify 如何使用强化学习 (Reinforcement Learing RL) 创建平衡探索和利用的播放列表(即查找用户可能喜欢的新歌曲并播放用户已经喜欢的歌曲)。介绍了世界模型(学习模拟用户行为和偏好的神经网络(simulate the user’s behavior and preferences))和动作头(学习为播放列表选择最佳歌曲的深度 Q 网络 (DQN deep Q-network))的概念。

然而,这只是冰山一角,因为还有更多 Spotify 推荐系统。通过探索各种推荐引擎(例如 Netflix、LinkedIn、Amazon 和 YouTube 推荐系统)的课程深入了解推荐系统。深入了解所使用的技术(例如,文本挖掘、K 最近邻、聚类、矩阵分解和神经网络(text mining, K-nearest neighbor, clustering, matrix factorization, and neural networks)。

参考

  • https://pyimagesearch.com/2023/10/30/spotify-music-recommendation-systems/

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

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

相关文章

语义检索系统【全】:基于milvus语义检索系统指令全流程-快速部署版

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

记一次线上bug排查-----SpringCloud Gateway组件 请求头accept-encoding导致响应结果乱码

基于公司的业务需求&#xff0c;在SpringCloud Gateway组件的基础上&#xff0c;写了一个转发服务&#xff0c;测试开发阶段运行正常&#xff0c;并实现初步使用。但三个月后&#xff0c;PostMan请求接口&#xff0c;返回异常&#xff0c;经排查&#xff0c;从日志中获取到转发…

开启数据库审计 db,extended级别或os级别)并将审计文件存放到/opt/oracle/audit/下

文章目录 1、登录到数据库2、查看审计状态3、创建审计目录4、启用审计5、设置审计文件路径6、再次查看结果 1、登录到数据库 使用SQL*Plus或者其他Oracle数据库客户端登录到数据库。 sqlplus / as sysdba;2、查看审计状态 show parameter audit;目前是DB状态&#xff0c;并且…

【算法萌新闯力扣】:旋转字符串

力扣热题&#xff1a;796.旋转字符串 开篇 今天下午刷了6道力扣算法题&#xff0c;选了一道有多种解法的题目与大家分享。 题目链接:796.旋转字符串 题目描述 代码思路 完全按照题目的要求&#xff0c;利用StringBuffer中的方法对字符串进行旋转&#xff0c;寻找相同的一项 …

第 372 场 LeetCode 周赛题解

A 使三个字符串相等 求三个串的最长公共前缀 class Solution { public:int findMinimumOperations(string s1, string s2, string s3) {int n1 s1.size(), n2 s2.size(), n3 s3.size();int i 0;for (; i < min({n1, n2, n3}); i)if (!(s1[i] s2[i] && s2[i] s…

[工业自动化-23]:西门子S7-15xxx编程 - 软件编程 - 西门子PLC人机界面交互HMI功能概述、硬件环境准备、软件环境准备

目录 一、什么是人机界面 二、什么是PLC人机交互界面HMI 三、人机界面设计的功能列表 四、开发主机与PLC的连接方式 五、开发主机与HMI的连接方式 六、HMI组态 一、什么是人机界面 人机界面是指人与机器或系统之间的交互界面。它是人类与计算机或其他设备之间进行信息交换…

NSSCTF第13页(2)

[HNCTF 2022 Week1]Challenge__rce 提示?hint 访问看到了源码 <?php error_reporting(0); if (isset($_GET[hint])) { highlight_file(__FILE__); } if (isset($_POST[rce])) { $rce $_POST[rce]; if (strlen($rce) < 120) { if (is_string($rce…

Java Web——JavaScript基础

1. 引入方式 JavaScript程序不能独立运行&#xff0c;它需要被嵌入HTML中&#xff0c;然后浏览器才能执行 JavaScript 代码。 通过 script 标签将 JavaScript 代码引入到 HTML 中&#xff0c;有3种方式&#xff1a; 1.1. 内嵌式(嵌入式) 直接写在html文件里&#xff0c;用s…

系列六、GC垃圾回收【四大垃圾算法-标记清除算法】

一、概述 标记清除算法分为两个阶段&#xff0c;即&#xff1a;标记和清除两个阶段&#xff0c;先标记出要回收的对象&#xff0c;然后统一回收这些对象。形如&#xff1a; 老年代一般是由标记清除或者标记清除 标记压缩的混合实现。 二、原理 用通俗的话解释一下标记清除算法…

2023年中职“网络安全“—Web 渗透测试②

2023年中职“网络安全“—Web 渗透测试② Web 渗透测试任务环境说明&#xff1a;1.访问http://靶机IP/web1/,获取flag值&#xff0c;Flag格式为flag{xxx}&#xff1b;2.访问http://靶机IP/web2/,获取flag值&#xff0c;Flag格式为flag{xxx}&#xff1b;3.访问http://靶机IP/web…

SOME/IP 协议介绍(六)接口设计的兼容性规则

接口设计的兼容性规则&#xff08;信息性&#xff09; 对于所有序列化格式而言&#xff0c;向较新的服务接口的迁移有一定的限制。使用一组兼容性规则&#xff0c;SOME / IP允许服务接口的演进。可以以非破坏性的方式进行以下添加和增强&#xff1a; • 向服务中添加新方法 …

莹莹API管理系统源码附带两套模板

这是一个API后台管理系统的源码&#xff0c;可以自定义添加接口&#xff0c;并自带两个模板。 环境要求 PHP版本要求高于5.6且低于8.0&#xff0c;已测试通过的版本为7.4。 需要安装PHPSG11加密扩展。 已测试&#xff1a;宝塔/主机亲测成功搭建&#xff01; 安装说明 &am…

新生儿奶藓:原因、科普和注意事项

引言&#xff1a; 新生儿奶藓是一种常见的婴儿皮肤问题&#xff0c;通常在生后的头几个月内出现。尽管奶藓对婴儿的健康没有太大影响&#xff0c;但了解其原因、科普相关信息以及采取适当的注意事项是帮助父母更好地照顾婴儿皮肤的关键。本文将深入探讨新生儿奶藓的原因、相关…

PPT基础入门

目录 相关设置快捷键shift 快捷键Ctrl 快捷键Ctrl Shift 组合快捷键快捷键总结 相关设置 设置撤回次数 自动保存 图片压缩 字体嵌入&#xff1a;目的是在不同的电脑上保留已经设置好的字体 多格式导出 &#xff08;1&#xff09;可以导出PDF &#xff08;2&#xff09;可以导…

DevExpress中文教程 - 如何在macOS和Linux (CTP)上创建、修改报表(上)

DevExpress Reporting是.NET Framework下功能完善的报表平台&#xff0c;它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集&#xff0c;包括数据透视表、图表&#xff0c;因此您可以构建无与伦比、信息清晰的报表。 DevExpress Reports — 跨平台报表组件&#x…

7.docker运行redis容器

1.准备redis的配置文件 从上一篇运行MySQL容器我们知道&#xff0c;需要给容器挂载数据卷&#xff0c;来持久化数据和配置&#xff0c;相应的redis也不例外。这里我们以redis6.0.8为例来实际说明下。 1.1 查找redis的配置文件redis.conf 下面这个网址有各种版本的配置文件供…

C++ 十进制与十六进制转换

文章作者&#xff1a;里海 来源网站&#xff1a;里海C\C专栏 十进制与十六进制转换 #include <iostream> #include <string> using namespace std;//十进制整数转十六进制字符串 string DecimalToHex(long long decimal) {string hex "";while (de…

svg图标最简单的使用方式

svg图标最简单的使用方式 使用svg图标1. 复制图标的svg代码2. 新建个存放svg图标的目录&#xff0c;新建.vue文件3. 在<template>标签内粘贴svg的代码4. 在代码中也可以调整颜色和大小5. 在组件中引用6. svg做的图标要独占一行,使用布局将它安排到合适的地方 使用svg图标…

Leetcode经典题目之“双指针交换元素“类题目

1 LC 27. 移除元素 class Solution {public int removeElement(int[] nums, int val) {int nnums.length;int s0;for(int i0;i<n;i){// 只有不等于目标值的时候才会进行交换&#xff0c;然后移动s指针if(nums[i]!val){swap(nums,i,s);}}return s;}void swap(int[]nums, int…

Uniapp连接iBeacon设备——实现无线定位与互动体验(理论篇)

目录 前言&#xff1a; 一、什么是iBeacon技术 二、Uniapp连接iBeacon设备的准备工作 硬件设备&#xff1a; 三、Uniapp连接iBeacon设备的实现步骤 创建Uniapp项目&#xff1a; 四、Uniapp连接iBeacon设备的应用场景 室内导航&#xff1a; 五、Uniapp连接iBeacon设备的未来…