一. 两两交换链表中的节点
题目链接:力扣
思路:
题目要求,不能修改数据域内容,只能进行节点交换。因此这道题只能通过修改每个节点的 .next 指针去解题。
这道题录哥给的建议是使用虚拟头结点,这样总能保证头结点后和链表是连着的,不会出现头结点是一个孤零零的头结点,链表是链表的情况。
而且使用虚拟头结点的话,头结点是固定的。也就是说头结点是一个“不变量”,可以使用递归去解题。
代码:
class Solution {
public ListNode swapPairs(ListNode head) {
//特值判断
if(head == null || head.next == null){
return head;
}
//获取当前节点的下一节点
ListNode next = head.next;
//递归
ListNode newNode = swapPairs(next.next);
//交换结点
next.next = head;
head.next = newNode;
return next;
}
}
上述代码中 newNode即作为头结点存在。
二. 删除链表的倒数第N个结点
题目链接:力扣
思路:
双指针,先让快指针向前走n+1步,让快慢指针之间始终相差n个元素,直到遍历结束。
此时,慢指针所指向的位置便是要删除元素的前一个位置。
代码:
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//虚拟头结点
ListNode dummunNode = new ListNode(0);
//将其放在头结点之前
dummunNode.next = head;
//快慢双指针都从头结点开始
ListNode fastIndex = dummunNode;
ListNode slowIndex = dummunNode;
//要求两个指针之间相差为n
for(int i =0; i<n; i++) {
fastIndex = fastIndex.next;
}
//而后两指针同时向后遍历
while(fastIndex.next != null) {
fastIndex = fastIndex.next;
slowIndex = slowIndex.next;
}
//此时slowIndex的位置就是待删除元素的前一位置
slowIndex.next = slowIndex.next.next;
return dummunNode.next;
}
}
三. 链表相交(面试题)
题目链接:力扣
思路:
这道题就是求两个链表交点节点的指针。因为,交点不是数值相等,而是指针相等。
假设俩链表交点的数值相等,那么我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到和curB 末尾对齐的位置,就可以比较curA和curB是否相同。如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
代码:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//创建俩链表的指针,用于遍历
ListNode hA = headA;
ListNode hB = headB;
//记录长度
int lenA = 0, lenB = 0;
//求A的长度
while(hA != null){
hA = hA.next;
lenA++;
}
//求B的长度
while(hB != null) {
hB = hB.next;
lenB++;
}
//将俩指针再回到俩链表开头
hA = headA;
hB = headB;
//让hA为最长链表的头,lenA为长度
if(lenB > lenA){
//交换A,B长度
int temp = lenA;
lenA = lenB;
lenB = temp;
//交换A,B指针
ListNode tempCur = hA;
hA = hB;
hB = tempCur;
}
//求长度差
int gap = lenA-lenB;
//移动A,B指针,使其处于同一起点
while(gap-- > 0) {
hA = hA.next;
}
//遍历A,B链表,遇到相同便返回
while(hA != null) {
if(hA == hB) {
return hA;
}
hA = hA.next;
hB = hB.next;
}
//若未返回则说明没有交点
return null;
}
}