面试之被问数组去重---简单重要方法之一

一、双重for循环嵌套,利用splice去重

此方法是比较常用的方法之一

在这里插入图片描述

二、建立新数组,利用index Of去重

建立一个新数组,原数组遍历传入新数组,并判断是否存在,值不存在就加入新数组中

在这里插入图片描述

三、ES6中利用set去重

在这里插入图片描述

<think>好的,用户的是在面试中如果被数组该怎么回答。我需要先回想常见的数组方法,然后整理出一个清晰的回答结构。首先得考虑不同方法的实现方式、时间复杂度和适用场景。 首先想到最简单的是用Set,ES6的Set数据结构可以自动,然后转回数组。这方法简单但可能不适用于对象等引用类型,因为对象即使内容相同,引用不同也会被当作不同元素。 然后是使用filter和indexOf的组合。遍历数组,检查当前元素第一次出现的索引是否等于当前索引,这样可以过滤掉复项。但这种方法时间复杂度是O(n²),对于大数组效率不高。另外,NaN的情况可能会有题,因为indexOf无法正确识别NaN。 接下来是使用reduce,逐个累积不复的元素。同样面临和filter类似的题,但代码更函数式。 还有一种是用对象或Map来记录已出现的元素,利用O(1)的查询时间,这样时间复杂度可以降到O(n)。但需要注意对象的键会被转为字符串,比如数字1和字符串'1'会被视为相同,这时候可能需要使用typeof来区分类型。或者用ES6的Map,可以保存键的类型。 另外,针对排序后的数组,可以在遍历时比较前一个元素,跳过复的。这种方法时间复杂度主要是排序的O(n log n),之后线性遍历,所以整体是O(n log n)。不过会改变原数组的顺序,如果要求保持原顺序就不适用了。 还要考虑特殊值的情况,比如NaN、null、undefined、对象等。例如,Set会认为NaN等于自身,所以用Set可以正确包含NaN的数组,而indexOf不行。 在面试回答时,应该分点说明不同方法,并比较它们的优缺点,以及适用场景。最好还能提到时间复杂度和空间复杂度,展示对性能的理解。此外,询面试官是否有特定要求,比如是否允许修改原数组,是否需要处理特定类型的数据,这样可以体现沟通能力。 可能还需要手写代码示例,比如用Set的最简方法,或者用对象的哈希表方法,这时候要注意代码的准确性和边界情况处理,比如处理对象元素时的题。 最后,总结不同方法的适用情况,建议根据实际需求选择合适的方法,并说明自己会考虑数据规模、类型以及环境支持(比如是否需要兼容ES5)等因素来决定使用哪种方法。</think>在面试中回答“数组题时,可以按以下结构组织答案,体现技术深度和逻辑性: --- ### **1. 明确题** 先确认需求,避免假设: - “请需要处理的是基本数据类型(如数字、字符串)还是包含对象的复杂类型?” - “是否需要保持原数组顺序?” --- ### **2. 分场景给出解决方案** #### **场景1:仅基本数据类型(ES6环境)** **方法1:利用 `Set` 数据结构** ```javascript const uniqueArray = (arr) => [...new Set(arr)]; ``` - **优点**:代码简洁,时间复杂度 `O(n)` - **缺点**:无法处理对象类型的(如 `{} !== {}`) --- #### **场景2:兼容对象类型或需自定义规则** **方法2:使用 `filter` + `Map` 记录唯一性** ```javascript const uniqueArray = (arr) => { const seen = new Map(); return arr.filter(item => { // 自定义唯一性判断逻辑(如根据id对象) const key = typeof item + JSON.stringify(item); return seen.has(key) ? false : seen.set(key, true); }); }; ``` - **优点**:支持复杂类型,可扩展性强 - **缺点**:空间复杂度 `O(n)`,需处理 `JSON.stringify` 的局限性(如函数、循环引用) --- #### **场景3:无ES6支持(传统写法)** **方法3:遍历 + 索引比对** ```javascript function uniqueArray(arr) { return arr.filter((item, index) => arr.indexOf(item) === index); } ``` - **优点**:兼容性高(ES5) - **缺点**:时间复杂度 `O(n²)`,无法处理 `NaN`(`indexOf(NaN)` 始终返回-1) --- #### **场景4:需处理 `NaN`** **方法4:手动标记 `NaN`** ```javascript const uniqueArray = (arr) => { const seen = []; return arr.filter(item => { const isNaN = Number.isNaN(item); // 处理 NaN 的特殊情况 if (isNaN && seen.includes('NaN')) return false; if (isNaN) { seen.push('NaN'); return true; } return seen.includes(item) ? false : seen.push(item); }); }; ``` --- ### **3. 分析复杂度** | 方法 | 时间复杂度 | 空间复杂度 | 适用场景 | |------------|------------|------------|------------------------| | `Set` | O(n) | O(n) | 简单类型,ES6环境 | | `Map` | O(n) | O(n) | 复杂类型,自定义规则 | | 双遍历 | O(n²) | O(1) | 兼容性要求高 | --- ### **4. 附加思考(加分项)** - **稳定性**:是否要保持原数组顺序?(如 `Map` 方案天然保持顺序) - **特殊值处理**:如何区分 `+0` 与 `-0`?如何处理 `Symbol` 类型? - **性能优化**:超大规模数组可使用位运算或分治策略(如布隆过滤器) --- ### **5. 示例回答** “我会先确认数据结构和需求。如果是基本类型且环境支持ES6,优先用 `Set` 实现,时间复杂度最优;如果包含对象,则用 `Map` 记录唯一标识;若需兼容旧环境,可以用双遍历,但需注意性能。此外,还需处理 `NaN` 等边界情况。” --- 通过分场景、分析复杂度、提供优化方向,能体现你全面的技术思考能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值