LeetCode
203. 移除链表元素
删除链表中等于给定值 val 的所有结点。
思路:
删除结点这件事情很可能发生在链表的头结点,因此需要对头结点特殊处理。
递归,首先处理递归到底的情况,直接返回 null。假设下一个结点开始的链表已经处理完了。再将头结点和除了头结点以外的链表部分合并考虑。
执行用时:1 ms, 在所有 Java 提交中击败了99.84%的用户。
class Solution {public ListNode removeElements(ListNode head, int val) {ListNode dummy = new ListNode(0);dummy.next = head;ListNode cur = dummy;while (cur.next != null) {if (cur.next.val == val) {cur.next = cur.next.next;} else {cur = cur.next;}}return dummy.next;}}
class Solution {
public ListNode removeElements(ListNode head, int val) {
if (head == null) {
return head;
}
ListNode res = removeElements(head.next, val);
if (head.val == val) {
return res;
} else {
head.next = res;
return head;
}
}
}
21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有结点组成的。
思路:
比较大小然后合并,注意递归和非递归两种方法。
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户。
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l2.next, l1);
return l2;
}
}
}
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(-1);
ListNode newhead = dummy;
while(l1 != null && l2 != null) {
if(l1.val < l2.val) {
newhead.next = l1;
l1 = l1.next;
} else {
newhead.next = l2;
l2 = l2.next;
}
newhead = newhead.next;
}
if(l1 != null) {
newhead.next = l1;
} else {
newhead.next = l2;
}
return dummy.next;
}
}
练习:
82. 删除排序链表中的重复元素 II
剑指 Offer
剑指 Offer 18. 删除链表的节点
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意:此题对比原题有改动
思路:
①链表。题目说了没有重复的值,先判断开头节点是否是我们要删除的,再开始遍历,如果遇到要删除的节点,分这个节点的下一个节点是否为null讨论。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteNode(ListNode head, int val) {
if (head.val == val) {
return head.next;
}
ListNode dummy = head;
while (dummy.next != null) {
ListNode temp = dummy.next;
if (temp.val == val) {
if (temp.next != null) {
dummy.next = temp.next;
} else {
dummy.next = null;
}
break;
}
dummy = dummy.next;
}
return head;
}
}
②双指针。
class Solution {
public ListNode deleteNode(ListNode head, int val) {
//初始化一个虚拟节点
ListNode dummy = new ListNode(0);
//让虚拟节点指向头结点
dummy.next = head;
ListNode cur = head;
ListNode pre = dummy;
while (cur != null) {
if (cur.val == val) {
//如果找到要删除的结点,直接把他删除
pre.next = cur.next;
break;
}
//如果没找到,pre指针和cur指针都同时往后移一步
pre = cur;
cur = cur.next;
}
//最后返回虚拟节点的下一个结点即可
return dummy.next;
}
}
③递归。
class Solution {
public ListNode deleteNode(ListNode head, int val) {
//边界条件判断
if (head == null)
return head;
//如果要删除的是头结点,直接返回头结点的下一个结点即可
if (head.val == val)
return head.next;
ListNode cur = head;
//找到要删除结点的上一个结点
while (cur.next != null && cur.next.val != val) {
cur = cur.next;
}
//删除结点
cur.next = cur.next.next;
return head;
}
}
剑指 Offer 35. 复杂链表的复制
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
思路:
1.复制每个节点。
2.复制随机节点。dummy.random.next而不是dummy.random,因为要指向之前复制的节点,不能指向原节点
3.拆分链表。
/*
// Definition for a Node.
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
*/
class Solution {
public Node copyRandomList(Node head) {
if (head == null) {
return head;
}
Node dummy = head;
while (dummy != null) {
Node clone = new Node(dummy.val);
Node next = dummy.next;
dummy.next = clone;
clone.next = next;
dummy = next;
}
dummy = head;
while (dummy != null) {
dummy.next.random = dummy.random == null ? null : dummy.random.next;
dummy = dummy.next.next;
}
dummy = head;
Node cloneHead = head.next;
while (dummy != null) {
Node clone = dummy.next;
dummy.next = clone.next;
clone.next = clone.next == null ? null : clone.next.next;
dummy = dummy.next;
}
return cloneHead;
}
}
