• 以赛促练-力扣第311场周赛反思与总结



    这场周赛仍然是抱着学习的态度去的,手速场掉大分。有些题目看一眼有感觉,但是真的做上去,就会发现自己的掌握程度还没有达到随心应手。

    T1直接奇偶性判断秒过了。

    T2.6181.最长的字母序连续子字符串的长度

    先是尝试用滑动窗口做,结果直接TLE,代码如下,虽然可以值得优化(放在后面),但是下面这种做法理论上来说也能过,就是O(N)的时间复杂度。问题出就出在 System.out.println(c),这几个打印函数直接让我突破2s的限制,把它们去掉就能通过了。

    class Solution {
        public int longestContinuousSubstring(String s) {
            int len=s.length();
            int left=0;
            int res=0;
            Deque<Character> que=new ArrayDeque<>();
            for(int right=0;right<len;right++){
                char c=s.charAt(right);
                while(left<right&&!que.isEmpty()&&que.peekLast()-c!=-1){
                    left++;
                    System.out.println(left+" "+right);
                }
                que.offer(c);
                System.out.println(c);
                res=Math.max(res,right-left+1);
                
            }
            return res;
        }
    }
    

    此外,我们并不需要一个队列ArrayDeque来存储之前访问过的所有值,我们只需要在遍历一次的过程中,判断当前字母和前一个字母是否连续就行。

    class Solution {
        public int longestContinuousSubstring(String s) {
            int len=s.length();
            int left=0;
            int res=1;
            for(int right=1;right<len;right++){
                while(left<right&&s.charAt(right)-s.charAt(right-1)!=1){
                    left++;
                }
                res=Math.max(res,right-left+1);
                
            }
            return res;
        }
    }
    

    上面做法并不是最优,由于找连续最长的原因,left++这个逻辑可以直接改成left=right

    class Solution {
        public int longestContinuousSubstring(String s) {
            int len=s.length();
            int left=0;
            int res=1;
            for(int right=1;right<len;right++){
               if(s.charAt(right)-s.charAt(right-1)!=1){
                   //当不等的时候就将left移到当前位置,right还没变化
                    left=right;
                }
                //当排除了上面不满足条件的情况再算res,即使上一步left=right,算出来的也是1
                res=Math.max(res,right-left+1);
                
            }
            return res;
        }
    }
    
    T3.2415.反转二叉树的奇数层

    这题应该是层次遍历和递归都能做的, 但当时脑子短路加上确实对递归函数理解不透,因此没有做出来。先来试下我当时没写完的层次遍历模拟。当时觉得层序遍历是逐个节点加入队列的,没法去处理完整一层的情况,其实只需要在加入以后的下一层去处理就行了。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode() {}
     *     TreeNode(int val) { this.val = val; }
     *     TreeNode(int val, TreeNode left, TreeNode right) {
     *         this.val = val;
     *         this.left = left;
     *         this.right = right;
     *     }
     * }
     */
    class Solution {
        public TreeNode reverseOddLevels(TreeNode root) {
            int level=1;
            if(root==null) return null;
            Deque<TreeNode> que=new ArrayDeque<>();
            que.offer(root);
            while(!que.isEmpty()){
                int size=que.size();
                int[]arr=que.stream().mapToInt(x->x.val).toArray();
                for(int i=0;i<size;i++){
                    TreeNode top=que.poll();
    				//偶数层进行首尾交换
                    if(level%2==0){
                        top.val=arr[size-1-i];
                    }
                    if(top.left!=null) que.offer(top.left);
                    if(top.right!=null) que.offer(top.right);
                }
                level++;
            }
            return root;
        }
    }
    

    递归做法如下:
    和轴对称有关的递归。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode() {}
     *     TreeNode(int val) { this.val = val; }
     *     TreeNode(int val, TreeNode left, TreeNode right) {
     *         this.val = val;
     *         this.left = left;
     *         this.right = right;
     *     }
     * }
     */
    class Solution {
        public TreeNode reverseOddLevels(TreeNode root) {
            if(root==null) return null;
            dfs(root.left,root.right,2);
            return root;
        }
        public void dfs(TreeNode left,TreeNode right,int level){
            if(left==null) return ;
            if(level%2==0){
                int temp=right.val;
                right.val=left.val;
                left.val=temp;
            }
            dfs(left.left,right.right,level+1);
            dfs(left.right,right.left,level+1);
        }
    }
    
    T4.6183.字符串的前缀分数和

    关于字符串前缀问题,我的技能树中只能找到字典树,我写了一个专题讲字典树,引路->算法学习-字典树。这道题的每个答案是某个字符串所有子前缀的分数和。在建树的过程中,我们就可以在途径的节点上进行子前缀的次数记录。在查询一个单词所有子前缀的分数和时,其实就可以用判断是否是前缀的startWith逻辑,在查找的过程中就途径了它的所有子前缀,将它们的子前缀次数全部加起来,最终的结果就是该单词的前缀分数和。

    刚开始纠结的点是,如果p.next[c-‘a’]是相同字母怎么办,会把不是该前缀但是相同字母结尾的数字全部加上去吗?其实不是的,字典树的建立和父节点息息相关,根结点是唯一的,以后当且仅当前缀相同的时候,才会指向同一数据地址。

    class Solution {
        public class TireNode{
            //记录某一个前缀的分数
            int preValue;
            TireNode[] next=new TireNode[26];
        }
        TireNode root=new TireNode();
    
        //插入的同时,进行子前缀次数的记录
        public void insert(String s){
            TireNode p=root;
            int len=s.length();
            for(int i=0;i<len;i++){
                char c=s.charAt(i);
                if(p.next[c-'a']==null){
                    p.next[c-'a']=new TireNode();
                }
                p.next[c-'a'].preValue++;
                p=p.next[c-'a'];
            }
        }
        
        //查找的过程中,进行子前缀出现次数的累加
        public int prefixWord(String s){
            int sum=0;
            int len=s.length();
            TireNode p=root;
            for(int i=0;i<len;i++){
                char c=s.charAt(i);
                if(p.next[c-'a']==null){
                    return sum;
                }
             
                sum+=p.next[c-'a'].preValue;
                p=p.next[c-'a'];
            }
            return sum;
        }
        
        public int[] sumPrefixScores(String[] words) {
            int len=words.length;
            for(String s:words){
                insert(s);
            }   
            int[]ans=new int[len];
            for(int i=0;i<len;i++){
                ans[i]=prefixWord(words[i]);
            }
            return ans;
        }
    }
    
  • 相关阅读:
    Python的高级用法:偏函数
    grpc、https、oauth2等认证专栏实战13:oauth2认证方式之客户端凭证式介绍
    【从0到1开发一个网关】网关Mock功能的实现
    python--第六章 python函数 装饰器 && 类 && 对象
    10-网络篇-DHCP获取的参数详解
    ChatGPT 基本用法!ChatGPT4的prompt的使用例子!
    windows node多版本管理
    iperf3: error - unable to connect to server: No route to host 但嵌入式Linux设备
    Educational Codeforces Round 136 (Rated for Div. 2)(A~D)
    Eclipse-MAT的插件介绍使用
  • 原文地址:https://blog.csdn.net/qq_44036439/article/details/126931584