题目:给定单向链表的头指针和一个节点指针,定义一个函数在 删除链表的节点 - 图1#card=math&code=O%281%29) 时间内删除该节点。

    常规我们删除节点是从头节点开始遍历,找到要删除的节点,然后删除它。之所以要从头结点开始,是因为我们要找到该节点的前一个节点,然后才能删除该节点,有如下链表

    删除链表的节点 - 图2

    比如我们要删除节点 3,这个时候我们必须找到它的前一个节点 2,将节点 2 的下一个指针指向节点 3 的下一个节点,如下

    删除链表的节点 - 图3

    但是从头结点开始查找的话,它的时间复杂度就是 删除链表的节点 - 图4#card=math&code=O%28n%29),达不到题目所要求的 删除链表的节点 - 图5#card=math&code=O%281%29) 的时间复杂度,这个时候我们就要另辟蹊径了。还是以删除节点 3 为例,这个时候可以将它下一个节点的值覆盖要被删除节点的值,即用 4 覆盖 3,然后删除节点 4,因为我们知道节点 4 的前一个节点(即给定的要删除的节点),所以可以将节点 4 删除,如下

    删除链表的节点 - 图6

    这时我们不用从头结点进行遍历,所需要的复杂度是 删除链表的节点 - 图7#card=math&code=O%281%29)。

    但是事情到这里还没有完成,如果要删除的节点是最后一个节点呢? 这个时候它没有下一个节点,我们就不得不从头结点开始遍历来删除这个节点了,这个时候就得知道它的前一个节点。这里又要考虑一种情况,因为要知道尾结点的前一个节点,如果链表只有一个元素的话,尾结点就没有前一个节点,这种情况要做特殊处理。代码如下:

    1. public class DeleteNode {
    2. private static class ListNode {
    3. ListNode next;
    4. int value;
    5. public ListNode(int value) {
    6. this.value = value;
    7. this.next = null;
    8. }
    9. }
    10. public static ListNode deleteNode(ListNode root, ListNode toBeDeletedNode) {
    11. if (root == null || toBeDeletedNode == null) {
    12. return root;
    13. }
    14. // 如果不是尾结点
    15. if (toBeDeletedNode.next != null) {
    16. // 将后面节点的值覆盖要删除的节点的值
    17. toBeDeletedNode.value = toBeDeletedNode.next.value;
    18. // 删除下一个节点
    19. ListNode deleteNext = toBeDeletedNode.next;
    20. toBeDeletedNode.next = deleteNext.next;
    21. deleteNext = null;
    22. } else {
    23. // 被删除的节点是尾结点
    24. ListNode cur = root;
    25. // 同时被删除的节点也是头结点,即只有一个元素
    26. if (cur == toBeDeletedNode) {
    27. root = null;
    28. toBeDeletedNode = null;
    29. return root;
    30. }
    31. // 从头结点遍历找到前一个节点
    32. while(cur.next != toBeDeletedNode) {
    33. cur = cur.next;
    34. }
    35. cur.next = null;
    36. toBeDeletedNode = null;
    37. }
    38. return root;
    39. }
    40. // 打印链表的方法
    41. public static void printList(ListNode root) {
    42. while (root != null) {
    43. if (root.next != null) {
    44. System.out.print(root.value + "->");
    45. } else {
    46. System.out.println(root.value);
    47. }
    48. root = root.next;
    49. }
    50. }
    51. // 测试代码
    52. public static void main(String[] args) {
    53. ListNode root = new ListNode(1);
    54. root.next = new ListNode(2);
    55. root.next.next = new ListNode(3);
    56. root.next.next.next = new ListNode(4);
    57. root.next.next.next.next = new ListNode(5);
    58. printList(root); // 1->2->3->4->5
    59. root = deleteNode(root, root.next.next.next.next);
    60. printList(root); // 1->2->3->4
    61. root = deleteNode(root, root);
    62. printList(root); // 2->3->4
    63. root = deleteNode(root, root.next);
    64. printList(root); // 2->4
    65. root = deleteNode(root, root.next);
    66. printList(root); // 2
    67. root = deleteNode(root, root);
    68. printList(root); //
    69. }
    70. }

    题目:在一个排序的链表中,如何删除重复的节点?

    这道题仔细一想的话非常简单,因为这个链表是有序的,这就意味着重复的节点是连在一起的,所以我们只要比较当前节点与下一个节点的值是否相同,如果相同,则删除下一个节点,如果不同则移动当前节点到下一个节点,代码如下:

    1. public class DeleteDuplicationNode {
    2. private static class ListNode {
    3. ListNode next;
    4. int value;
    5. public ListNode(int value) {
    6. this.value = value;
    7. this.next = null;
    8. }
    9. }
    10. public static void deleteDuplicationNode(ListNode root) {
    11. if (root == null) {
    12. return;
    13. }
    14. ListNode cur = root;
    15. while(cur.next != null) {
    16. // 如果当前节点的值与下一个节点的值相同,删除下一个节点
    17. if (cur.value == cur.next.value) {
    18. ListNode curNext = cur.next;
    19. cur.next = curNext.next;
    20. curNext = null;
    21. } else {
    22. // 否则移动当前节点
    23. cur = cur.next;
    24. }
    25. }
    26. }
    27. // 打印链表
    28. public static void printList(ListNode root) {
    29. while (root != null) {
    30. if (root.next != null) {
    31. System.out.print(root.value + "->");
    32. } else {
    33. System.out.println(root.value);
    34. }
    35. root = root.next;
    36. }
    37. }
    38. public static void main(String[] args) {
    39. ListNode root = new ListNode(1);
    40. root.next = new ListNode(1);
    41. root.next.next = new ListNode(2);
    42. root.next.next.next = new ListNode(2);
    43. root.next.next.next.next = new ListNode(2);
    44. root.next.next.next.next.next = new ListNode(3);
    45. printList(root); // 1->1->2->2->2->3
    46. deleteDuplicationNode(root); // 1->2->3
    47. printList(root);
    48. }
    49. }