1:两两交换链表中的节点
解法1:不带虚节点
刚开始的思路是不带虚节点 。有点混乱。
/**
* 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 swapPairs(ListNode head) {
if(head == null){
return head;
}
ListNode cur = head;
ListNode after = cur.next;
ListNode result;
if(after != null){
result = after;
}
else {
result = cur;
}
while(cur!= null && after !=null){
ListNode temp = after.next;
after.next = cur;
if(temp != null && temp.next != null){
after = temp.next;
}
else if(temp != null && temp.next == null){
cur.next = temp;
break;
}
else {
after = null;
}
//这里上一个cur要指向下一个after
cur.next = after;
cur = temp;
}
return result;
}
}
解法二:带虚节点
TODO
2:删除链表的倒数第N个节点
定义双指针i和j,j首先向后移动n位,ij同时后移,i即倒数第n个节点 这里有两种解法,第一种是j最后指向链表最后一个结点,第二种是可以将j指向最后一个结点的后一个
第一种
/**
* 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) {
ListNode dummy = new ListNode(-1,head);
ListNode slow = dummy, fast = dummy;
while(n > 0 && fast.next != null){
fast = fast.next;
n--;
}
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
第二种
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//新建一个虚拟头节点指向head
ListNode dummyNode = new ListNode(0);
dummyNode.next = head;
//快慢指针指向虚拟头节点
ListNode fastIndex = dummyNode;
ListNode slowIndex = dummyNode;
// 只要快慢指针相差 n 个结点即可
for (int i = 0; i <= n; i++) {
fastIndex = fastIndex.next;
}
while (fastIndex != null) {
fastIndex = fastIndex.next;
slowIndex = slowIndex.next;
}
// 此时 slowIndex 的位置就是待删除元素的前一个位置。
// 具体情况可自己画一个链表长度为 3 的图来模拟代码来理解
// 检查 slowIndex.next 是否为 null,以避免空指针异常
if (slowIndex.next != null) {
slowIndex.next = slowIndex.next.next;
}
return dummyNode.next;
}
}
3:链表相交
简单来说,就是求两个链表交点节点的指针。 这里同学们要注意,交点不是数值相等,而是指针相等。
为了方便举例,假设节点元素数值相等,则节点指针相等。
看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:
我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
否则循环退出返回空指针。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lena= 0, lenb= 0;
ListNode curA = headA, curB = headB;
while(curA!= null){
lena++;
curA = curA.next;
}
while(curB != null){
lenb++;
curB = curB.next;
}
int abs = (lena - lenb) > 0 ? (lena - lenb) : -(lena - lenb);
curA = headA;
curB = headB;
if(lena > lenb){
while(abs > 0){
curA = curA.next;
abs--;
}
}
else{
while(abs > 0){
curB = curB.next;
abs--;
}
}
while(curA != null && curB != null){
if(curA == curB){
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
4:环形链表II
方法一:哈希表
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
Map<ListNode,Integer> map = new HashMap<>();
ListNode cur = head;
while(cur != null){
map.put(cur,map.getOrDefault(cur,0) + 1);
if(map.get(cur) > 1){
return cur;
}
cur = cur.next;
}
return null;
}
}
方法二:快慢指针法
TODO