赞
踩
本文介绍单链表删除相关的常见算法。
链表节点:
public class ListNode{
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
删除链表中等于给定值 val 的所有节点。
哑节点(dummy node)是初始值为NULL的节点,它可以起到避免处理头节点为空的边界问题的作用,减少代码执行异常的可能性。
哑节点的使用可以对代码起到简化作用,在删除节点,或者进行有序插入时,带有头部哑节点的链表可以简化代码的逻辑,我们的代码可以不用考虑第一个节点的特殊情况。
/** * 删除链表中等于val的所有节点 leetcode203 * @param head * @param val * @return */ public ListNode removeElements(ListNode head, int val){ ListNode pre = new ListNode(-1); pre.next = head; ListNode cur = pre; while (cur.next != null){ if (cur.next.val == val){ cur.next = cur.next.next; }else { cur = cur.next; } } return pre.next; }
请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
说明:
链表至少包含两个节点。
链表中所有节点的值都是唯一的。
给定的节点为非末尾节点并且一定是链表中的一个有效节点。
不要从你的函数中返回任何结果。
这个题目输入参数只有一个,是将要删除的节点,所以题目可以理解为”删除指定的节点“。
删除当前节点,需要找到上一个节点,然后让上一个节点的next指向,当前节点的next节点即可。但是这是一个单链表,我们通过当前节点无法找到它的上一个节点。
所以,我们需要换个思路,将当前节点改为next节点,然后删除next节点也就变相的实现了删除当前节点了。
/**
* 删除当前节点 leetcode 19
* @param head
*/
public void deleteNode(ListNode head) {
ListNode next = head.next;
head.val = next.val;
head.next = next.next;
}
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
删除链表的倒数第N个节点,最简单的方法就是遍历链表,找到链表的长度,然后再找找倒数N个节点就非常简答了。但是这样会经过2次遍历。
我们换个思路:
/** * 删除链表的倒数第N个节点 leetcode 19 * @param head * @param n * @return */ public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummy = new ListNode(-1); dummy.next = head; ListNode quick = dummy; ListNode slow = dummy; for (int i = 0; i < n + 1; i++) { quick = quick.next; } while (quick != null) { quick = quick.next; slow = slow.next; } slow.next = slow.next.next; return dummy.next; }
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
题目中的单链表是已排序的列表,所以,从链表头开始,依次对比节点值,如果相等,则删除即可。
/** * 83. 删除排序链表中的重复元素 * @param head * @return */ public ListNode deleteDuplicates(ListNode head) { ListNode cur = head; while (cur != null && cur.next != null){ if (cur.val == cur.next.val){ cur.next = cur.next.next; }else { cur = cur.next; } } return head; }
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中没有重复出现的数字。
示例:
输入: 1->2->3->3->4->4->5
输出: 1->2->5
该题和上一题的区别是:要删除重复数字的所有节点。
思路1:可以使用上一题的思路,遍历整个链表,当节点中的值出现重复时,则删除重复的节点,例如节点3重复,则删除第一个之后所有重复的节点,最后删除当前节点即可。
思路2:遍历链表时,使用2个指针,第一个指针pre指向无重复节点的最右端,第二个指针cur指向当前节点,当前节点与后面节点值相等时,当前节点后移一位,直到找到不相等的值为止,这时让pre的next指向cur的next,就会把所有重复元素都删除掉了。
/** * 82. 删除排序链表中的重复元素 II * * @param head * @return */ public ListNode deleteDuplicates2(ListNode head) { ListNode dummy = new ListNode(-1); dummy.next = head; ListNode cur = head, pre = dummy; boolean isDel = false; while (cur != null && cur.next != null) { if (cur.val == cur.next.val) { cur.next = cur.next.next; isDel = true; } else { if (isDel) { pre.next = cur.next; cur = pre.next; isDel = false; } else { pre = cur; cur = cur.next; } } } if (isDel) { pre.next = cur.next; } return dummy.next; }
/** * 82. 删除排序链表中的重复元素 II * * @param head * @return */ public ListNode deleteDuplicates1(ListNode head) { ListNode dummy = new ListNode(-1); dummy.next = head; ListNode cur = dummy.next, pre = dummy; while (cur != null && cur.next != null) { if (cur.val == cur.next.val) { while (cur != null && cur.next != null && cur.val == cur.next.val) { cur = cur.next; } pre.next = cur.next; cur = pre.next; } else { pre = pre.next; cur = cur.next; } } return dummy.next; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。