LeetCode 24 两两交换链表中的节点
题目链接:. - 力扣(LeetCode)
思路解析:
在这道题里,最简单的方法还是需要用到之前所说的虚拟头节点的概念,因为在执行交换操作时需要涉及到四个节点,即前中后和下一个阶段的前节点。例如如果有一个五个节点的链表,
1 | 2 | 3 | 4 | 5 |
那么,在执行时对于头节点来说缺少它的前节点,因此如果不使用虚拟头节点则需要单独讨论。如果使用虚拟头节点dummyHead,每次的执行顺序就是dummyHead指向2,2指向1,1指向3(即下一个操作的第一个节点),然后以此类推。注意在执行时需要用到临时变量存储节点的值,因为在改变指向的过程中其实也是在执行删除节点的操作。
/**
* 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 dummyhead = new ListNode();
dummyhead.next = head;
ListNode point;
point = dummyhead;
ListNode firstnode;
ListNode secondnode;
ListNode nextlevel;
while (point.next != null && point.next.next != null){
firstnode = point.next;
secondnode = point.next.next;
nextlevel = point.next.next.next;
point.next = secondnode;
secondnode.next = firstnode;
firstnode.next = nextlevel;
point = firstnode;
}
return dummyhead.next;
}
}
LeetCode 19 删除链表的倒数第n个节点
题目链接:. - 力扣(LeetCode)
思路解析:
在刚开始看的时候我的想法就是单纯的遍历出长度再解题。但解析的思路要比我的简单很多。简单的思路就是使用双指针,一快一慢,只需要让快的走n+1(n是题目给的倒数第n个节点),然后再让快慢指针同时同速走,当快指针走到null时,慢指针就到了需要删除节点的前一个节点。(注意,快指针不是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 dummyhead = new ListNode();
dummyhead.next = head;
ListNode fast;
ListNode slow;
fast = dummyhead;
slow = dummyhead;
for (int i=0; i<=n; i++){
fast = fast.next;
}
while(fast != null){
fast = fast.next;
slow = slow.next;
}
slow.next=slow.next.next;
return dummyhead.next;
}
}
LeetCode 面试 02.07 链表相交
题目链接:. - 力扣(LeetCode)
思路解析:
这道题我也是看了解析思路才做出来。我开始想到了虽然交点前两个链表的节点数肯定不相同,所以可以从两个链表末尾到交点这段相同的距离找思路,但是没进行下去。这道题只需要把两个链表以尾节点对其,然后从将两个链表的指针都停在短链表的第一个节点位置,一直循环直到两个指针相同即可。
/**
* 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 lengtha=0;
int lengthb=0;
ListNode pointa = headA;
ListNode pointb = headB;
while (pointa != null){
lengtha++;
pointa = pointa.next;
}
while (pointb != null){
lengthb++;
pointb = pointb.next;
}
pointa = headA;
pointb = headB;
int dif = Math.abs(lengtha-lengthb);
if (lengtha >= lengthb){
for (int i=0; i<dif; i++){
pointa = pointa.next;
}
while (pointa != pointb){
pointa = pointa.next;
pointb = pointb.next;
}
return pointa;
}else
{
for (int i=0; i<dif; i++){
pointb = pointb.next;
}
while (pointa != pointb){
pointa = pointa.next;
pointb = pointb.next;
}
return pointa;
}
}
}
LeetCode 142 环形链表
题目链接:. - 力扣(LeetCode)
思路解析:
首先这道题是依靠快慢指针的相遇来判断链表是否存在环,但是如何找到入口处需要明白几个点。快慢指针在环里相遇后慢指针一定走不完一圈;而快指针一定走完至少一圈。(解释:因为,首先快指针的速度设置为2,慢指针的速度设置为1,当慢指针入环后,快慢指针之间距离一定小于环的长度,且快慢的速度差其实就是慢指针的速度,那么追上慢指针的时间一定小于慢指针走完整个环的时间;其次,如果快指针没有走完一整个圈,那么因为快慢指针在环里是同向移动的,快指针遇到慢指针意味着追上了慢指针,那么快指针如果没走完一个圈,意味着慢指针先入了环,因此矛盾。)
当明白以上几点后,我们就可以推导出公式,设x为头节点与入口处的路程,y为入口处和相遇点的路程,y为相遇点到入口处的路程,那么x+y为慢指针所走的全程,x+y+n(y+z)为快指针走的全程,其中n(y+z)代表的是n圈。那么快指针为慢指针的两倍可以列出来一个方程,解出来,当n=1时,x=z,那么意味着如果在相遇点和头节点分别放置两个节点,同速同时出发,一定会在入口处相遇。因此,通过这样我们就可以判断是否有环且有环时得到入口处的节点。
我的shi山代码
/**
* 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) {
if (head.next != null && head.next.next != null){
ListNode fast=head.next.next;
ListNode slow=head.next;
while (fast != slow && fast != null){
fast=fast.next.next;
slow=slow.next;
}
if (fast == null ){
return null;
}
ListNode cur1=head;
ListNode cur2=fast;
while (cur1 != cur2){
cur1 = cur1.next;
cur2 = cur2.next;
}
return cur1;
}else{
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 index1 = fast;
ListNode index2 = head;
// 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
while (index1 != index2) {
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}