【力扣周赛】第 355 场周赛(构造二分答案异或前缀 状态压缩⭐)

news2024/10/5 16:22:18

文章目录

  • Q1:6921. 按分隔符拆分字符串(双指针)
  • Q2:6915. 合并后数组中的最大元素(倒序遍历+贪心)
    • 代码优化
  • Q3:6955. 长度递增组的最大数目🚹🚹🚹🚹🚹
    • 解法1——构造⭐
    • 解法2——排序 + 二分⭐(🐂!重要!有启发性!)
  • Q4:2791. 树中可以形成回文的路径数🚹🚹🚹🚹🚹(异或&哈希表)⭐⭐⭐⭐⭐
    • 补充:相关题目
      • 1457. 二叉树中的伪回文路径
      • 1371. 每个元音包含偶数次的最长子字符串
      • 1542. 找出最长的超赞子字符串
  • 成绩记录

Q1:6921. 按分隔符拆分字符串(双指针)

https://leetcode.cn/problems/split-strings-by-separator/description/

在这里插入图片描述
提示:

1 <= words.length <= 100
1 <= words[i].length <= 20
words[i] 中的字符要么是小写英文字母,要么就是字符串 ".,|$#@" 中的字符(不包括引号)
separator 是字符串 ".,|$#@" 中的某个字符(不包括引号)

用双指针手动切分每个 word 加入答案列表即可。

class Solution {
    public List<String> splitWordsBySeparator(List<String> words, char separator) {
        List<String> ans = new ArrayList();
        for (String word: words) {
            int n = word.length();
            for (int r = 0, l = 0; r < n; ++r) {
                if (word.charAt(r) == separator) {
                    if (r > l) ans.add(word.substring(l, r));
                    l = r + 1;
                } else if (r == n - 1) ans.add(word.substring(l, n));
            }
        }
        return ans;
    }
}

Q2:6915. 合并后数组中的最大元素(倒序遍历+贪心)

在这里插入图片描述
提示:

1 <= nums.length <= 10^5
1 <= nums[i] <= 10^6

贪心地尽量先合并后面的元素。

因为先合并前面的可能会导致数字变大不能继续合并。 e.g. 3,4,5 变成 7,5之后就不能合并了;但是变成3,9之后可以继续合并成12。

使用 long 是防止在原数组上计算时溢出。

class Solution {
    public long maxArrayValue(int[] nums) {
        long[] ans = new long[nums.length];
        for (int i = nums.length - 1; i >= 0; --i) {
            ans[i] = nums[i];
        }
        
        for (int i = nums.length - 1; i > 0; --i) {
            if (ans[i] >= ans[i - 1]) ans[i - 1] += ans[i];
        }
        return Arrays.stream(ans).max().getAsLong();
    }
}

代码优化

也可以用 cur 存储当前结果,省去额外的 long 数组。

class Solution {
    public long maxArrayValue(int[] nums) {
        long ans = nums[nums.length - 1], cur = ans;
        for (int i = nums.length - 1; i > 0; --i) {
            if (cur >= nums[i - 1]) cur += nums[i - 1];
            else cur = nums[i - 1];
            ans = Math.max(ans, cur);
        }
        return ans;
    }
}

Q3:6955. 长度递增组的最大数目🚹🚹🚹🚹🚹

https://leetcode.cn/problems/maximum-number-of-groups-with-increasing-length/description/

在这里插入图片描述

提示:

1 <= usageLimits.length <= 10^5
1 <= usageLimits[i] <= 10^9

解法1——构造⭐

在这里插入图片描述
证明讲解可见:https://www.bilibili.com/video/BV1n8411m7Fs/

class Solution {
    public int maxIncreasingGroups(List<Integer> usageLimits) {
        // 从小到大排序
        Collections.sort(usageLimits);
        long ans = 0, s = 0;
        for (int v: usageLimits) {
            s += v;
            // 如果像让当前的 ans + 1,就需要 s 足够组成 1 ~ ans + 1 的等差数列
            if (s >= (ans + 2) * (ans + 1) / 2) {
                // 每次来一个新的数字,且它的数量足够,那么就可以多构造出 1 组
                ans++;
            }
        }
        return (int)ans;
    }
}

解法2——排序 + 二分⭐(🐂!重要!有启发性!)

参考题解:https://leetcode.cn/problems/maximum-number-of-groups-with-increasing-length/solutions/2355580/pai-xu-er-fen-tu-jie-ban-by-yzq-a-smlx/

设可以组成 k 个序列。

二分答案。检查答案是否合理的过程是:将 usageLimits 从大到小进行排序,之后枚举。
数量少的元素可以补给数量大的元素,但是反过来不行。

在这里插入图片描述

在这里插入图片描述

