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


    删除链表重复元素

    题目描述

    思路分析 

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

    具体分析一下指针移动

     外部循环判定卡住的位置

    c语言代码:

    1. #include
    2. #include
    3. struct ListNode
    4. {
    5. int val;
    6. struct ListNode *next;
    7. };
    8. struct ListNode *deleteDuplicates(struct ListNode *head)
    9. {
    10. // 把头结点做个备份的思想很好
    11. if (!head)
    12. {
    13. return head;
    14. }
    15. // 新建一个节点备份头结点,这也是一个哑结点
    16. struct ListNode *dummy = (struct ListNode *)malloc(sizeof(struct ListNode));
    17. dummy->next = head; // 下一个节点保存头结点,我们要让指针指向两比较结点最前面的一个结点
    18. struct ListNode *cur = dummy; // 让cur结点指向哑结点,cur结点改动,哑结点自然也会改动,最后要返回哑结点的next,也就是从头开始
    19. // 开始外部整体循环一次
    20. // 内部相同数据多次循环
    21. while (cur->next != NULL && cur->next->next != NULL)
    22. {
    23. // 如果遇到相同的节点,让内部指针移动
    24. // 1 1 1 2 2 3
    25. if (cur->next->val == cur->next->next->val)
    26. {
    27. int x = cur->next->val;
    28. // 开始内部循环相同结点
    29. while (cur->next != NULL && cur->next->val == x)
    30. {
    31. cur->next = cur->next->next; // 1 1(指向这第一次) 1 2 2 3 //还会循环一次,指向 1 1 1 2(第二次,跳出内部) 2
    32. }
    33. }
    34. else
    35. {
    36. // 如果不相等cur就正常往下面走,但是不改变next指向
    37. cur = cur->next;
    38. }
    39. }
    40. // 整体循环完之后,返回dummy指向的next头结点
    41. return dummy->next; // 返回头结点的地址
    42. }
    43. void display(struct ListNode *head)
    44. {
    45. while (head != NULL)
    46. {
    47. printf("%d ", head->val);
    48. head = head->next;
    49. }
    50. printf("\n---------\n");
    51. }
    52. int main()
    53. {
    54. struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
    55. head->val = 1;
    56. struct ListNode *p1 = (struct ListNode *)malloc(sizeof(struct ListNode));
    57. p1->val = 1;
    58. struct ListNode *p2 = (struct ListNode *)malloc(sizeof(struct ListNode));
    59. p2->val = 2;
    60. struct ListNode *p3 = (struct ListNode *)malloc(sizeof(struct ListNode));
    61. p3->val = 2;
    62. struct ListNode *p4 = (struct ListNode *)malloc(sizeof(struct ListNode));
    63. p4->val = 3;
    64. struct ListNode *p5 = (struct ListNode *)malloc(sizeof(struct ListNode));
    65. p5->val = 4;
    66. struct ListNode *p6 = (struct ListNode*)malloc(sizeof(struct ListNode));
    67. p6->val = 4;
    68. //把结点都连接起来
    69. head->next = p1;
    70. p1->next = p2;
    71. p2->next = p3;
    72. p3->next = p4;
    73. p4->next = p5;
    74. p5->next = p6;
    75. p6->next = NULL;
    76. //打印节点
    77. display(head);
    78. //删除重复结点
    79. //头结点其实就是dummy结点的next结点
    80. head = deleteDuplicates(head);
    81. display(head);
    82. return 0;
    83. }

    java代码实现:

    1. package com.pxx.leetcode.delDuplicates82;
    2. //数据节点
    3. //直接用一个对象来做
    4. class ListNode {
    5. int val;
    6. ListNode next;
    7. public ListNode(int val, ListNode next) {
    8. this.val = val;
    9. this.next = next;
    10. }
    11. public ListNode() {
    12. }
    13. public ListNode(int val) {
    14. this.val = val;
    15. }
    16. }
    17. class Solution {
    18. public ListNode deleteDuplicates(ListNode head) {
    19. if (head == null) {
    20. return head;
    21. }
    22. //哑结点
    23. ListNode dummy = new ListNode(0, head);//哑结点的next指向头结点
    24. //移动结点
    25. ListNode cur = dummy;//指针直接指向了哑结点
    26. //开始整体一次循环移动
    27. while (cur.next != null && cur.next.next != null) {
    28. //next与next.next是否相等
    29. if (cur.next.val == cur.next.next.val) {
    30. //备份一个相等的节点值用于里布进行循环判定
    31. int x = cur.next.val;
    32. // (指针可以理解为先在头部) 1 1 1
    33. while (cur.next != null && cur.next.val == x) {
    34. //更改这片空间指向的next
    35. //如果头结点不一样,头结点也会改动
    36. cur.next = cur.next.next;//第一次 1 1(指向这个位置) 1
    37. }
    38. } else {
    39. cur = cur.next;
    40. }
    41. }
    42. return dummy.next;
    43. }
    44. }
    45. public class Solution1 {
    46. }

    思路2:采用递归的方式来做

    上面就是如果头结点与它的next结点的值一样,那么就把这个头结点的next交给move结点,然后内部循环是否继续相等,知道不相等的时候跳出循环,继续以move为头结点进行递归,一旦到了一个与next不相等的位置,那么就把这个当前move指针的next继续下面递归,直到最后next等于NULL时候,停止递归,开始返回数据。

    那么最早的头一定是最晚返回的数据,所以最后的head,一定就是头结点了。

    c语言代码实现:

    1. #include
    2. #include
    3. struct ListNode
    4. {
    5. int val;
    6. struct ListNode *next;
    7. };
    8. //目的:返回第一个不是重复数字的头
    9. //过程:递归控制有效指针的next移动
    10. struct ListNode* deleteDuplicates(struct ListNode* head)
    11. {
    12. //已经是最后一个结点
    13. if (head == NULL || head->next == NULL)
    14. {
    15. return head;
    16. }
    17. if (head->val != head->next->val)
    18. {
    19. //不相等直接改变next指向
    20. head->next = deleteDuplicates(head->next);
    21. }
    22. else
    23. {
    24. struct ListNode *move = head->next;
    25. //把第一个有相同值节点的头当成头结点传入
    26. while (move != NULL && move->val == head->val)
    27. {
    28. //最后move移动到没有相同结点的位置
    29. move = move->next;
    30. }
    31. return deleteDuplicates(move);//把不是相同的节点传进来
    32. }
    33. //返回实际的next地址
    34. //最后程序结束
    35. return head;
    36. }
    37. void display(struct ListNode *head)
    38. {
    39. printf("\n-----\n");
    40. while (head != NULL)
    41. {
    42. printf("%d %d\n", head->val, head->next);
    43. head = head->next;
    44. }
    45. printf("\n---------\n");
    46. }
    47. int main()
    48. {
    49. struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
    50. head->val = 1;
    51. struct ListNode *p1 = (struct ListNode *)malloc(sizeof(struct ListNode));
    52. p1->val = 3;
    53. struct ListNode *p2 = (struct ListNode *)malloc(sizeof(struct ListNode));
    54. p2->val = 3;
    55. struct ListNode *p3 = (struct ListNode *)malloc(sizeof(struct ListNode));
    56. p3->val = 5;
    57. /*
    58. struct ListNode *p4 = (struct ListNode *)malloc(sizeof(struct ListNode));
    59. p4->val = 4;
    60. struct ListNode *p5 = (struct ListNode *)malloc(sizeof(struct ListNode));
    61. p5->val = 4;
    62. struct ListNode *p6 = (struct ListNode*)malloc(sizeof(struct ListNode));
    63. p6->val = 5;
    64. */
    65. //把结点都连接起来
    66. head->next = p1;
    67. p1->next = p2;
    68. p2->next = p3;
    69. p3->next = NULL;
    70. display(head);
    71. head = deleteDuplicates(head);
    72. display(head);
    73. return 0;
    74. }

    java代码实现

    1. package com.pxx.leetcode.delDuplicates82;
    2. //数据节点
    3. //直接用一个对象来做
    4. class ListNode {
    5. int val;
    6. ListNode next;
    7. public ListNode(int val, ListNode next) {
    8. this.val = val;
    9. this.next = next;
    10. }
    11. public ListNode() {
    12. }
    13. public ListNode(int val) {
    14. this.val = val;
    15. }
    16. }
    17. //采用一次遍历的方式来做
    18. class Solution {
    19. public ListNode deleteDuplicates(ListNode head) {
    20. if (head == null) {
    21. return head;
    22. }
    23. //哑结点
    24. ListNode dummy = new ListNode(0, head);//哑结点的next指向头结点
    25. //移动结点
    26. ListNode cur = dummy;//指针直接指向了哑结点
    27. //开始整体一次循环移动
    28. while (cur.next != null && cur.next.next != null) {
    29. //next与next.next是否相等
    30. if (cur.next.val == cur.next.next.val) {
    31. //备份一个相等的节点值用于里布进行循环判定
    32. int x = cur.next.val;
    33. // (指针可以理解为先在头部) 1 1 1
    34. while (cur.next != null && cur.next.val == x) {
    35. //更改这片空间指向的next
    36. //如果头结点不一样,头结点也会改动
    37. cur.next = cur.next.next;//第一次 1 1(指向这个位置) 1
    38. }
    39. } else {
    40. cur = cur.next;
    41. }
    42. }
    43. return dummy.next;
    44. }
    45. }
    46. //采用递归来做
    47. class Solution1 {
    48. public ListNode deleteDuplicates(ListNode head) {
    49. //最后一个结点就直接null,不做了
    50. if (head == null || head.next == null) {
    51. return head;
    52. }
    53. if (head.val != head.next.val) {
    54. //指针直接next往下面走动
    55. head.next = deleteDuplicates(head.next);
    56. } else {
    57. ListNode move = head.next;
    58. //移动到非相同数值的位置
    59. while (move != null && move.val == head.val) {
    60. move = move.next;
    61. }
    62. return deleteDuplicates(move);//继续传入下一个值递归
    63. }
    64. return head;
    65. }
    66. }
    67. public class Lc1 {
    68. public static void main(String[] args) {
    69. ListNode head = new ListNode(1,null);
    70. ListNode node1 = new ListNode(3,null);
    71. ListNode node2 = new ListNode(3,null);
    72. ListNode node3 = new ListNode(5,null);
    73. head.next = node1;
    74. node1.next = node2;
    75. node2.next = node3;
    76. node3.next = null;
    77. //打印原始链表
    78. display(head);
    79. //删除重复元素,调用递归的方法
    80. Solution1 s1 = new Solution1();
    81. head = s1.deleteDuplicates(head);
    82. display(head);
    83. }
    84. public static void display(ListNode head) {
    85. while (head != null) {
    86. System.out.print(head.val + " ");
    87. head = head.next;
    88. }
    89. System.out.println();
    90. System.out.println("-----");
    91. }
    92. }

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

  • 相关阅读:
    DPDK系列之三十一DPDK的并行机制简介
    淘宝/天猫API:item_search_neighbors-邻家好货
    【OpenCV入门学习--python】直方图的比较
    使用ping命令定位网络延迟问题
    五分钟教你如何制作学生期末网页作业(web前端期末大作业)
    ios版本小于13.4.1的手机需要前端对其调整图片方向,上传拍照照片总是方向不对
    asp.core 同时兼容JWT身份验证和Cookies 身份验证两种模式
    12.并发之ForkJoin框架详解
    声明式查询服务,只需定义,无需实现
    【Linux 系统】gcc/g++使用零星整理
  • 原文地址:https://blog.csdn.net/Pxx520Tangtian/article/details/134134699