217. Contains Duplicate [easy] (Python)

这篇博客介绍了LeetCode上的第217题,题目要求判断一个整数数组中是否存在重复元素。文章提供了三种解题思路:排序后对比相邻元素、使用字典记录出现过的数以及将数组转换为集合并比较长度。每种方法都有相应的Python代码实现。

题目链接

https://leetcode.com/problems/contains-duplicate/

题目原文

Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

题目翻译

给定一个整数数组,判断其中是否包含重复元素。你要写的函数,当包含重复元素时返回 true,否则返回 false。

思路方法

首先我们可能会想到,遍历数组,对于每个元素,再检查后面所有元素是否有相同的就可以了。然而这样时间复杂度太高,会超时,所以不可取。

思路一

既然暴力查重不可取,那么我没先将数组进行排序(排序的复杂度),排序后比较每个元素与后一个元素是否相等即可。

代码

class Solution(object):
    
<think> 我们之前讨论了MySQL中REPLACE操作的效率,现在用户想了解INSERT ... ON DUPLICATE KEY UPDATE(以下简称IODKU)的效率和使用情况,特别是与REPLACE操作(REPLACE INTO)的对比。根据引用,我们可以从以下几个方面分析: 1. **效率对比**:引用[3]提到,使用UPDATE更新数据速度为2000/s,而使用IODKU更新速度达到40000/s,效率提升显著。而REPLACE INTO在冲突时是先删除再插入,IODKU则是直接更新,避免了删除操作的开销,因此在更新操作时IODKU效率更高。 2. **工作原理**:IODKU在遇到主键或唯一键冲突时,执行UPDATE操作(只更新指定字段),而不是删除整行再插入。这减少了索引变动、触发器触发(如删除相关的触发器)以及自增ID的浪费。 3. **使用场景**:适合需要根据唯一键判断记录是否存在,存在则更新部分字段,不存在则插入的场景。如用户引用[4]中的例子:记录用户对单词的录音,如果已有记录则更新录音路径和时间。 4. **使用方法**:基本语法如下: ```sql INSERT INTO table (col1, col2, ...) VALUES (val1, val2, ...) ON DUPLICATE KEY UPDATE col1 = val1, col2 = val2, ...; ``` 注意:UPDATE后面可以更新为新的值,也可以引用VALUES函数来使用插入时的值,例如: ```sql INSERT INTO test (a, b) VALUES (1, 2) ON DUPLICATE KEY UPDATE b = VALUES(b); ``` 5. **与REPLACE INTO的对比**: - **操作差异**:REPLACE INTO是删除后插入,整行替换;IODKU是直接更新部分列。 - **效率**:IODKU在更新时效率更高(避免删除和重新插入,减少索引维护)。 - **自增ID**:REPLACE INTO会改变自增ID(旧行删除,新行插入,自增ID增加),而IODKU不会(因为只是更新,原ID保留)。 - **触发器**:REPLACE INTO会触发DELETE和INSERT触发器,而IODKU只触发UPDATE触发器(如果存在)和INSERT触发器(当插入时)或UPDATE(当更新时)。 6. **注意事项**: - 必须存在主键或唯一索引才能触发更新。 - 在高并发下,IODKU比REPLACE INTO性能更好,因为减少了锁的持有时间(引用[3]的实践数据)。 - 使用IODKU会绑定MySQL(引用[1]),因为这是MySQL的扩展语法。 7. **优化建议**: - 只更新需要变更的字段,避免不必要的更新。 - 如果不需要更新所有字段,在UPDATE子句中只列出需要更新的字段。 结合用户之前的问题(REPLACE效率),我们可以这样总结: - 在需要更新部分字段且存在冲突的情况下,优先使用IODKU,因为它效率更高(引用[3]的数据)。 - 在需要整行替换时(即冲突时希望用新数据完全覆盖旧数据),可以使用REPLACE INTO,但要注意其效率较低以及自增ID变化的问题。 接下来,我们将详细说明IODKU的使用方法和效率分析。 </think>### MySQL中`INSERT ... ON DUPLICATE KEY UPDATE`效率与使用分析 结合您关注的效率对比(特别是与`REPLACE INTO`的对比)以及引用内容,以下从效率机制、使用方法和场景建议展开: --- ### 一、核心效率机制 #### 1. **与`REPLACE INTO`的效率对比** | **操作** | **底层行为** | **效率优势** | **效率劣势** | |-------------------------------|-----------------------------|---------------------------------------------------|-------------------------------------| | **REPLACE INTO** | 冲突时:先删除旧行 → 插入新行 | 逻辑简单,适合整行替换 | 1. 自增ID不连续<br>2. 触发`DELETE`触发器<br>3. 索引重建成本高 | | **ON DUPLICATE KEY UPDATE** | 冲突时:直接更新指定字段 | 1. **避免删除操作**<br>2. **仅更新差异字段**<br>3. **保留原自增ID** | 需显式指定更新字段 | **实测数据**(引用[3]): - `UPDATE`:约 2000次/秒 - `ON DUPLICATE KEY UPDATE`:约 **40000次/秒**(效率提升20倍)[^3] > 原因:避免行删除和重建,减少I/O和索引维护。 #### 2. **高效原理** - **最小化写操作**:仅修改冲突字段(如引用[4]中只更新`path`和`time`)[^4] - **原子性保证**:单语句完成"存在则更新,不存在则插入",减少事务开销[^2] - **锁优化**:InnoDB引擎下行级锁,并发性能更高(对比`REPLACE INTO`的表级锁风险) --- ### 二、使用方法与示例 #### 1. **基础语法** ```sql INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...) ON DUPLICATE KEY UPDATE 列1 = 新值1, 列2 = 新值2; ``` #### 2. **实战案例** **场景**:记录用户单词录音,存在相同记录时更新路径和时间(引用[4])[^4] ```sql INSERT INTO kid_big_cat_course_word_recording (user_id, word_id, path, time) VALUES (#{userId}, #{pk}, #{path}, NOW()) ON DUPLICATE KEY UPDATE path = VALUES(path), -- 使用VALUES()引用插入值 time = NOW(); ``` > **关键技巧**: > - 使用`VALUES(列名)`获取插入值,避免重复传参 > - 只更新必要字段(`path`和`time`) #### 3. **自动识别冲突** - **触发条件**:主键(Primary Key)或唯一索引(Unique Index)冲突 - **错误写法**: ```sql ON DUPLICATE KEY UPDATE path = 'new_path'; -- 直接赋固定值(错误!) ``` - **正确写法**: ```sql ON DUPLICATE KEY UPDATE path = VALUES(path); -- 动态引用插入值[^4] ``` --- ### 三、适用场景与限制 #### ✅ **推荐场景** 1. **高并发写入**(如计数器、实时日志) ```sql INSERT INTO page_views (page_id, views) VALUES (123, 1) ON DUPLICATE KEY UPDATE views = views + 1; -- 原子性递增 ``` 2. **数据同步**(避免`SELECT`检查存在性)[^2] 3. **部分字段更新**(如用户配置表,仅更新最后修改时间)[^4] #### ⚠️ **使用限制** 1. **数据库绑定**:MySQL特有语法,迁移到其他数据库需重写(引用[1])[^1] 2. **更新字段**:必须显式列出需更新的列(`REPLACE INTO`默认更新所有列) 3. **触发器行为**: - 冲突时触发`BEFORE UPDATE`和`AFTER UPDATE` - **不触发**`DELETE`相关触发器(与`REPLACE INTO`关键区别) --- ### 四、性能优化建议 1. **精简更新字段** ```sql -- 只更新必要字段 ON DUPLICATE KEY UPDATE status = VALUES(status), update_time = NOW(); -- 而非更新所有列 ``` 2. **避免全表更新** 结合`WHERE`条件限制范围(但需注意:WHERE在IODKU中无效,需前置过滤数据) 3. **索引优化** - 确保冲突检测列(主键/唯一索引)覆盖高频查询 - 避免对更新列建立过多索引(减少写放大) 4. **批量操作加速** ```sql INSERT INTO table (id, data) VALUES (1, 'a'), (2, 'b'), (3, 'c') ON DUPLICATE KEY UPDATE data = VALUES(data); ``` --- ### 五、总结:何时选择`ON DUPLICATE KEY UPDATE` | **需求** | 推荐方案 | |-------------------------|----------------------------| | 冲突时需**更新部分字段** | ✅ `ON DUPLICATE KEY UPDATE` | | 冲突时需**完全替换整行** | ⚠️ `REPLACE INTO`(注意副作用) | | 需要**保留原自增ID** | ✅ `ON DUPLICATE KEY UPDATE` | | 高并发增量更新(如计数器) | ✅ `ON DUPLICATE KEY UPDATE` | > **结论**:在更新为主的场景中,`ON DUPLICATE KEY UPDATE`因避免删除操作和精准字段更新,效率显著高于`REPLACE INTO`(引用[3]实测数据验证)[^3]。唯需注意其MySQL依赖性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值