24. 两两交换链表中的节点
重点
保存节点
了解curnode下一步在哪里
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dumyhead = new ListNode(-1); // 设置一个虚拟头结点
dumyhead.next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
ListNode cur = dumyhead;
ListNode temp; // 临时节点,保存两个节点后面的节点
ListNode firstnode; // 临时节点,保存两个节点之中的第一个节点
ListNode secondnode; // 临时节点,保存两个节点之中的第二个节点
while (cur.next != null && cur.next.next != null) {
temp = cur.next.next.next;
firstnode = cur.next;
secondnode = cur.next.next;
cur.next = secondnode; // 步骤一
secondnode.next = firstnode; // 步骤二
firstnode.next = temp; // 步骤三
cur = firstnode; // cur移动,准备下一轮交换
}
return dumyhead.next;
}
}
19.删除链表的倒数第N个节点
思路:
- 快慢指针
解题方法:
定义快慢指针,当快指针距离慢指针n个节点长度后二者同时移动,直至快指针的next为null就结束;此时slowNode就是待删除节点的前一个节点,把slowNode.next指向slowNode.next.next的节点即完成删除。
复杂度
时间复杂度: O(n)
空间复杂度: O(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 removeNthFromEnd(ListNode head, int n) {
ListNode dummy =new ListNode(0) ;
ListNode fast;
ListNode slow;
dummy.next= head;
fast= dummy;
slow = dummy;
//fast走了n+1步
for (int i=0;i<=n;i++){
fast = fast.next;
}
while (fast!=null){
slow=slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
面试题 02.07. 链表相交
方法:
末尾对齐,判断两个指针是否相等(不是值)
复杂度
时间复杂度:O(n + m)
空间复杂度:O(1)
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0, lenB = 0;
while (curA != null) { // 求链表A的长度
lenA++;
curA = curA.next;
}
while (curB != null) { // 求链表B的长度
lenB++;
curB = curB.next;
}
curA = headA;
curB = headB;
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
//1. swap (lenA, lenB);
int tmpLen = lenA;
lenA = lenB;
lenB = tmpLen;
//2. swap (curA, curB);
ListNode tmpNode = curA;
curA = curB;
curB = tmpNode;
}
// 求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap-- > 0) {
curA = curA.next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != null) {
if (curA == curB) {
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
142.环形链表II
思路
快慢指针
解决方法
- 判断链表是否环
- 如果有环,如何找到这个环的入口
复杂度
- 时间复杂度: O(n),快慢指针相遇前,指针走的次数小于链表长度,快慢指针相遇后,两个index指针走的次数也小于链表长度,总体为走的次数小于 2n
- 空间复杂度: O(1)
代码
/**
* 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) {
ListNode fast = head;
ListNode slow = head;
while (fast!=null &&fast.next!= null){//考虑空链表情况
fast = fast.next.next;
slow = slow.next;
if (fast == slow){//判断是==
ListNode index1 =head;
ListNode index2 = slow;
while(index1 != index2){//之前用的if ,只判断了一次,不合理,所以用while
index1 = index1.next;
index2 = index2.next;}
return index1;
}
}
return null;
}
}