class Solution {
    public int maxIncreasingGroups(List<Integer> usageLimits) {
        Collections.sort(usageLimits, (a, b) -> b - a);     // 降序排序
        int l = 0, r = usageLimits.size();
        while (l < r) {
            int mid = l + r + 1>> 1;
            if (check(usageLimits, mid)) l = mid;
            else r = mid - 1;
        }
        return l;
    }

    boolean check(List<Integer> usageLimits, int k) {
        int gap = 0;
        for (int v: usageLimits) {
            // 数量少的可以补给数量大的,所以降序排序后枚举
            gap = Math.min(gap + v - k, 0);
            if (k > 0) k--;         // k是当前需要的数量
        }
        return gap >= 0;
    }
}

Q:为什么要先使用数量多的元素?
A:因为数量多的元素即使数量大于组成序列个数 k,也最多只能使用 k 个,否则会重复。而数量小的元素可以放在任意不同的序列中而不会发生重复。

Q4:2791. 树中可以形成回文的路径数🚹🚹🚹🚹🚹(异或&哈希表)⭐⭐⭐⭐⭐

相似原题链接:https://loj.ac/p/6681

https://leetcode.cn/problems/count-paths-that-can-form-a-palindrome-in-a-tree/

在这里插入图片描述

提示:

n == parent.length == s.length
1 <= n <= 10^5
对于所有 i >= 1 ,0 <= parent[i] <= n - 1 均成立
parent[0] == -1
parent 表示一棵有效的树
s 仅由小写英文数字组成


注意题目要求的是路径可以重新排列成回文串而不是要求路径组成了回文串。(即对字母的顺序没有要求,只对字母的数量有要求)。

重要可以排列成回文串等价于最多一个字母出现奇数次,其余字母出现偶数次。

对于这道题来说,只有27个二进制数符合要求:
在这里插入图片描述

那么如何计算各个路径之间的异或和呢?
在这里插入图片描述

class Solution {
    List<Integer>[] g;
    String s;
    Map<Integer, Integer> cnt = new HashMap<>();
    long ans = 0;

    public long countPalindromePaths(List<Integer> parent, String s) {
        int n = parent.size();
        this.s = s;
        g = new ArrayList[n];
        Arrays.setAll(g, e -> new ArrayList<>());
        for (int i = 1; i < n; ++i) {
            g[parent.get(i)].add(i);
        }
        cnt.put(0, 1);          // 放入一条【空路径】
        dfs(0, 0);
        return ans;
    }

    void dfs(int x, int xor) {
        for (int y: g[x]) {
            int bit = 1 << (s.charAt(y) - 'a');
            int y_xor = xor ^ bit;
            ans += cnt.getOrDefault(y_xor, 0);      // 自己和自己异或是0
            for (int i = 0; i < 26; ++i) {
                // 和只有1位数字不一样的异或,结果上只有1位数字是1
                ans += cnt.getOrDefault(y_xor ^ (1 << i), 0);
            }
            cnt.merge(y_xor, 1, Integer::sum);
            dfs(y, y_xor);
        }
    }
}

注意在 dfs 之前要现在 cnt 中添加一条空路径。

我们在 dfs 过程中计算的是从根节点到各个节点的 xor。如果两条路径可以组成一条合理的路径有两种情况:1.两条路径的 xor 相同2.两条路径的二进制表示只有一个位置不同

补充:相关题目

1457. 二叉树中的伪回文路径

https://leetcode.cn/problems/pseudo-palindromic-paths-in-a-binary-tree/

在这里插入图片描述

提示:

给定二叉树的节点数目在范围 [1, 10^5] 内
1 <= Node.val <= 9

这道题目相对简单一些,只需要判断从根节点到叶子节点的路径能否排列成回文串。

class Solution {
    int ans = 0;

    public int pseudoPalindromicPaths (TreeNode root) {
        dfs(root, 0);
        return ans;
    }

    void dfs(TreeNode root, int xor) {
        xor ^= 1 << root.val;
        if (root.left == null && root.right == null) {
            if (xor == 0 || (xor & (xor - 1)) == 0) ++ans;
            return;
        }
        if (root.left != null) dfs(root.left, xor);
        if (root.right != null) dfs(root.right, xor);
    }
}

1371. 每个元音包含偶数次的最长子字符串

https://leetcode.cn/problems/find-the-longest-substring-containing-vowels-in-even-counts/

在这里插入图片描述

使用异或前缀,记录每一种状态出现的第一个位置,当出现了之前出现过的状态时,可以尝试更新答案。

