1.链表中环的入口结点
【题目】
链表中环的入口结点给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出 null。
【代码】
package swear2offer.linkednode;
public class Loop {
/**
* 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出 null。
*
* 思路:
* 快慢指针,快指针一次走两个,慢指针一次走一个,
* 二者最开始从起点走,然后在A点相遇,A点是在环内
* 然后让其中一个指针从起点重新出发,另一个在A点出发
* 二者每次都是走一步,二者再次相遇的地点就是环的入口点
*
* 特殊情况:
* 起点就是入口节点
* 没有环的情况
* 注意:漏掉了节点只有一个元素的情况,此时head.next.next是报异常的
* */
public ListNode EntryNodeOfLoop(ListNode pHead) {
if (pHead == null) return null;
if (pHead.next == null) return null;
ListNode slow,fast;
slow = fast = pHead;
slow = slow.next;
fast = fast.next.next;
while (slow != fast && slow !=null && fast != null) {
slow = slow.next;
fast = fast.next.next;
}
// 不存在环
if (slow != fast) return null;
slow = pHead;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
* 思路:
* 快慢指针,快指针一次走两个,慢指针一次走一个,
* 二者最开始从起点走,然后在A点相遇,A点是在环内
* 然后让其中一个指针从起点重新出发,另一个在A点出发
* 二者每次都是走一步,二者再次相遇的地点就是环的入口点
*
* 特殊情况:
* 起点就是入口节点
* 没有环的情况
* 注意:漏掉了节点只有一个元素的情况,此时head.next.next是报异常的
2.删除链表中重复的结点
【题目】
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5
【代码】
package swear2offer.linkednode;
public class DeDuplication {
/**
* 在一个排序的链表中,存在重复的结点,
* 请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
* 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5
*
* 三个指针,before,p,q
*
* 相等就移动后面的
* 不等就把后指针赋值给前指针,然后后指针向后移动一位
* 跳出:后指针为空
* 边界处理:无元素,只有一个元素,只有两个元素
*
*
* 上述情况思考不完整,推到重建
*
* 1.并不需要三个指针,因为判断重复指针,只需要一个指针和自身的next判断即可
* 2.循环嵌套,一个循环最好是负责一个功能,
* 内循环负责遍历重复,外循环负责移动两个节点
* 当两者用同一个循环的时候,功能可能不完整
* 3.一个很棘手的问题:当头结点重复的时候,删除头结点。
* 头结点是重复情况,需要返回其他节点,不在返回头节点
* 解决:借助辅助头结点,可避免单独讨论头结点的情况。
* 注意,引入辅助头节点,需要从辅助头节点开始遍历,而不是从原有节点遍历
* 同时,返回的时候,也是返回辅助头节点的next而不是返回辅助头结点本身
* */
public ListNode deleteDuplication(ListNode pHead) {
// 只有一个元素或者无元素
if (pHead==null || pHead.next==null) return pHead;
ListNode head,pre,cur;
head = new ListNode(Integer.MIN_VALUE);// 辅助头节点
head.next = pHead;
pre = pHead;
cur = pre.next;
if (cur.val == pre.val) {
return null;
}
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 = cur.next;
pre.next = cur;
} else {
pre = cur;
cur = cur.next;
}
}
return head.next;
}
/**
* 在一个排序的链表中,存在重复的结点,
* 请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
* 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5
*
* 三个指针,before,p,q
*
* 相等就移动后面的
* 不等就把后指针赋值给前指针,然后后指针向后移动一位
* 跳出:后指针为空
* 边界处理:无元素,只有一个元素,只有两个元素
*
*
* 上述情况思考不完整,推到重建
*
* 1.并不需要三个指针,因为判断重复指针,只需要一个指针和自身的next判断即可
* 2.循环嵌套,一个循环最好是负责一个功能,
* 内循环负责遍历重复,外循环负责移动两个节点
* 当两者用同一个循环的时候,功能可能不完整
* 3.一个很棘手的问题:当头结点重复的时候,删除头结点。
* 头结点是重复情况,需要返回其他节点,不在返回头节点
* 解决:借助辅助头结点,可避免单独讨论头结点的情况。
* 注意,引入辅助头节点,需要从辅助头节点开始遍历,而不是从原有节点遍历
* 同时,返回的时候,也是返回辅助头节点的next而不是返回辅助头结点本身
* */