面试经典150题(50-53)

leetcode 150道题 计划花两个月时候刷完,今天(第二十二天)完成了4道(50-53)150:

50.(141. 环形链表)题目描述:

给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false

第一版(这个是经典的题目,快慢指针就可以,如果有环他们肯定会相遇,没环一定会到 null )

public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode low=head;
        ListNode fast=head;
        while(fast!=null&&low!=null){
            low=low.next;
            if(fast.next==null){
                return false;
            }
            fast=fast.next.next;
            if(low==fast){
                return true;
            }
        }
        return false;
    }
}

第二版(我总感觉我对这个起始的指针处理不好,就看了一下解题,他是反着去判断了,也可以学习一下)

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head==null||head.next==null){
            return false;
        }
        ListNode low=head;
        ListNode fast=head.next;
        while(low!=fast){
           if(fast==null||fast.next==null){
               return false;
           }
            fast=fast.next.next;
            low=low.next;
        }
        return true;
    }
}

51.(2. 两数相加)题目描述:

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

第一版(这个题我第一反应以为他第一个指针是最大位数。。看了好久才读懂了题目。。但是这个题目处理的应该是一个模板,就是 3个while 的模板。。一般就是处理长度不一样的情况下我感觉都是3个while。。)

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
       ListNode res=new ListNode(0);
       ListNode resTemp=res;
       int add=0;
       while(l1!=null&&l2!=null){
           int num=l1.val+l2.val+add;
           add=num/10;
           num%=10;
            resTemp.next=new ListNode(num);
            resTemp=resTemp.next;
            l1=l1.next;
            l2=l2.next;
       }
       while(l1!=null){
           int num=l1.val+add;
           add=num/10;
           num%=10;
            resTemp.next=new ListNode(num);
            resTemp=resTemp.next;
            l1=l1.next;
       }
       while(l2!=null){
           int num=l2.val+add;
           add=num/10;
           num%=10;
            resTemp.next=new ListNode(num);
            resTemp=resTemp.next;
            l2=l2.next;
       }
       if(add!=0){
            resTemp.next=new ListNode(add);
            resTemp=resTemp.next;
       }
       return res.next;

    }
}

52.(21. 合并两个有序链表)题目描述:

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

第一版(这个也是我上面说的长度不一样要一起处理的 3个while模板,只不过这个是链表,你只需要指定了头后面也会跟着这个头,所以这块就是 一个 while 两个 if)

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode res=new ListNode(0);
        ListNode resTemp=res;
        while(list1!=null&&list2!=null){
            if(list1.val<list2.val){
                resTemp.next=new ListNode(list1.val);
                list1=list1.next;
            }else{
                 resTemp.next=new ListNode(list2.val);
                list2=list2.next;
            }
            resTemp=resTemp.next;
        }
        if(list1!=null){
            resTemp.next=list1;
        }
        if(list2!=null){
            resTemp.next=list2;
        }
        return res.next;
    }
}

53.(138. 随机链表的复制) 题目描述:

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为  null 。
你的代码 只 接受原链表的头节点 head 作为传入参数。

第一版(这个题比较长,意思就是每个节点都要新建,我第一次写了好久,但是写出来还是一坨。。)

class Solution {
    public Node copyRandomList(Node head) {
        Node res=new Node(0);
        Node resTemp=res;
        Node headTemp=head;
        Map<Node,Integer> nodeMap=new HashMap();
        int index=0;
        while(headTemp!=null){
            resTemp.next=new Node(headTemp.val);
            nodeMap.put(headTemp,index++);
            headTemp=headTemp.next;
            resTemp=resTemp.next;
        }
        Map<Integer,Integer> indexMap=new HashMap();
        for (Map.Entry<Node, Integer> entry : nodeMap.entrySet()) {
            if(entry.getKey().random==null){
                indexMap.put(entry.getValue(),-1);
            }
            else
                indexMap.put(entry.getValue(),nodeMap.get(entry.getKey().random));
        }
        // 复制 random 开始
        resTemp=res.next;
        Node temp=res.next;
        index=0;
        while(resTemp!=null){
            temp=res.next;
            if(indexMap.get(index)!=-1){
                for(int i=0;i<indexMap.get(index);i++){
                    temp=temp.next;
                }
                resTemp.random=temp;
            }
            index++;
            resTemp=resTemp.next;
        }
        return res.next;
    }
}

第二版(看了解题,真的这个思想很好,把每个节点单独出来,一个一个来赋值他的 next和 random)

class Solution {
    
    public Node copyRandomList(Node head) {
        if(head==null){
            return null;
        }
        Map<Node, Node> nodeMap = new HashMap<Node, Node>();
        Node headTemp=head;
        while(headTemp!=null){
            nodeMap.put(headTemp,new Node(headTemp.val));
            headTemp=headTemp.next;
        }
        headTemp=head;
        while(headTemp!=null){
            Node nodeNew=nodeMap.get(headTemp);
            if(headTemp.next!=null){
                nodeNew.next=nodeMap.get(headTemp.next);
            }
            if(headTemp.random!=null){
                nodeNew.random=nodeMap.get(headTemp.random);
            }
            headTemp=headTemp.next;
        }
        return nodeMap.get(head);
    }
}

昨天又鸽了一天。。不知道为啥昨天啥都不想干。。昨天把yys也删了,超鬼王真的肝不动了。。

加油,第二十二天了,早日跳槽!!!

你可能感兴趣的:(面试经典,150,题,面试,算法,职场和发展,数据结构)