算法学习8(题解)
1.题目
给你一个链表,删除链表的倒数第n
个结点,并且返回链表的头结点。
- 注:删除节点并不是指从内存中删除它,而是让指定节点的值不应该存在于链表中。
进阶:你能尝试使用一趟扫描实现吗?
2.实例
实例一
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
实列二
输入:head = [1], n = 1
输出:[]
3.代码
鄙人的:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode tempNode = head;
int count = 0;
//求链表的长度
while(tempNode != null){
count++;
tempNode = tempNode.next;
}
count -= n;
// 说明删除的是头节点
if(count == 0){
return head.next;
}
tempNode = head;
//获取要删除链表的前一个结点
for(int i = 0; i < count - 1;i++){
tempNode = tempNode.next;
}
//完成链表删除
tempNode.next = tempNode.next.next;
return head;
}
大佬的:
public ListNode removeNthFromEnd(ListNode head, int n) {
int pos = length(head, n);
// 说明删除的是头节点
if (pos == n)
return head.next;
return head;
}
// 获取节点所在位置,逆序
public int length(ListNode node, int n) {
if (node == null)
return 0;
int pos = length(node.next, n) + 1;
//获取要删除链表的前一个结点,就可以完成链表的删除
if (pos == n + 1)
node.next = node.next.next;
return pos;
}
作者:数据结构和算法
来源:力扣(LeetCode)
4.思路
鄙人的用的最容易想到的for
循环; 大佬用的递归,也就是所谓的的一次扫描,叹服。
- 无论哪种方法,最先想到的都是获取链表的长度,可以用
for
也可以用递归;
//求链表的长度
private int length(ListNode head) {
int count = 0;
while(tempNode != null){
count++;
tempNode = tempNode.next;
}
return count;
}
private int length(ListNode head) {
if (head == null)
return 0;
return length(head.next) + 1;
}
- 接着我就用
for
循环遍历找到目标节点的前一个位置,让它指向下下个节点即可,删除头节点没有了前置节点需要特殊处理,直接返回head.next
作为链表的头节点,间接删除掉了头节点;
tempNode.next = tempNode.next.next;
if(count == 0){
return head.next;
}
- 而用递归求链表长度时,因为递归是逆向求和,也就是从后往前计算,那么求倒数位置的节点可谓正中下怀,只需要在后面添加
if
判断进行计数的pos
与n
的关系即可进行删除。
至于如何处理删除首节点,因为pos
不可能大于n
,所以没有前置节点会被自动过滤,最后只需判断返回链表长度与n
的关系即可删除首节点,妙哉。
if (pos == n)
return head.next;
以上题目及实列代码均来自于:力扣(LeetCode)