class Solution {
    public int findTheLongestSubstring(String s) {
        int n = s.length(), ans = 0, xor = 0;
        String vowels = "aeiou";
        Map<Integer, Integer> idx = new HashMap<>();
        idx.put(0, -1);          // 0的位置是-1
        for (int i = 0; i < n; ++i) {
            char ch = s.charAt(i);
            // 如果是元音
            if (vowels.indexOf(ch) != -1) {
                xor ^= 1 << (ch - 'a');
            }
            
            // 记录每个状态第一次出现的位置
            if (idx.containsKey(xor)) {
                ans = Math.max(i - idx.get(xor), ans);
            } else idx.put(xor, i);
        }
        return ans;
    }
}

1542. 找出最长的超赞子字符串

https://leetcode.cn/problems/find-longest-awesome-substring/

在这里插入图片描述

提示:

1 <= s.length <= 10^5
s 仅由数字组成

可以变成回文子串:异或值至多有 1 个 1。

class Solution {
    public int longestAwesome(String s) {
        int n = s.length(), ans = 0, xor = 0;
        int[] idx = new int[1 << 10];
        Arrays.fill(idx, n);
        idx[0] = -1;
        for (int i = 0; i < n; ++i) {
            xor ^= 1 << (s.charAt(i) - '0');
            // 前缀一致,出现次数全是偶数
            if (idx[xor] != n) ans = Math.max(ans, i - idx[xor]);
            // 前缀只有一位不一样,只有一个次数是奇数
            for (int j = 0; j <= 9; ++j) {
                int x = xor ^ (1 << j);
                if (idx[x] != n) ans = Math.max(ans, i - idx[x]);
            }

            if (idx[xor] == n) idx[xor] = i;
        }
        return ans;
    }
}

成绩记录

在这里插入图片描述

在这里插入图片描述
T1做慢了。

