1.链表中环的入口结点
一个链表中包含环,请找出该链表的环的入口结点。
解析:
一、两个指针p1和p2,p1每次走1步,p2每次走2步,它们俩一定会在环内的某一处相遇,
假设p1走了x步,那么p2就走了2x步
p2刚好比p1多走了一个环的距离才又赶上p1
环的长度n=2x-x=x
p1其实在环外走了x1步,又在环内走了x-x1步,[还差n-(x-x1)=x1步就走到了入口]
二、现在把p2放回表头,让它们俩同时一起一步一步走,p2走x1步走到入口,p1走x1步也走到入口
不用单独求x1是什么,只需要把p2放在表头,然后让他们移动,相遇的地方就是入口!!
【不明白的时候画一个图】
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if(pHead==null||pHead.next==null)//这步一定不要少
return null;
ListNode p1=pHead;
ListNode p2=pHead;
while(p2!=null&&p2.next!=null){//要一直循环到两个指针相遇,有可能链表里面没有环,p2走得快,用他控制一下!!
p1=p1.next;
p2=p2.next.next;
if(p1==p2){
p2=pHead;
while(p1!=p2){
p1=p1.next;
p2=p2.next;
}
if(p1==p2)
return p1;
}
}
return null;
}
}
第二种方法:
用hashmap记录节点,ListNode-boolean类型的,如果没有这个节点就放进去,并放一个true,当发现这个节点已经有过了,containsKey()
就说明这个节点是入口
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
import java.util.*;
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
HashMap<ListNode,Boolean> map=new HashMap<ListNode,Boolean>();
while(pHead!=null){
if(map.containsKey(pHead))
return pHead;
map.put(pHead,true);
pHead=pHead.next;
}
return null;
}
}
2.删除链表中重复的结点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
解析:
这里是用递归解决的
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode deleteDuplication(ListNode pHead)
{
if(pHead==null)
return null;
if(pHead.next==null&&pHead!=null)
return pHead;//前面两部分也可以直接换成if(pHead==null||pHead.next==null)return pHead;
ListNode cur=pHead;
if(pHead.val==pHead.next.val){
cur=pHead.next.next;
while(cur!=null&&cur.val==pHead.val){//!!注意!!cur!=null一定要写在前面!!&&这个东西很艮的,只看前面,如果前面的条件不成立,直接不看后面的
cur=cur.next;
}
return deleteDuplication(cur);
}else{
cur=pHead.next;
pHead.next=deleteDuplication(cur);
return pHead;
}
}
}
3. [编程题]两个链表的第一个公共结点
输入两个链表,找出它们的第一个公共结点。
解析:
先求出两个链表的长度,长的为m,短的为n,让长的先走m-n步,然后两个人一起走,时刻比较此时节点是否相等,相等返回其中一个节点就行
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
int len1=len(pHead1);
int len2=len(pHead2);
if(len1>len2){
pHead1=walk(pHead1,len1-len2);
}else{
pHead2=walk(pHead2,len2-len1);
}
while(pHead1!=null){
if(pHead1==pHead2)
return pHead1;
pHead1=pHead1.next;
pHead2=pHead2.next;
}
return null;
}
public int len(ListNode node){
int count=0;
if(node==null)
return count;
while(node!=null){
node=node.next;
count++;
}
return count;
}
public ListNode walk(ListNode node,int step){
while(step>0){
node=node.next;
step--;
}
return node;
}
}