刷刷笔试题--[链表类编程]

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;
    }
}










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值