T3、T4 做不出来是正常的(

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/791981.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

企业级PaaS低代码快开平台源码,基于 Salesforce Platform 的开源替代方案

PaaS低代码快开平台是一种快速开发应用系统的工具&#xff0c;用户通过少量代码甚至不写代码就可以快速构建出各种应用系统。 随着信息化技术的发展&#xff0c;企业对信息化开发的需求正在逐渐改变&#xff0c;传统的定制开发已经无法满足企业需求。低代码开发平台&#xff0…

ElementUI tabs标签页样式改造美化

今天针对ElementUI的Tabs标签页进行了样式修改&#xff0c;更改为如下图所属的样子。 在线运行地址&#xff1a;JSRUN项目-ElementUI tabs标签页样式改造 大家如果有需要可以拿来修改使用&#xff0c;下面我也简单的贴上代码&#xff0c;代码没有注释&#xff0c;很抱歉&#x…

Centos7.9安装瀚高数据库企业版6.0.4_并开启远程连接_使用瀚高连接工具操作_亲测成功---国产瀚高数据库工作笔记003

1.首先去瀚高官网,注册,然后下载安装包, OpenEuler23.03欧拉系统_安装瀚高数据库企业版6.0.4_openeuler切换root用户_su:拒绝权限_passwd: 鉴定令牌操作错误---国产瀚高数据库工作笔记001 一部分内容可以参考一下这个博文 2.准备一下环境: 关闭防火墙,关闭网络管理器 syste…

Spingboot yaml 配置文件及数据读取

属性配置在这里插入图片描述 修改服务器端口 → server.port80 修改 banner → spring.main.banner off(关闭)/console(控制台)/log(日志) 日志 → logging.level.rootinfo Common Application Properties 配置文件分类 优先级 如果三种文件共存时&#xff0c;优先级为&am…

618技术揭秘 - 大促弹窗搭投实践 | 京东云技术团队

背景 618 大促来了&#xff0c;对于业务团队来说&#xff0c;最重要的事情莫过于各种大促营销。如会场、直播带货、频道内营销等等。而弹窗作为一个极其重要的强触达营销工具&#xff0c;通常用来渲染大促氛围、引流主会场、以及通过频道活动来提升频道复访等。因此&#xff0…

基本数据类型转换(基本数据类型之间的运算规则)

自动类型转换 前提&#xff1a;这里讨论只是7种基本数据类型变量间的运算。不包含boolean类型的。 自动类型转换&#xff1a;容量小的类型自动转换为容量大的数据类型。数据类型按容量大小排序为&#xff1a; 有多种类型的数据混合运算时&#xff0c;系统首先自动将所有数据 …

ssm文章发布管理系统java小说作品发表jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 ssm文章发布管理系统 系统有2权限&#xff1a;前台账…

企业微信开发应用之获取userId

一、创建应用 企业微信 (qq.com) 在【应用管理】界面-【应用】-【自建】点击【创建应用】 参考 一&#xff1a;如何创建企业内部应用 - 教程 - 企业微信开发者中心 (qq.com) 二、配置信息 开发阶段“应用可见范围”可先选择小范围可见&#xff0c;待开发完成后再开放给企业…

PMP成绩查询及电子版证书下载方式

2023年05月27日PMP考试成绩预计将于2023年7月24日晚开始发布&#xff0c;按照往年的情况&#xff0c;成绩都是分批出的&#xff0c;如果暂时没查到成绩的同学请耐心等待&#xff0c;预计一周内成绩会全部出来。 具体查询方法如下 当你在PMI的注册邮箱收到一封PMI发来的&#x…

EC200U-CN学习(四)

EC200U系列内置丰富的网络协议&#xff0c;集成多个工业标准接口&#xff0c;并支持多种驱动和软件功能&#xff08;适用于Windows 7/8/8.1/10、Linux和Android等操作系统下的USB驱动&#xff09;&#xff0c;极大地拓展了其在M2M领域的应用范围&#xff0c;如POS、POC、ETC、共…

JavaScript学习 -- Base64编码

Base64编码是一种常用的将二进制数据转换为文本数据的方式。在JavaScript中&#xff0c;我们可以通过使用Base64编码算法&#xff0c;将二进制数据转换为可读的文本数据&#xff0c;以便于在网络传输、文件传输等场景下使用。在本篇博客中&#xff0c;我们将介绍Base64编码的基…

pipeline和retiming

首先,pipeline 是 rtl design 的技巧,Retiming 是 synthesize 的技术。设计里面要有pipeline,才有后面的retiming。 当然,現在synthesis 进步很多了,這句话在有些时候已经不成立了,但是,大多数的时候,Retiming 还是针对pipeline 做优化。 一個简单的例子,例如我们做一…

021 - count()函数 - 对结果进行计数统计

COUNT() 函数返回匹配指定条件的行数。 -- 语法&#xff1a; COUNT(column_name) 函数返回指定列的值的数目&#xff08;NULL 不计入); SELECT COUNT(name) AS "统计" FROM test02; -- 语法&#xff1a; COUNT(*) 函数返回表中的记录数; select COUNT(*) AS "统…

【沁恒蓝牙mesh】手机配网+自组网联合调试

开发蓝牙mesh过程中&#xff0c;需要一个管理者&#xff0c;采用以下方案 一个节点用手机配网的方式&#xff0c;其余节点用自组网的方式&#xff0c;只要手机组网的节点与自组网的节点的配网信息相同&#xff0c;所有节点就可以在一个mesh网络中。 1. 组网描述 描述&#xff1…

【外卖系统】新增员工

需求分析和数据模型 新增员工就是将新增页面录入的员工数据插入到emoloyee表&#xff0c;username字段约束是唯一的&#xff0c;即员工的登录账号是唯一的status字段默认值为1&#xff0c;表示状态正常 前端界面 报错信息&#xff1a; 代码开发分析 页面发送ajax请求&…

推荐几款不错的AI绘画工具

随着近年来数据、算法等核心技术的不断进步&#xff0c;人工智能在内容创作各垂直领域的比例不断增加&#xff0c;包括人工智能写作、人工智能编辑和最近流行的人工智能绘画。 许多朋友也想跟上潮流&#xff0c;使用人工智能绘画生成软件创建人工智能图像&#xff0c;但我不知…

命令行计算和校验文件的MD5值,校验文件的完整性

MD5算法常常被用来验证网络文件传输的完整性&#xff0c;防止文件被人篡改。MD5全称是报文摘要算法&#xff08;Message-Digest Algorithm 5&#xff09;&#xff0c;此算法对任意长度的信息逐位进行计算&#xff0c;产生一个二进制长度为128位&#xff08;十六进制长度就是32位…

业务不打烊:解决软件系统升级痛点的新方法

数字化时代&#xff0c;随着用户对产品性能和功能要求的不断提升&#xff0c;应用服务升级成了企业保持竞争力的关键之一。然而&#xff0c;传统的应用服务升级往往会给用户带来不必要的中断和不便&#xff0c;这种“伤筋动骨”的升级方式已经无法满足日益增长的用户需求&#…

【Mo 人工智能技术博客】推荐系统(二)用户行为数据

任少斌 上一期&#xff1a;推荐系统&#xff08;一&#xff09;简要介绍 用户提供信息 正所谓“知己知彼&#xff0c;百战不殆”&#xff0c;为了让推荐系统更符合用户的偏好&#xff0c;我们需要深入了解用户的行为特征。如果有用户在注册的时候能够描述个人的偏好&#xff…

【网络安全带你练爬虫-100练】第15练:模拟用户登录

目录 一、目标1&#xff1a;理清逻辑 二、目标2&#xff1a;将每一步用代码进行表示 三、网络安全O 一、目标1&#xff1a;理清逻辑 模拟登录的基本流程 1、进入入口程序 2、读取目标URL 3、请求加上线程 4、确定请求数据包 5、请求格式的确认 6、数据的处理与判断 二、目标…