单链表题目
第七题删除重复的节点
题目大意是一个单链表中存在重复的节点,我们需要将重复的节点删除
样例:
看到这个样例我们知道,删除重复的节点之后,会生成一个新的链表,所以我们需要重新定义一个链表
我们可以看着图片来演示这个过程,具体思路就是两个节点,一个节点存的就是要删除的那个节点的前驱,另一个节点就是要删除的节点。
public class Solution {
public ListNode deleteDuplication(ListNode pHead) {
ListNode cur = pHead;
ListNode newHead = new ListNode(-1);
ListNode tmp = newHead;
while(cur != null) {
if(cur.next != null && cur.val == cur.next.val) {
while(cur.next != null && cur.val == cur.next.val) {
cur = cur.next;
}
cur = cur.next;
}else {
tmp.next = cur;
cur = cur.next;
tmp = tmp.next;
}
}
tmp.next = null;
return newHead.next;
}
}
太多的细节要考虑了,只有当自己真正的自己演示一遍,才有可能搞懂。
第八题判断链表的回文
判断链表的回文
这题主要思路就是首先找到链表的中间节点,然后让中间节点的后面,都指向前面,一个从前往中间走,一个从后往中间走,如果都一样说明就是回文链表。
1.找到中间节点
2.实现逆置
3.判断是否回文
继续看上面的那个图片
如果链表是奇数的情况就不用说了,但是偶数我们来需要画图来演示
我们再移动的过程中可以发现,如果是偶数的情况下head.next = slow
public class PalindromeList {
public boolean chkPalindrome(ListNode A) {
// write code here
if(A == null) {
return true;
}
ListNode fast = A;
ListNode slow = A;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;//找到中间节点
}
ListNode cur = slow.next;
while(cur != null) {
ListNode curNext = cur.next;
cur.next = slow;
slow = cur;
cur = curNext;//实现逆置
}
while(A != slow) {
if(A.val != slow.val) {
return false;
}
if(A.next == slow) {
return true;
}
A = A.next;
slow = slow.next;
}//判断是否回文
return true;
}
}
第九题找到公共节点
看到这个问题我们应该想到两个地方,
1.这是个Y型,的还是X型的
2.公共节点是值一样,还是地址一样
从这个图中我们可以看到这是一个Y型的,并且相交的是地址,我们可以看到那个注意保持其原始结构
具体思路是先求出长的链表,比短的多几个长度,然后长的链表走这个长度
1.先求链表A的长度
2.求链表B的长度
3.求出长度差
4.之后继续走判断是否有地址相等的位置
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode pl = headA;
ListNode ps = headB;
int lenA = 0;
int lenB = 0;
while(pl != null) {
pl = pl.next;
lenA ++;//找到A的长度
}
pl = headA;
while(ps != null) {
ps = ps.next;
lenB ++;//找到B的长度
}
ps = headB;
int len = lenA - lenB;
if(len < 0) {
pl = headB;
ps = headA;
len = lenB - lenA;//找到长度差
}
while(len != 0) {
pl = pl.next;
len --;
}
while(pl != ps) {
pl = pl.next;//最后判断是否相等
ps = ps.next;
}
return pl;
}
}
第十题判断链表是否有环
判断链表是否有环
这里有个很形象的比喻,就像我们在操场上跑步的场景,如果有环,跑的快的一定可以追上跑的慢的。
我们让其中一个的速度,是另一个速度的2倍。
这里为什么不是3倍呢?
我们看这样一种情况:
这样的话,速度是3倍是不是永远都满足不了。
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if(fast == slow) {
return true;
}
}
return false;
}
}
第十一题找到链表开始如环的第一个节点
找到链表开始如环的第一个节点
还是想到操场的情况,为什么会相遇,只能说明路程是另一个路程的2倍
之间的关系为:
化简后可以得到:
到这里有人问了,你这是只多跑了一圈,后面还有可能多跑了很多圈,其实仔细想想就知道,跑了很多圈只能说明C小,公式还是一样的的。
具体步骤:
1.找到相遇点
2.找到环的节点
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if(fast == slow) {
break;
}
}
if(fast == null || fast.next == null) {
return null;
}
fast = head;
while(fast != slow) {
fast = fast.next;
slow = slow.next;
}
return fast;
}
}
本篇文章接上篇文章上篇文章的网址