LeetCode 141. Linked List Cycle

链表循环检测

Given a linked list, determine if it has a cycle in it.

To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.

Example 1:

Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the second node.
在这里插入图片描述

Example 2:

Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the first node.
在这里插入图片描述

Example 3:

Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.

在这里插入图片描述

Follow up:

Can you solve it using O(1) (i.e. constant) memory?

划重点 o(1)很自然想到用哈希表来解决

public static boolean hasCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        while (head != null) {
            if (set.contains(head)) {  //set中已经有,说明有环
                return true;
            } else {
                set.add(head);
            }
            head = head.next;
        }
        return false;
    }


在C/C++开发中,`corrupted double-linked list` 错误通常表示堆内存管理结构遭到破坏。这类错误常见于使用 `malloc`、`free`、`new` 或 `delete` 等动态内存管理函数时出现不当操作。 ### 常见原因分析 1. **越界写入(Buffer Overflow)**:当程序向分配的内存块之外的区域进行写操作时,可能覆盖了内存管理器维护的数据结构,例如堆链表中的指针信息。 2. **重复释放(Double Free)**:对同一块内存调用多次 `free` 或 `delete`,可能导致堆链表的前后指针指向无效地址,从而破坏双向链表结构。 3. **释放未分配的内存(Invalid Free)**:尝试释放一个未通过 `malloc` 或 `new` 分配的指针,或已经释放过的内存。 4. **内存泄漏(Memory Leak)**:虽然不会直接导致堆损坏,但长期运行的程序如果存在大量内存泄漏,可能引发后续内存分配失败,间接导致异常行为。 5. **跨库内存分配/释放问题**:例如在一个共享库中使用 `malloc` 分配内存,而在另一个库中使用 `free` 释放,若链接方式不一致(如静态与动态链接混用),也可能破坏堆结构。 ### 调试方法 1. **GDB调试**: - 使用 GDB 捕获崩溃现场,查看堆栈跟踪以定位出错位置。 - 检查涉及内存分配和释放的代码路径是否正确,尤其是 `malloc` 和 `free` 的匹配情况。 2. **Valgrind工具**: - 利用 Valgrind 的 Memcheck 工具检测非法内存访问和内存泄漏问题。 - 示例输出如 `Invalid write of size 8` 表明程序在某个内存块之后进行了非法写入操作,这可能是缓冲区溢出 [^2]。 - Valgrind 可以帮助识别出具体的内存访问违规行为,并指出相关代码行。 3. **AddressSanitizer (ASan)**: - ASan 是一种快速的内存错误检测工具,集成在 GCC 和 Clang 中。 - 它能高效地发现堆栈溢出、全局变量溢出、使用已释放内存等问题。 - 编译时加入 `-fsanitize=address` 并运行程序即可获得详细的诊断信息。 4. **检查内存分配与释放逻辑**: - 确保每次 `malloc` 或 `new` 都有对应的 `free` 或 `delete`。 - 避免对同一个指针调用多次 `free`。 - 对数组使用 `new[]` 和 `delete[]` 进行匹配操作。 ### 解决方案 - **修复越界写入**:仔细检查数组、字符串操作等场景,确保不会超出分配的内存范围。可以使用更安全的函数如 `strncpy` 替代 `strcpy`。 - **避免重复释放**:为每个分配的指针设置一个清晰的所有权模型,确保只释放一次。 - **统一内存管理策略**:在同一模块中完成内存分配与释放,特别是在跨库调用时,确保使用相同的内存分配器。 - **使用智能指针(C++)**:利用 `std::unique_ptr` 和 `std::shared_ptr` 自动管理内存生命周期,减少手动释放的风险。 - **启用编译器警告和静态分析**:使用 `-Wall`、`-Wextra` 等选项捕获潜在问题,结合静态分析工具如 Clang Static Analyzer 提前发现隐患。 ### 示例:使用智能指针避免手动管理内存 ```cpp #include <memory> #include <iostream> int main() { // 使用 unique_ptr 自动管理内存 std::unique_ptr<int[]> data(new int[100]); // 使用数据... for (int i = 0; i < 100; ++i) { data[i] = i; } // 不需要手动 delete,离开作用域自动释放 return 0; } ``` 通过上述方法,可以有效定位并修复 `corrupted double-linked list` 错误的根本原因,提升程序的稳定性和健壮性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值