LeetCode刷题笔记

23. Merge k Sorted Lists

要点:

1. 学会数据结构PriorityQueue(优先队列)的用法, 通过给优先队列传入自定义的经过复写compare方法的比较器实现大根堆或者小根堆。

2. PriorityQueue中不能存放null值,所以每次更新优先队列都需要作判空检查,如遇null值直接剔除。 

 

 1 import java.util.Comparator;
 2 import java.util.PriorityQueue;
 3 
 4 class Solution {
 5     public ListNode mergeKLists(ListNode[] lists) {
 6         //要点1
 7         PriorityQueue<ListNode> nodesQueue = new PriorityQueue<>(new Comparator<ListNode>() {
 8             @Override
 9             //将compare方法重写为比较ListNode的val值大小
10             public int compare(ListNode o1, ListNode o2) {
11                 return o1.val-o2.val;
12             }
13         });
14 
15         ListNode head = new ListNode(0);
16         for(ListNode node:lists)
17             if(node!=null)
18                 nodesQueue.add(node);
19 
20         ListNode p = head;
21         while(!nodesQueue.isEmpty()){
22             //判空检查,如果ListNode的下一个Node是null,则取出该Node后不再将其下一个节点放回优先队列。
23             if(nodesQueue.peek().next==null){
24                 p.next = new ListNode(nodesQueue.poll().val);
25                 p = p.next;
26             }else{
27                 ListNode tmp = nodesQueue.poll();
28                 p.next = new ListNode(tmp.val);
29                 p = p.next;
30                 nodesQueue.add(tmp.next);
31             }
32         }
33         return head.next;
34     }
35 
36 }

29. Divide Two Integers

class Solution {
    //用dividend循环减去diviso并计数减了多少次,这种方法会tle
    public static int divide(int dividend, int divisor) {
        //处理两种溢出情况
        if(dividend == -2147483648){
            if(divisor == 1)
                return -2147483648;
            if(divisor == -1)
                return 2147483647;
        }
        /**
           32位整数的取值范围是-2147483648~+2147483647
           将两个数都转为负数,以处理最大溢出-2147483648
        */
        
        //保存符号
        int flag = 1;
        if((dividend>0&&divisor<0)||(dividend<0&&divisor>0))
            flag = -1;
        //都转为负数
        dividend = dividend>0?-dividend:dividend;
        divisor = divisor>0?-divisor:divisor;
        int res = 0;
        if(dividend>divisor)
            return 0;
        //开始循环取商
        while(dividend<0){
            int k = 1;
            //divisor_tmp是变量,只要比dividend小就每次加倍,同时k作为商的计数也加倍
            int divisor_tmp = divisor;
            int tmp=0;
            while(dividend<divisor_tmp){
                tmp = divisor_tmp;
                //divisor_tmp在加倍的过程中有可能溢出,需要处理
                if(divisor_tmp+divisor_tmp>0||divisor_tmp+divisor_tmp==-2147483648)
                    break;
                divisor_tmp += divisor_tmp;
                k += k;
            }
            //如果跳出加倍循环后,dividend比divisor_tmp大,说明divisor_tmp加倍超过了dividend,需要撤销上一次的加倍
            if(dividend>divisor_tmp){
                divisor_tmp -= tmp;
                k>>=1;
            }
            //从divideng减去divisor_tmp并保存加倍值
            dividend -= divisor_tmp;
            res += k;
        }
        return res*flag;
    }

}

32. Longest Valid Parentheses

连同下面的解释,参考自 https://www.acwing.com/solution/LeetCode/content/114/

算法

