链表
链表
删除链表元素
Leetcode19.删除链表的倒数第N个节点

问题在于如何定位倒数第n个节点。采用「双指针」。可以先P1从头遍历n个节点,然后再以P2从头开始遍历,直到P1到尾节点。此时P2刚好会落在倒数第n个节点。
代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head == null || n == 0) {
return head;
}
// 定义结果
ListNode result = new ListNode(0, head);
// pre从head开始遍历
ListNode pre = head;
// 从1开始计数,while循环结束后pre刚好指向第n个节点
int i = 1;
while(i < n) {
pre = pre.next;
i++;
}
// cur从result开始遍历。因为要删除倒数第n个节点,所以此处提前一个节点遍历
ListNode cur = result;
while(pre.next != null) {
cur = cur.next;
pre = pre.next;
}
// 删除第n个节点
cur.next = cur.next.next;
return result.next;
}
}
LeetCode82.删除排序链表中的重复元素II

代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null) {
return head;
}
ListNode result = new ListNode(-1000, head);
ListNode cur = result;
// 注意这里的判断
while(cur.next != null && cur.next.next != null) {
// 如果存在相等的case,就进入if条件
if (cur.next.val == cur.next.next.val) {
int val = cur.next.val;
// 这里用while,因为相同的元素都需要被剔除
while(cur.next != null && cur.next.val == val) {
cur.next = cur.next.next;
}
} else {
// 指针前移
cur = cur.next;
}
}
return result.next;
}
}
翻转/旋转链表
剑指offer 24.翻转链表

单向链表的翻转。代码如下。注意方法一和方法二的区别。
方法一:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null) {
return head;
}
ListNode result = new ListNode(0);
while(head != null) {
ListNode tmp = head.next;
ListNode next = result.next;
result.next = head;
head.next = next;
head = tmp;
}
return result.next;
}
}
方法二:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null) return null;
ListNode result = new ListNode();
result.next = head;
ListNode prev = result;
// 在完成翻转后,curr仍然等于head
ListNode curr = prev.next;
while(curr.next != null) {
ListNode tmp = prev.next;
prev.next = curr.next;
curr.next = curr.next.next;
prev.next.next = tmp;
}
return result.next;
}
}
LeetCode25.K个一组翻转链表

相当于分段翻转链表。注意,翻转链表后的返回结果,即head需要不断的更新。代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
if(head == null) return head;
ListNode result = new ListNode(0);
result.next = head;
ListNode prev = result;
ListNode end = prev.next;
int i = 0;
while(true) {
if(i == k) {
prev = reverse(prev, end);
i = 0;
} else {
if(end == null) {
break;
}
end = end.next;
i++;
}
}
return result.next;
}
/**
* param: 0 - 1 - 2 - 3 - 4 - 5. prev = 0, end = 3
* return: 0 - 2 - 1 - 3 - 4 - 5. curr = 1
* (参考上题的方法二)
*/
private ListNode reverse(ListNode prev, ListNode end) {
ListNode curr = prev.next;
while(curr.next != null && curr.next != end) {
ListNode tmp = prev.next;
prev.next = curr.next;
curr.next = curr.next.next;
prev.next.next = tmp;
}
return curr;
}
}
Leetcode61.旋转链表
注意该题k的取值范围,可能超过链表长度,所以需要取余。对于上图的例子,两种思路。
思路一:
另p1和p2分别指向1,然后p1先走k步,然后p1和p2同时后移,直到p1为null,此时p2指向3,然后另p3等于p2的next节点,并且p2.next=null, 然后p3继续后移,直到p3.next=null,再另p3.next=head,完毕。
代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head == null) return null;
int length = 0;
ListNode tmp = head;
while(tmp != null) {
length++;
tmp = tmp.next;
}
k = k % length;
if(k == 0) return head;
int i = 0;
ListNode p1 = head;
ListNode p2 = head;
while(i <= k) {
p1 = p1.next;
i++;
}
while(p1 != null) {
p2 = p2.next;
p1 = p1.next;
}
ListNode newHead = p2.next;
p2.next = null;
ListNode p3 = newHead;
while(p3 != null && p3.next != null) {
p3 = p3.next;
}
p3.next = head;
return newHead;
}
}
思路二:
再计算长度时,另tmp指向节点5,然后tmp.next=null。取k = length - k % length,另p1=head,然后p1先走k-1步,指向3,然后p1.next=null。完毕。
代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head == null) return null;
int length = 0;
ListNode tmp = head;
ListNode lastNode = head;
while(tmp != null) {
length++;
lastNode = tmp;
tmp = tmp.next;
}
// 将尾节点的next指向首节点
lastNode.next = head;
k = length - k % length;
tmp = head;
while(k > 1) {
tmp = tmp.next;
k--;
}
ListNode result = tmp.next;
tmp.next = null;
return result;
}
}

浙公网安备 33010602011771号