707. 设计链表

image.png

题解

image.png

  1. class MyLinkedList {
  2. /**
  3. * 伪头节点
  4. */
  5. private ListNode dummyHead;
  6. private ListNode tail;
  7. private int size;
  8. public static class ListNode {
  9. int val;
  10. ListNode next;
  11. public ListNode(int val) {
  12. this.val = val;
  13. }
  14. public ListNode(int val, ListNode next) {
  15. this.val = val;
  16. this.next = next;
  17. }
  18. }
  19. public MyLinkedList() {
  20. dummyHead = new ListNode(0);
  21. tail = dummyHead;
  22. size = 0;
  23. }
  24. /**
  25. * 根据索引获取节点值
  26. *
  27. * @param index
  28. * @return
  29. */
  30. public int get(int index) {
  31. ListNode node = getNode(index);
  32. if (node == null) {
  33. return -1;
  34. } else {
  35. return node.val;
  36. }
  37. }
  38. /**
  39. * 私有辅助方法,根据索引获取节点
  40. *
  41. * @param index
  42. * @return
  43. */
  44. private ListNode getNode(int index) {
  45. if (index < 0 || index > size - 1) return null;
  46. ListNode temp = dummyHead.next;
  47. for (int i = 0; i < index && temp != null; i++) {
  48. temp = temp.next;
  49. }
  50. return temp;
  51. }
  52. /**
  53. * 在头部插入元素
  54. *
  55. * @param val
  56. */
  57. public void addAtHead(int val) {
  58. // 生成一个结点,存放的值为 val
  59. ListNode addNode = new ListNode(val);
  60. // 注意动静结合原则,添加结点时,注意修改 tail 指针
  61. if (dummyHead == tail) tail = addNode;
  62. ListNode tempHead = dummyHead.next;
  63. dummyHead.next = addNode;
  64. addNode.next = tempHead;
  65. size ++;
  66. }
  67. /**
  68. * 在尾部插入元素
  69. *
  70. * @param val
  71. */
  72. public void addAtTail(int val) {
  73. tail.next = new ListNode(val);
  74. tail = tail.next;
  75. size ++;
  76. }
  77. /**
  78. * 在索引 index 处插入元素
  79. *
  80. * @param index
  81. * @param val
  82. */
  83. public void addAtIndex(int index, int val) {
  84. if (index <= 0) {
  85. // 如果 index 小于 0,则在头部插入结点
  86. addAtHead(val);
  87. } else if (index > size) {
  88. // 如果 index 大于链表长度,则不会插入结点
  89. } else if (index == size) {
  90. // 如果 index 等于链表的长度,则该结点将附加到链表的末尾
  91. addAtTail(val);
  92. } else {
  93. ListNode nodeWithPreIndex = getNode(index - 1);
  94. ListNode tempNext = nodeWithPreIndex.next;
  95. nodeWithPreIndex.next = new ListNode(val);
  96. nodeWithPreIndex.next.next = tempNext;
  97. size ++;
  98. }
  99. }
  100. /**
  101. * 删除索引为 index 的元素
  102. *
  103. * @param index
  104. */
  105. public void deleteAtIndex(int index) {
  106. // 如果index无效,那么什么也不做
  107. if (index < 0 || index > size - 1) return;
  108. // 找到index前面的结点
  109. ListNode temp = dummyHead;
  110. for (int i = 0; i < index && temp != null; i++) {
  111. temp = temp.next;
  112. }
  113. // 如果要删除的是最后一个结点,那么需要更改tail指针
  114. if (temp.next == tail) {
  115. tail = temp;
  116. }
  117. // 执行删除
  118. temp.next = temp.next.next;
  119. size--;
  120. }
  121. @Override
  122. public String toString() {
  123. StringBuilder sb = new StringBuilder();
  124. ListNode listNode = dummyHead.next;
  125. sb.append("size: ").append(size).append(" ; ");
  126. while (listNode != null) {
  127. sb.append(listNode.val).append("->");
  128. listNode = listNode.next;
  129. }
  130. sb.append("NULL");
  131. return sb.toString();
  132. }
  133. }