2026/4/6 15:33:11
网站建设
项目流程
茶叶网站建设模板,dz做网站缺点,医院网站制作好吗,活字格能开发企业网站吗1 题目
817. 链表组件
给定链表头结点 head#xff0c;该链表上的每个结点都有一个 唯一的整型值 。同时给定列表 nums#xff0c;该列表是上述链表中整型值的一个子集。
返回列表 nums 中组件的个数#xff0c;这里对组件的定义为#xff1a;链表中一段最长连续结点的值…1 题目817. 链表组件给定链表头结点head该链表上的每个结点都有一个唯一的整型值。同时给定列表nums该列表是上述链表中整型值的一个子集。返回列表nums中组件的个数这里对组件的定义为链表中一段最长连续结点的值该值必须在列表nums中构成的集合。示例 1输入:head [0,1,2,3], nums [0,1,3]输出:2解释:链表中,0 和 1 是相连接的且 nums 中不包含 2所以 [0, 1] 是 nums 的一个组件同理 [3] 也是一个组件故返回 2。示例 2输入:head [0,1,2,3,4], nums [0,3,1,4]输出:2解释:链表中0 和 1 是相连接的3 和 4 是相连接的所以 [0, 1] 和 [3, 4] 是两个组件故返回 2。提示链表中节点数为n1 n 1040 Node.val nNode.val中所有值不同1 nums.length n0 nums[i] nnums中所有值不同2 代码实现思考其实没什么思路确认在不在这个num里面是不是构造unordered_map?遍历遇到不在map里的就停下来。然后对于“组件”写好count计数。题解/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: int numComponents(ListNode* head, vectorint nums) { unordered_set int num_set (nums.begin(), nums.end()); int count 0 ; bool is_component false; ListNode*cur head ; while(cur !nullptr){ if(num_set.count(cur -val)){ if(!is_component){ count; is_component true; } }else{ is_component false; } cur cur - next ; } return count; } };具体分析你的思路你提到的两个核心点用哈希结构unordered_map/unordered_set判断值是否在 nums 中这是解决这个问题的关键优化因为如果直接遍历 nums 数组判断 “值是否存在”时间复杂度会是 O (n*m)n 是链表长度m 是 nums 长度而用哈希结构能把查询时间降到 O (1)整体时间复杂度优化为 O (nm)这也是这道题的最优解法思路。小补充你说的unordered_map也能用但unordered_set更贴合需求只需存值无需键值对空间和操作上更轻量不过两者核心效果一致。遍历链表遇到不在哈希结构里的就停下统计组件 count这个 “遇到不在就停下” 的思路本质就是区分 “组件内” 和 “组件外” 的状态和我代码里in_component标记的逻辑完全等价 —— 你的思路已经抓住了 “组件是最长连续段” 这个核心定义。解题思路哈希集合优化查询将 nums 数组存入unordered_set使 “判断节点值是否在 nums 中” 的操作时间复杂度降为 O (1)比 unordered_map 更轻量因为只需存值无需存键值对。遍历链表统计组件初始化组件计数count为 0标记in_component表示当前是否处于一个组件中为 false。遍历链表每个节点如果节点值在集合中且in_component为 false说明进入了新组件count1并将in_component置为 true如果节点值不在集合中说明组件中断将in_component置为 false。C 核心代码LeetCode 可直接提交/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: int numComponents(ListNode* head, vectorint nums) { // 1. 将nums存入无序集合快速查询 unordered_setint num_set(nums.begin(), nums.end()); int count 0; // 组件个数 bool in_component false; // 标记当前是否在组件中 // 2. 遍历链表 ListNode* curr head; while (curr ! nullptr) { if (num_set.count(curr-val)) { // 当前节点值在nums中且未处于组件中 → 新组件开始 if (!in_component) { count; in_component true; } } else { // 当前节点值不在nums中 → 组件中断 in_component false; } curr curr-next; // 移动到下一个节点 } return count; } };代码关键部分解释哈希集合初始化unordered_setint num_set(nums.begin(), nums.end())直接将 nums 数组转为集合利用集合的 O (1) 查询特性避免遍历 nums 数组的 O (n) 查询。核心遍历逻辑num_set.count(curr-val)判断当前节点值是否在 nums 中count 返回 1 表示存在0 表示不存在。in_component标记避免重复计数同一组件比如连续的 0、1 只会在 0 时计数一次。只有 “从非组件状态进入组件状态” 时才对count加 1符合 “最长连续节点段” 的组件定义。自己梳理以后再写的代码有错/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: int numComponents(ListNode* head, vectorint nums) { unordered_set int num_set (nums.begin(), nums.end()); int count 0 ; bool is_component true; ListNode*cur head ; while(cur !nullptr){ if(num_set.count(cur -val)){ if(!is_component){ count; is_component true; }else{ is_component false; } } cur cur - next ; } return count; } };1.核心逻辑错误状态翻转逻辑写反 缺失组件中断处理错误表现当节点值在nums中时你错误地在else分支将is_component置为false相当于 “进入组件后立刻标记为离开”同时完全缺失 “节点值不在 nums 中时标记组件中断” 的else分支影响这会导致组件的状态标记完全混乱无法正确识别 “连续的组件段”计数结果完全偏离预期。2. 细节错误状态初始值设置错误错误表现将is_component初始值设为true默认 “处于组件中”影响遍历开始前本无任何节点默认状态应为 “不在组件中false”初始值错误会导致第一个属于组件的节点无法触发计数比如示例 1 中第一个节点 0 本该让 count1却因!is_component为 false 被跳过最终少统计一个组件。3 小结感受遍历链表的题单就做完了思路很清晰正常思路去想就没什么问题无非是map \ set哪个更好是自己实践写代码知道的。之前在滑窗我只会用map来状态标记主要是自己再每个题目有细节有逻辑要实现好这一块难度不是很大基本上就是熟悉语法、数据结构。-------ai老师出场深化我的感悟。从这道题提炼出的2 个通用解题思维1.“查询加速” 的选型思维什么时候用 set/map什么时候不用这道题你一开始想到unordered_map后来知道unordered_set更优 —— 这个过程就是选型思维的体现。用哈希的核心场景需要频繁判断 “一个元素是否存在”比如本题的节点值是否在nums中且数据量较大比如本题 n 到 1e4。对比如果用数组遍历查询时间复杂度是 O (m)m 是 nums 长度1e4 数据量下会超时用哈希是 O (1)直接最优。set vs map 的选型原则只需要“存值 查询存在性”→ 用unordered_set更轻量省空间需要“键值对映射”比如链表节点值对应出现次数→ 用unordered_map。这个思维能直接套用到其他链表题比如“环形链表 II”“相交链表”里的节点查重都可以用哈希加速。2.“状态标记” 的核心思维用一个布尔变量解决 “连续段统计” 问题这道题的核心难点不是 “查询值是否存在”而是 **“如何统计最长连续段的个数”**—— 你的两个错误其实都是没吃透这个思维。状态标记的本质用一个变量比如is_component记录当前处于什么状态通过 “状态的切换” 来触发计数。本题的状态只有两种在组件中(true)/不在组件中(false)计数的唯一触发时机false → true从非组件进入组件代表新组件开始状态重置时机true → false遇到不在 nums 中的节点组件中断。