leetcode82删除排序链表中的重复元素

删除链表重复元素

题目描述

leetcode82删除排序链表中的重复元素_第1张图片

思路分析 

思路1:采用一次遍历,内部循环判定是否相等

leetcode82删除排序链表中的重复元素_第2张图片

具体分析一下指针移动

leetcode82删除排序链表中的重复元素_第3张图片 外部循环判定卡住的位置

leetcode82删除排序链表中的重复元素_第4张图片

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:采用递归的方式来做

leetcode82删除排序链表中的重复元素_第5张图片

上面就是如果头结点与它的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("-----");
    }

}

好了,祝大家早安午安晚安

你可能感兴趣的:(算法刷题,链表,数据结构)