LeetCode 第 398 场周赛 个人题解

100310. 特殊数组 I

原题链接

特殊数组 I - 力扣 (LeetCode) 竞赛

思路分析

签到题直接一次遍历

时间复杂度: O(n)

AC代码

class Solution:
    def isArraySpecial(self, nums: List[int]) -> bool:
        n = len(nums)
        for i in range(n - 1):
            if (nums[i] & 1) ^ (nums[i + 1] & 1):
                continue
            return False
        return True

100308. 特殊数组 II

原题链接

特殊数组 II - 力扣 (LeetCode) 竞赛

思路分析

其实算个预处理个前缀和就行了,不知道为啥比赛的时候换cpp写了树状数组。。。

下面是O(n)思路,不过代码我还是放的树状数组:

标记数组st[], 对于nums[i] 和 nums[i + 1]如果二者奇偶性不同,st[i] = 1

然后对于查询[l, r], sum[st[l], st[r - 1]]如果大于0,该查询就是false,否则是true

时间复杂度O(n)

这道题因为写了树状数组导致比别人多了三四分钟,排到几十名了。。。。哭死

AC代码

树状数组O(nlogn)

class Solution {
public:
int tr[100010], n;
void add(int x, int k) {
    for (; x <= n; x += (x & -x))
        tr[x] += k;
}
int query(int x) {
    int res = 0, n;
    for (; x; x &= (x - 1))
        res += tr[x];
    return res;
}
    
    vector<bool> isArraySpecial(vector<int>& nums, vector<vector<int>>& queries) {
        n = nums.size();
        memset(tr, 0, sizeof tr);
        for (int i = 0; i + 1 < n; i ++)
            if ((nums[i] & 1) ^ (nums[i + 1] & 1)) continue;
            else add(i + 1, 1);
        vector<bool> res;
        for (auto& v : queries) {
            int x = v[0], y = v[1];
            if (query(y) - query(x)) res.emplace_back(false);
            else res.emplace_back(true);
        }
        return res;
    }
};

100300. 所有数对中数位不同之和

原题链接

所有数对中数位不同之和 - 力扣 (LeetCode) 竞赛

思路分析

计数数组cnt[i][j] 代表遍历到当前数字为止,前面的数字第i位为j的数目

然后遍历每个数字,从低到高位统计计数即可

时间复杂度O(nU), U为数字十进制下的长度

AC代码

class Solution:
    def sumDigitDifferences(self, nums: List[int]) -> int:
        res = 0
        cnt = [[0] * 10 for _ in range(10)]
        for x in map(str, nums):
            for i, ch in enumerate(x[::-1]):
                res += sum(cnt[i]) - cnt[i][int(ch)]
                cnt[i][int(ch)] += 1
        return res
        

100298. 到达第 K 级台阶的方案数

原题链接

到达第 K 级台阶的方案数 - 力扣 (LeetCode) 竞赛

思路分析

这玩意写完代码犹豫了两分钟才交,然后瞬间过了。。。。

然后想了下时间复杂度是log级别的。。。

就是一个很标准的dp,而且直接记忆化搜索就行

我们定义状态f(i, j, lim)为当前在 第 i 级台阶,jump = j,lim为true说明如果i!=0就可以向下跳一级台阶时,到达k级的方案数

那么f(i, j, lim) = (i == k) + f(i + (1 << j), j + 1, False) + (如果lim=true并且i不为0) f(i - 1, j, False)

递归出口:i - 1 > k,就return

时间复杂度O(logk)

AC代码

class Solution:
    def waysToReachStair(self, k: int) -> int:
        @cache
        def dfs(i: int, j: int, lim: bool) -> int:
            res = 0
            if i == k:
                res += 1
            if i - 1 > k:
                return res
            if lim and i:
                res += dfs(i - 1, j, False)
            res += dfs(i + (1 << j), j + 1, True)
            return res
        dfs.cache_clear()
        return dfs(1, 0, True)

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQUINOX1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值