给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
单链表
查找复杂度O(n),删除O(1),新增O(1),
实际生产中,一般使用双向链表,空间换时间,但更实用;
比如这个查找倒数第n个节点的问题,
- 单链表需要2个指针以不同速度遍历1次实现,或者是需要完全遍历2次;
- 双向链表只需遍历1次到达尾节点,再往前遍历n次就可以完成任务;
2个指针删除倒数第N个元素的复杂度
- 时间复杂度:O(L),该算法对含有 L个结点的列表进行了一次遍历。
- 空间复杂度:O(1),只用了常量级的额外空间。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
public static ListNode removeNthFromEnd2(ListNode head, int n) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode p = dummy; int len = 0; while (p.next != null) { p = p.next; len++; } p = dummy; len -= n; while (len > 0) { len--; p = p.next; } p.next = p.next.next; return dummy.next; }
public static ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummy = new ListNode(0); dummy.next = head; ListNode q = dummy; ListNode s = dummy; for (int i = 0; i < n + 1; i++) { q = q.next; } while (q != null) { s = s.next; q = q.next; } s.next = s.next.next; return dummy.next; }
public static ListNode newSingleLinkedList(int[] vals) { ListNode[] nodes; nodes = new ListNode[vals.length]; for (int i = 0; i < vals.length; i++) { if (nodes[i] == null) { nodes[i] = new ListNode(vals[i]); } if (i < vals.length - 1) { nodes[i + 1] = new ListNode(vals[i + 1]); nodes[i].next = nodes[i + 1]; } } return nodes[0]; }
public static class ListNode { int val; ListNode next;
public ListNode(int val) { this.val = val; }
public void printNode() { ListNode printNode = this; StringBuilder sb = new StringBuilder(); while (printNode != null) { sb.append("-->").append(printNode.val); printNode = printNode.next; } System.out.println(sb); } }
|