代码随想录算法训练营第4天
今日任务
● 24. 两两交换链表中的节点 ● 19.删除链表的倒数第N个节点 ● 面试题 02.07. 链表相交 ● 142.环形链表II ● 总结
链接:https://docs.qq.com/doc/DUFNjYUxYRHRVWklp (opens in a new tab)
24. 两两交换链表中的节点
自己想法
/**
* 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) {
ListNode dummy = new ListNode(-1,head);
ListNode cur = dummy.next;
ListNode pre = dummy;
ListNode swap = null;
if (head == null || head.next == null) {
// 链表为空或只有一个元素,直接返回
return head;
}
else {
while (cur != null && cur.next != null) {
// 当前还剩至少2个节点,需要交换
swap = cur.next;
cur.next = swap.next;
swap.next = cur;
pre.next = swap;
pre = cur;
cur = cur.next;
}
return dummy.next;
}
}
}题解想法
无
困难
无
回顾
无
19.删除链表的倒数第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) {
ListNode dummy = new ListNode(-1,head);
ListNode pre_delay = dummy;
ListNode cur_delay = dummy.next;
ListNode pre = dummy;
ListNode cur = dummy.next;
int delay = 1;
if (head == null || head.next == null) {
return null;
}
while (cur != null) {
if (delay <= n) {
delay ++;
}
else {
pre_delay = cur_delay;
cur_delay = cur_delay.next;
}
pre = cur;
cur = cur.next;
}
System.out.println(pre_delay.val);
pre_delay.next = cur_delay.next;
return dummy.next;
}
}题解想法
无
困难
无
回顾
通过维护两个延迟节点pre_delay与cur_delay,实现一次遍历。
面试题 02.07. 链表相交
自己想法
/**
* 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 len_a = getLength(headA);
int len_b = getLength(headB);
ListNode long_list = null;
ListNode short_list = null;
ListNode long_cur = null;
ListNode short_cur = null;
int diff = 0;
if (len_a > len_b) {
long_list = headA;
short_list = headB;
long_cur = headA;
short_cur = headB;
diff = len_a - len_b;
}
else {
long_list = headB;
short_list = headA;
long_cur = headB;
short_cur = headA;
diff = len_b - len_a;
}
for (int i = 0; i < diff; i++) {
long_cur = long_cur.next;
}
while (long_cur != null) {
if (long_cur != short_cur) {
long_cur = long_cur.next;
short_cur = short_cur.next;
}
else {
return long_cur;
}
}
return null;
}
public int getLength(ListNode head) {
int length = 0;
ListNode cur = head;
while (cur != null) {
cur = cur.next;
length ++;
}
return length;
}
}题解想法
无
困难
无
回顾
找出长度后,长的链表先走diff步,然后两个链表同时走,直到相遇。
142.环形链表II
自己想法
无
题解想法
方法一:哈希表
遍历链表中的每个节点,并将它记录下来;一旦遇到了此前遍历过的节点,就可以判定链表中存在环。
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode cur = head;
Set<ListNode> past = new HashSet<ListNode>();
while (cur != null) {
if (past.contains(cur))
return cur;
else
past.add(cur);
cur = cur.next;
}
return null;
}
}方法二:快慢指针
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) { // 有环
ListNode cur = head;
while (cur != slow) {
// 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
cur = cur.next;
slow = slow.next;
}
return cur;
}
}
return null;
}
}困难
只能想到O(n^2)的暴力法。
回顾
-
java哈希表:
Set<ListNode> past = new HashSet<ListNode>();,操作:past.contains(),past.add()。 -
快慢指针:自行推理几个问题。为什么一定相遇、为什么相遇后,再从头结点开始走,两个指针一定会在环入口相遇。