记录十四——从已排序的链表中删除重复项

删除已排序链表中的重复项

给出一个已排序的链表,删除所有重复的元素保证每个元素只出现一次


Input: 1->1->2
Output: 1->2


Input: 1->1->2->3->3
Output: 1->2->3


这道题是一道简单题,考察的就是对链表的指针操作,需要加强这方面的练习

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode curr = head;
        while(curr != null && curr.next != null){
            if(curr.val == curr.next.val){
                curr.next = curr.next.next;
            }
            else {
                curr = curr.next;
            }
        }
        return head;
    }
}
好的,下面是关于如何使用 C 实现“删除排序链表中的重复元素”的详细说明及代码实现过程。 --- ### **问题解析** 我们需要编写一个程序来移除排序链表中的所有重复节点,只保留唯一值的节点,并保证结果仍然按升序排列。由于输入已经是非递减排列的链表,因此我们可以利用这一特性简化算法设计。 #### 主要步骤: 1. 创建一个结构体表示单向链表节点 `ListNode`。 2. 定义函数用于遍历链表,检查当前节点与其下一个节点是否相等。 - 如果相等,则跳过该重复节点; - 否则继续向下移动指针。 3. 最终返回去重后的链表头结点。 以下是完整代码及其逐行解释: ```c #include <stdio.h> #include <stdlib> // 定义链表节点结构体 typedef struct ListNode { int val; // 节点值 struct ListNode* next; // 指向下一节点的指针 } ListNode; // 函数声明:创建新节点、插入节点到链表尾部以及打印链表内容 ListNode* createNode(int value); void append(ListNode** head_ref, int new_data); void printList(ListNode* node); // 核心功能:删除排序链表中的重复项 ListNode* deleteDuplicates(ListNode* head) { if (head == NULL || head->next == NULL) { // 边界条件判断 return head; } ListNode *current = head; while (current != NULL && current->next != NULL) { if (current->val == current->next->val) { ListNode *temp = current->next; // 记录待删节点地址 current->next = temp->next; // 绕过重复节点 free(temp); // 删除重复节点释放内存 } else { current = current->next; // 移动至下一个不同节点 } } return head; } int main() { // 初始化空链表 ListNode* head = NULL; // 示例数据构建链表: 1 -> 1 -> 2 -> 3 -> 3 append(&head, 1); append(&head, 1); append(&head, 2); append(&head, 3); append(&head, 3); printf("原始链表:\n"); printList(head); // 执行去除重复操作 head = deleteDuplicates(head); printf("\n去重后链表:\n"); printList(head); return 0; } // 动态分配空间生成一个新的节点 ListNode* createNode(int value) { ListNode* newNode = (ListNode*)malloc(sizeof(ListNode)); newNode->val = value; newNode->next = NULL; return newNode; } // 尾插法将数值添加进链表 void append(ListNode** head_ref, int new_data) { ListNode* newNode = createNode(new_data); if (*head_ref == NULL) { *head_ref = newNode; return; } ListNode* last = *head_ref; while (last->next != NULL) last = last->next; last->next = newNode; } // 输出链表的所有节点值 void printList(ListNode* node) { while (node != NULL) { printf("%d ", node->val); node = node->next; } } ``` --- ### **逐步讲解** 1. **定义链表节点类型 (`struct ListNode`)** 我们通过自定义结构体实现了基本的单链表形式。每个节点包含两个部分: - 数据域 `val` 表示存储的数据(这里为整数); - 指针域 `next` 引用指向下一个节点的对象引用或为空(NULL),表示结束标志。 2. **核心逻辑——`deleteDuplicates` 函数** 此处采用迭代的方式从前往后逐一比较相邻两节点的数值大小关系;若发现连续两项相匹配,则直接调整前驱节点链接以绕开中间那个多余的副本位置。 3. **辅助工具** 包含了几个简单的实用小方法如构造新的单一单元实例(`createNode`),追加指定项目到最后端(`append`)还有展示整个序列状态的功能模块(`printList`)便于测试验证最终效果正确与否。 4. **主入口点(main function)** 构建初始样本集合再调用上述消除多余拷贝的服务最后输出修改版本供用户查看对比差异情况。 --- ### § **相关问题§** 1. 如何对未排好序的一般情形下的普通列表做同样的操作呢? 2. 当遇到极端情况比如全是相同的数字构成的大规模循环时性能表现会怎样变化? 3. 是否有更高效的空间优化策略而无需额外开辟临时变量来进行交换或其他复杂变换动作?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值