(双指针扫描、贪心) O(n)O(n)
假设当前从前到后统计合法括号子串,令(的权值为1,)的权值为-1。首先记录start为某个起点,则在i向后移动的过程中,若当前[start,i]区间和等于0,该字符串是合法的;若区间和大于0,则说明目前缺少右括号,可以不修改start;若区间和小于0,则说明区间已经不合法了,需要修正start为i+1。初始时start从0开始即可。
可是对于…((((合法)(((这种情况,以上算法不能够准确捕捉到最长的合法子串,此时我们逆向考虑,将以上过程反向,从后向前统计,即可处理所有的情况。

时间复杂度

两次线性扫描,故时间复杂度为O(n)O(n)。

class Solution {
    public int longestValidParentheses(String s) {
       char[] chars = s.toCharArray();
        int[] marks = new int[chars.length];
        for(int i=0; i<chars.length;i++)
            marks[i] = chars[i]=='('?1:-1;

        int pr = 0;
        int pl = 0;
        int distance = 0;
        int tmp = 0;
        while(pr<marks.length){
            tmp+=marks[pr];
            if(tmp<0){
                tmp = 0;
                pl = pr+1;
            }
            if(tmp == 0)
                distance = pr-pl+1>distance?pr-pl+1:distance;
            pr++;
        }

        pr = marks.length-1;
        pl = pr;
        tmp = 0;
        while(pl>=0){
            tmp += marks[pl] ;
            if(tmp>0) {
                tmp = 0;
                pr = pl-1;
            }
            if(tmp == 0)
                distance = pr-pl+1>distance?pr-pl+1:distance;

            pl--;
        }
        return distance;
    }
}

 两道并查集

547. Friend Circles

 

全部评论

相关推荐

自由水:这HR已经很好了,多的是已读不回和不读了
点赞 评论 收藏
分享
03-15 14:55
已编辑
门头沟学院 golang
bg:双非学院本&nbsp;ACM银&nbsp;go选手timeline:3.1号开始暑期投递3.7号第二家公司离职顽岩科技&nbsp;ai服务中台方向&nbsp;笔试➕两轮面试,二面挂(钱真的好多😭)厦门纳克希科技&nbsp;搞AI的,一面OC猎豹移动&nbsp;搞AIGC方向&nbsp;一面OC北京七牛云&nbsp;搞AI接口方向&nbsp;一面OC上海古德猫宁&nbsp;搞AIGC方向&nbsp;二面OC上海简文&nbsp;面试撞了直接拒深圳图灵&nbsp;搞AIGC方向一面后无消息懒得问了,面试官当场反馈不错其他小厂没记,通过率80%,小厂杀手😂北京字节&nbsp;具体业务不方便透露也是AIGC后端方向2.28约面&nbsp;(不知道怎么捞的我,我也没在别的地方投过字节简历哇)3.6一面&nbsp;一小时&nbsp;半小时拷打简历(主要是AIGC部分)剩余半小时两个看代码猜结果(经典go问题)➕合并二叉树(秒a,但是造case造了10分钟哈哈)一天后约二面3.12&nbsp;二面,让我挑简历上两个亮点说,主要说的docker容器生命周期管理和raft协议使用二分法优化新任leader上任后与follower同步时间。跟面试官有共鸣,面试官还问我docker底层cpu隔离原理和是否知道虚拟显存。之后一道easy算法,(o1空间解决&nbsp;给定字符串含有{和}是否合法)秒a,之后进阶版如何用10台机加快构建,想五分钟后a出来。面试官以为45分钟面试时间,留了18分钟让我跟他随便聊,后面考了linux&nbsp;top和free的部分数据说什么意思(专业对口了只能说,但是当时没答很好)。因为当时手里有7牛云offer,跟面试官说能否快点面试,马上另外一家时间到了。10分钟后约hr面3.13,上午hr面,下午走完流程offer到手3.14腾讯技术运营约面,想直接拒😂感受:&nbsp;因为有AIGC经验所以特别受AI初创公司青睐,AIGC后端感觉竞争很小(指今年),全是简历拷打,基本没有人问我八股(八股吟唱被打断.jpeg),学的东西比较广的同时也能纵向深挖学习,也运气比较好了哈哈可能出于性格原因,没有走主流Java路线,也没有去主动跟着课写项目,项目都是自己研究和写的哈哈
烤点老白薯:你根本不是典型学院本的那种人,贵了你这能力
查看7道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务