每日算法-250531

每日算法学习记录 - 250531

今天完成了两道 LeetCode 题目,主要用到了前缀和的思想。记录如下:


1. 2559. 统计范围内的元音字符串数

题目

思路

前缀和

解题过程

我们可以先预处理出一个前缀和数组 nums,其中 nums[i] 表示 words 数组中从下标 0 到下标 i(包含 i)的字符串里,以元音字母开头且以元音字母结尾的字符串的总个数。

预处理完成后,对于每个查询 [left, right]

  • 如果 left == 0,则区间 [0, right] 内满足条件的字符串数量就是 nums[right]
  • 如果 left > 0,则区间 [left, right] 内满足条件的字符串数量为 nums[right] - nums[left - 1]

复杂度

  • mwords 数组的长度,nqueries 数组的长度。
  • 时间复杂度 : O ( m + n ) O(m + n) O(m+n)
    • 预处理前缀和数组 nums:遍历 words 数组一次,对每个单词调用 isVowelisVowel 操作检查首尾字符,可视为 O ( 1 ) O(1) O(1)。总共 O ( m ) O(m) O(m)。
    • 处理 n 个查询:每个查询通过前缀和数组 O ( 1 ) O(1) O(1) 计算。总共 O ( n ) O(n) O(n)。
    • 因此,总时间复杂度为 O ( m + n ) O(m + n) O(m+n)。
  • 空间复杂度 : O ( m ) O(m) O(m)
    • 用于存储前缀和数组 nums

Code

java 复制代码
class Solution {
    public int[] vowelStrings(String[] words, int[][] queries) {
        int n = queries.length, m = words.length;
        int[] ret = new int[n], nums = new int[m];
        nums[0] = isVowel(words[0]);
        for (int i = 1; i < m; i++) {
            nums[i] = nums[i - 1] + isVowel(words[i]);
        }
        for (int i = 0; i < n; i++) {
            int left = queries[i][0], right = queries[i][1];
            ret[i] = left == 0 ? nums[right] : nums[right] - nums[left - 1];
        }
        return ret;
    }

    private int isVowel(String s) {
        int n = s.length();
        if ((s.charAt(0) == 'a' 
        || s.charAt(0) == 'e' 
        || s.charAt(0) == 'i' 
        || s.charAt(0) == 'o' 
        || s.charAt(0) == 'u') 
        && (s.charAt(n - 1) == 'a' 
        || s.charAt(n - 1) == 'e' 
        || s.charAt(n - 1) == 'i' 
        || s.charAt(n - 1) == 'o' 
        || s.charAt(n - 1) == 'u')) {
            return 1;
        }
        return 0;
    }
}

2. 3152. 特殊数组 II

题目

思路

前缀和

解题过程

一个数组 nums 的子数组 nums[from...to] 是"特殊"的,当且仅当其中所有相邻元素的奇偶性都不同。

我们可以预处理一个前缀和数组 prefixBadPairsprefixBadPairs[i] (for i > 0) 表示在 nums 数组的 nums[0...i] 部分中,有多少对相邻元素 (nums[k-1], nums[k]) (其中 1 <= k <= i) 具有相同的奇偶性(我们称之为"坏对")。prefixBadPairs[0] 可以设为 0。

对于一个查询 [from, to]

  • 如果 from == to,子数组只有一个元素,根据定义它总是特殊的。
  • 如果 from < to,我们需要检查 nums[from...to] 中是否存在"坏对"。
    这些"坏对"可能发生在 (nums[from], nums[from+1]), (nums[from+1], nums[from+2]), ..., (nums[to-1], nums[to])
    • prefixBadPairs[to] 包含从 (nums[0],nums[1])(nums[to-1],nums[to]) 的所有坏对。
    • prefixBadPairs[from] 包含从 (nums[0],nums[1])(nums[from-1],nums[from]) 的所有坏对。
    • 他们的差值 prefixBadPairs[to] - prefixBadPairs[from] 即为从 (nums[from],nums[from+1])(nums[to-1],nums[to]) 范围内的坏对数量。
  • 如果这个差值为 0,则说明子数组 nums[from...to] 中没有相邻元素奇偶性相同,该子数组是特殊的,结果为 true。否则,结果为 false

复杂度

  • Nnums 数组的长度,Mqueries 数组的长度。
  • 时间复杂度 : O ( N + M ) O(N + M) O(N+M)
    • 预处理 prefixBadPairs 数组需要 O ( N ) O(N) O(N) 时间。
    • 处理 M 个查询,每个查询 O ( 1 ) O(1) O(1) 时间。
  • 空间复杂度 : O ( N ) O(N) O(N)
    • 用于存储 prefixBadPairs 数组。

Code

java 复制代码
class Solution {
    public boolean[] isArraySpecial(int[] nums, int[][] queries) {
        int n = nums.length, m = queries.length;
        boolean[] ret = new boolean[m];
        int[] prefixBadPairs = new int[n];
        for (int i = 1; i < n; i++) {
            prefixBadPairs[i] = prefixBadPairs[i - 1];
            if ((nums[i] % 2) == (nums[i - 1] % 2)) {
                prefixBadPairs[i]++;
            }
        }
        for (int i = 0; i < m; i++) {
            int from = queries[i][0], to = queries[i][1];
            ret[i] = (prefixBadPairs[to] - prefixBadPairs[from] == 0);
        }
        return ret;
    }
}
相关推荐
小纭在努力几秒前
【算法设计与分析】实验——改写二分搜索算法,众数问题(算法分析:主要算法思路),有重复元素的排列问题,整数因子分解问题(算法实现:过程,分析,小结)
数据结构·python·学习·算法·算法设计与分析·实验报告·实验
芜湖xin1 小时前
【题解-洛谷】B4278 [蓝桥杯青少年组国赛 2023] 简单算术题
算法·
理智的灰太狼1 小时前
题目 3298: 蓝桥杯2024年第十五届决赛真题-兔子集结
算法·职场和发展·蓝桥杯
kingmax542120084 小时前
【洛谷P9303题解】AC- [CCC 2023 J5] CCC Word Hunt
数据结构·c++·算法·广度优先
白熊1885 小时前
【机器学习基础】机器学习入门核心算法:XGBoost 和 LightGBM
人工智能·算法·机器学习
bai_lan_ya5 小时前
数据结构-排序-排序的七种算法(2)
数据结构·算法·排序算法
全域智图6 小时前
元胞自动机(Cellular Automata, CA)
人工智能·算法·机器学习
珂朵莉MM7 小时前
2022 RoboCom 世界机器人开发者大赛-本科组(省赛)解题报告 | 珂学家
人工智能·算法·职场和发展·深度优先·图论
独家回忆3647 小时前
每日算法-250601
数据结构·算法
YONYON-R&D7 小时前
DEEPSEEK帮写的STM32消息流函数,直接可用.已经测试
算法·消息流