删除链表重复元素
题目描述
思路分析
思路1:采用一次遍历,内部循环判定是否相等
具体分析一下指针移动
c语言代码:
#include
#include
struct ListNode
{
int val;
struct ListNode *next;
};
struct ListNode *deleteDuplicates(struct ListNode *head)
{
// 把头结点做个备份的思想很好
if (!head)
{
return head;
}
// 新建一个节点备份头结点,这也是一个哑结点
struct ListNode *dummy = (struct ListNode *)malloc(sizeof(struct ListNode));
dummy->next = head; // 下一个节点保存头结点,我们要让指针指向两比较结点最前面的一个结点
struct ListNode *cur = dummy; // 让cur结点指向哑结点,cur结点改动,哑结点自然也会改动,最后要返回哑结点的next,也就是从头开始
// 开始外部整体循环一次
// 内部相同数据多次循环
while (cur->next != NULL && cur->next->next != NULL)
{
// 如果遇到相同的节点,让内部指针移动
// 1 1 1 2 2 3
if (cur->next->val == cur->next->next->val)
{
int x = cur->next->val;
// 开始内部循环相同结点
while (cur->next != NULL && cur->next->val == x)
{
cur->next = cur->next->next; // 1 1(指向这第一次) 1 2 2 3 //还会循环一次,指向 1 1 1 2(第二次,跳出内部) 2
}
}
else
{
// 如果不相等cur就正常往下面走,但是不改变next指向
cur = cur->next;
}
}
// 整体循环完之后,返回dummy指向的next头结点
return dummy->next; // 返回头结点的地址
}
void display(struct ListNode *head)
{
while (head != NULL)
{
printf("%d ", head->val);
head = head->next;
}
printf("\n---------\n");
}
int main()
{
struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
head->val = 1;
struct ListNode *p1 = (struct ListNode *)malloc(sizeof(struct ListNode));
p1->val = 1;
struct ListNode *p2 = (struct ListNode *)malloc(sizeof(struct ListNode));
p2->val = 2;
struct ListNode *p3 = (struct ListNode *)malloc(sizeof(struct ListNode));
p3->val = 2;
struct ListNode *p4 = (struct ListNode *)malloc(sizeof(struct ListNode));
p4->val = 3;
struct ListNode *p5 = (struct ListNode *)malloc(sizeof(struct ListNode));
p5->val = 4;
struct ListNode *p6 = (struct ListNode*)malloc(sizeof(struct ListNode));
p6->val = 4;
//把结点都连接起来
head->next = p1;
p1->next = p2;
p2->next = p3;
p3->next = p4;
p4->next = p5;
p5->next = p6;
p6->next = NULL;
//打印节点
display(head);
//删除重复结点
//头结点其实就是dummy结点的next结点
head = deleteDuplicates(head);
display(head);
return 0;
}
java代码实现:
package com.pxx.leetcode.delDuplicates82;
//数据节点
//直接用一个对象来做
class ListNode {
int val;
ListNode next;
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
}
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if (head == null) {
return head;
}
//哑结点
ListNode dummy = new ListNode(0, head);//哑结点的next指向头结点
//移动结点
ListNode cur = dummy;//指针直接指向了哑结点
//开始整体一次循环移动
while (cur.next != null && cur.next.next != null) {
//next与next.next是否相等
if (cur.next.val == cur.next.next.val) {
//备份一个相等的节点值用于里布进行循环判定
int x = cur.next.val;
// (指针可以理解为先在头部) 1 1 1
while (cur.next != null && cur.next.val == x) {
//更改这片空间指向的next
//如果头结点不一样,头结点也会改动
cur.next = cur.next.next;//第一次 1 1(指向这个位置) 1
}
} else {
cur = cur.next;
}
}
return dummy.next;
}
}
public class Solution1 {
}
思路2:采用递归的方式来做
上面就是如果头结点与它的next结点的值一样,那么就把这个头结点的next交给move结点,然后内部循环是否继续相等,知道不相等的时候跳出循环,继续以move为头结点进行递归,一旦到了一个与next不相等的位置,那么就把这个当前move指针的next继续下面递归,直到最后next等于NULL时候,停止递归,开始返回数据。
那么最早的头一定是最晚返回的数据,所以最后的head,一定就是头结点了。
c语言代码实现:
#include
#include
struct ListNode
{
int val;
struct ListNode *next;
};
//目的:返回第一个不是重复数字的头
//过程:递归控制有效指针的next移动
struct ListNode* deleteDuplicates(struct ListNode* head)
{
//已经是最后一个结点
if (head == NULL || head->next == NULL)
{
return head;
}
if (head->val != head->next->val)
{
//不相等直接改变next指向
head->next = deleteDuplicates(head->next);
}
else
{
struct ListNode *move = head->next;
//把第一个有相同值节点的头当成头结点传入
while (move != NULL && move->val == head->val)
{
//最后move移动到没有相同结点的位置
move = move->next;
}
return deleteDuplicates(move);//把不是相同的节点传进来
}
//返回实际的next地址
//最后程序结束
return head;
}
void display(struct ListNode *head)
{
printf("\n-----\n");
while (head != NULL)
{
printf("%d %d\n", head->val, head->next);
head = head->next;
}
printf("\n---------\n");
}
int main()
{
struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
head->val = 1;
struct ListNode *p1 = (struct ListNode *)malloc(sizeof(struct ListNode));
p1->val = 3;
struct ListNode *p2 = (struct ListNode *)malloc(sizeof(struct ListNode));
p2->val = 3;
struct ListNode *p3 = (struct ListNode *)malloc(sizeof(struct ListNode));
p3->val = 5;
/*
struct ListNode *p4 = (struct ListNode *)malloc(sizeof(struct ListNode));
p4->val = 4;
struct ListNode *p5 = (struct ListNode *)malloc(sizeof(struct ListNode));
p5->val = 4;
struct ListNode *p6 = (struct ListNode*)malloc(sizeof(struct ListNode));
p6->val = 5;
*/
//把结点都连接起来
head->next = p1;
p1->next = p2;
p2->next = p3;
p3->next = NULL;
display(head);
head = deleteDuplicates(head);
display(head);
return 0;
}
java代码实现
package com.pxx.leetcode.delDuplicates82;
//数据节点
//直接用一个对象来做
class ListNode {
int val;
ListNode next;
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
}
//采用一次遍历的方式来做
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if (head == null) {
return head;
}
//哑结点
ListNode dummy = new ListNode(0, head);//哑结点的next指向头结点
//移动结点
ListNode cur = dummy;//指针直接指向了哑结点
//开始整体一次循环移动
while (cur.next != null && cur.next.next != null) {
//next与next.next是否相等
if (cur.next.val == cur.next.next.val) {
//备份一个相等的节点值用于里布进行循环判定
int x = cur.next.val;
// (指针可以理解为先在头部) 1 1 1
while (cur.next != null && cur.next.val == x) {
//更改这片空间指向的next
//如果头结点不一样,头结点也会改动
cur.next = cur.next.next;//第一次 1 1(指向这个位置) 1
}
} else {
cur = cur.next;
}
}
return dummy.next;
}
}
//采用递归来做
class Solution1 {
public ListNode deleteDuplicates(ListNode head) {
//最后一个结点就直接null,不做了
if (head == null || head.next == null) {
return head;
}
if (head.val != head.next.val) {
//指针直接next往下面走动
head.next = deleteDuplicates(head.next);
} else {
ListNode move = head.next;
//移动到非相同数值的位置
while (move != null && move.val == head.val) {
move = move.next;
}
return deleteDuplicates(move);//继续传入下一个值递归
}
return head;
}
}
public class Lc1 {
public static void main(String[] args) {
ListNode head = new ListNode(1,null);
ListNode node1 = new ListNode(3,null);
ListNode node2 = new ListNode(3,null);
ListNode node3 = new ListNode(5,null);
head.next = node1;
node1.next = node2;
node2.next = node3;
node3.next = null;
//打印原始链表
display(head);
//删除重复元素,调用递归的方法
Solution1 s1 = new Solution1();
head = s1.deleteDuplicates(head);
display(head);
}
public static void display(ListNode head) {
while (head != null) {
System.out.print(head.val + " ");
head = head.next;
}
System.out.println();
System.out.println("-----");
}
}
好了,祝大家早安午安晚安