1、删除链表中重复的结点
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
方法1:
public class Linked {
public static void main(String[] args) {
ListNode pHead = new ListNode(1);
ListNode nodeh = pHead;
ListNode index = new ListNode(1);
nodeh.next = index;
nodeh = index;
index = new ListNode(2);
nodeh.next = index;
Linked s = new Linked();
ListNode list = s.deleteDuplication(null);
System.out.println("list");
while(list != null) {
System.out.print(list.val + " ");
list = list.next;
}
}
private ListNode deleteDuplication(ListNode pHead) {
if(pHead == null) return pHead;
//创建一个节点,防止头节点被删除
ListNode pre_head = new ListNode(-1);
pre_head.next = pHead;
//指向前一个节点
ListNode pre = pre_head;
ListNode cur = pHead;
while(cur != null && cur.next != null) { //注意条件的顺序,否则不对,因为如果p为null,p.next肯定异常
if(cur.val == cur.next.val) {
int val = cur.val;
//向后重复查找
while(cur != null && val == cur.val) {
cur = cur.next;
}
//上个非重复值指向下一个非重复值:即删除重复值。
pre.next = cur;
} else {
//如果当前节点和下一个节点值不等,则向后移动一位
pre = cur;
cur = cur.next;
}
}
return pre_head.next;
}
}
方法2 (三指针法):
采用三个指针来进行遍历,同时删除重复的节点,因为是有序的链表,我们就可以确定,重复的元素肯定是在一块链接,所以我们就可以,用三指针,我们这里就叫pre、cur、nex 分别代表的是前中后三个指针,我们在考虑的情况中,如果头节点开始就重复,我们就处理很起来多了一种情况就需要额外处理,所以我们添加一个头节点,变成带头节点,保证了头节点开始不会重复,那么我们就可以开是让pre指向带头的节点,cur指向pre的next,nex指向cur的next。
接下来我们就可以看cur是否和nex相等,相等就让nex继续向下走,不相等然后再处理删除,cur开始到nex中间节点都是要删除的(包含cur指向,不包含nex指向)删除,就用到了pre,删除完成让pre指向cur就可以了。
如果cur值与nex值不相等,那么就可以三个指针各自往前移动一个。
import java.util.ArrayList;
import java.util.HashSet;
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public class Solution {
public static void main(String[] args) {
ListNode pHead = new ListNode(1);
ListNode nodeh = pHead;
ListNode index = new ListNode(1);
nodeh.next = index;
nodeh = index;
index = new ListNode(1);
nodeh.next = index;
Solution s = new Solution();
ListNode list = s.deleteDuplication(pHead);
while(list != null) {
System.out.print(list.val + " ");
list = list.next;
}
}
public ListNode deleteDuplication(ListNode pHead){
if(pHead == null || pHead.next == null) {
return pHead;
}
ListNode pre = new ListNode(0);
pre.next = pHead;
ListNode pre_head = pre;
ListNode cur = pHead;
ListNode nex = pHead.next;
while(nex != null) {
while(nex != null && cur.val == nex.val) {
nex = nex.next;
}
if(cur.next != nex) {
while(cur != nex) {
pre.next = cur.next;
cur = cur.next;
}
if(nex != null) {
nex = nex.next;
}
} else {
pre = cur;
cur = nex;
nex = nex.next;
}
}
pre_head = pre_head.next;
return pre_head;
}
}
2、链表中环的入口节点
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路:
第一步,找环中相汇点。分别用p1,p2指向链表头部,
- p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。
通过141题,我们知道可以通过快慢指针来判断是否有环,现在我们假设两个指针相遇在z点,如图
那么我们可以知道fast指针走过a+b+c+b
slow指针走过a+b
那么2*(a+b) = a+b+c+b
所以a = c
那么此时让slow回到起点,fast依然停在z,两个同时开始走,一次走一步
那么它们最终会相遇在y点,正是环的起始点
public class Huan {
public ListNode EntryNodeOfLoop(ListNode pHead) {
if(pHead == null || pHead.next == null) {
return pHead;
}
ListNode slow = pHead;
ListNode fast = pHead;
while(slow != null && fast != null) {
slow = slow.next;
fast = fast.next.next;
if(slow == fast) {
slow = pHead;
while(slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
return null;
}
}
2、两个链表的第一个公共结点
题目描述
输入两个链表,找出它们的第一个公共结点
public class PublicNode {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if(pHead1 == null || pHead2 == null) return null;
ListNode c1 = pHead1;
ListNode c2 = pHead2;
int n = 0;
while(c1 != null) {
n++;
c1 = c1.next;
}
while(c2 != null) {
n --;
c2 =c2.next;
}
if(c1 != c2) {
return null;
}
c1 = n > 0?pHead1:pHead2;
c2 = c1==pHead1?pHead2:pHead1;
n = Math.abs(n);
while(n != 0) {
n --;
c1 = c1.next;
}
while(c1 != c2) {
c1 = c1.next;
c2 = c2.next;
}
return c1;
}
}
3、复杂链表的复制
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
import java.util.HashMap;
class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
public class CopyListWithRand1 {
public RandomListNode copyListWithRand1(RandomListNode head) {
HashMap<RandomListNode,RandomListNode> map = new HashMap<RandomListNode,RandomListNode>();
RandomListNode cur = head;
while(cur != null) {
map.put(cur,new RandomListNode(cur.label));
cur = cur.next;
}
cur = head;
while(cur != null) {
map.get(cur).next = map.get(cur.next);
map.get(cur).random = map.get(cur.random);
cur = cur.next;
}
return map.get(head);
}
}