力扣周赛398题解

特殊数组Ⅰ

如果数组的每一对相邻元素都是两个奇偶性不同的数字,则该数组被认为是一个 特殊数组 。

Aging 有一个整数数组 nums。如果 nums 是一个 特殊数组 ,返回 true,否则返回 false

示例 1:

输入:nums = [1]

输出:true

解释:

只有一个元素,所以答案为 true

示例 2:

输入:nums = [2,1,4]

输出:true

解释:

只有两对相邻元素: (2,1) 和 (1,4),它们都包含了奇偶性不同的数字,因此答案为 true

示例 3:

输入:nums = [4,3,1,6]

输出:false

解释:

nums[1] 和 nums[2] 都是奇数。因此答案为 false

提示:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 100

        比较暴力,可以直接判断相邻的元素的奇偶性,如果相同返回False,如果检查没有的话,返回True。

代码如下:

class Solution:
    def isArraySpecial(self, nums: List[int]) -> bool:
        for x,y in pairwise(nums):
            if x%2 == y%2:
                return False
        return True

特殊数组Ⅱ

如果数组的每一对相邻元素都是两个奇偶性不同的数字,则该数组被认为是一个 特殊数组 。

周洋哥有一个整数数组 nums 和一个二维整数矩阵 queries,对于 queries[i] = [fromi, toi],请你帮助周洋哥检查子数组 nums[fromi..toi] 是不是一个 特殊数组 

返回布尔数组 answer,如果 nums[fromi..toi] 是特殊数组,则 answer[i] 为 true ,否则,answer[i] 为 false 。

示例 1:

输入:nums = [3,4,1,2,6], queries = [[0,4]]

输出:[false]

解释:

子数组是 [3,4,1,2,6]。2 和 6 都是偶数。

示例 2:

输入:nums = [4,3,1,6], queries = [[0,2],[2,3]]

输出:[false,true]

解释:

  1. 子数组是 [4,3,1]。3 和 1 都是奇数。因此这个查询的答案是 false
  2. 子数组是 [1,6]。只有一对:(1,6),且包含了奇偶性不同的数字。因此这个查询的答案是 true

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105
  • 1 <= queries.length <= 105
  • queries[i].length == 2
  • 0 <= queries[i][0] <= queries[i][1] <= nums.length - 1

         直接暴力去解决会超时,因为暴力的解法是O(n^2),而数据范围是1e5。

        换一种考虑的方法,既然是要考虑相邻的元素之间的奇偶性,不妨直接考虑他们之间的“逗号”。

        比如说例子——

        4, 3, 1, 6

        我们去考虑每个逗号两侧的数字的奇偶性的相同,如果是相同的话,记为0,不同的话记为1.

        那么就是这样——

        0, 1, 0

做个图:

        但是我们是需要去查询一段区间内是否有这种特殊的数组,不难想到使用前缀和的方法。

        查询的时候发现需要加一个前导0.

        原理就是只要这个区间的两端的端点的前缀和不相等就是False,反之就是True。

代码如下:

class Solution:

    def isArraySpecial(self, nums: List[int], queries: List[List[int]]) -> List[bool]:

        s = [0]

        for x,y in pairwise(nums):

            s.append(s[-1]+(x%2==y%2))

        return [s[f] == s[t] for f,t in queries]

所有数对中数位不同之和

车尔尼有一个数组 nums ,它只包含  整数,所有正整数的数位长度都 相同 。

两个整数的 数位不同 指的是两个整数 相同 位置上不同数字的数目。

请车尔尼返回 nums 中 所有 整数对里,数位不同之和。

示例 1:

输入:nums = [13,23,12]

输出:4

解释:
计算过程如下:
13 和 23 的数位不同为 1 。
- 13 和 12 的数位不同为 1 。
23 和 12 的数位不同为 2 。
所以所有整数数对的数位不同之和为 1 + 1 + 2 = 4 。

示例 2:

输入:nums = [10,10,10,10]

输出:0

解释:
数组中所有整数都相同,所以所有整数数对的数位不同之和为 0 。

提示:

  • 2 <= nums.length <= 105
  • 1 <= nums[i] < 109
  • nums 中的整数都有相同的数位长度。

        题目中说明,只包含有正整数,并且正整数的数位长度是相同的,需要我们返回的是所有正数中不同数位之和。

        把所有的数位分开来考虑,举个例子——

        假如说现在已经考虑到了第1个数(下标为1)的各位,不妨把所有的各位抽出来看看如何计算。

        

        箭头所指向的3,就是我们当前考虑到的地方,那么是如何进行考虑的呢?

        因为我们是要统计每个数字的每一位的不同的数量,下标刚好就是在我们当前这个位置一共有多少个数字,我们可以搞一个哈希表,来统计在我们这个位置之前的,这个位置的值出现的次数。

        又因为这个值只会是【0,9】,所以完全可以使用数组来模拟。

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

        

到达第 K 级台阶的方案数

给你有一个 非负 整数 k 。有一个无限长度的台阶,最低 一层编号为 0 。

虎老师有一个整数 jump ,一开始值为 0 。虎老师从台阶 1 开始,虎老师可以使用 任意 次操作,目标是到达第 k 级台阶。假设虎老师位于台阶 i ,一次 操作 中,虎老师可以:

  • 向下走一级到 i - 1 ,但该操作 不能 连续使用,如果在台阶第 0 级也不能使用。
  • 向上走到台阶 i + 2jump 处,然后 jump 变为 jump + 1 。

请你返回虎老师到达台阶 k 处的总方案数。

注意 ,虎老师可能到达台阶 k 处后,通过一些操作重新回到台阶 k 处,这视为不同的方案。

示例 1:

输入:k = 0

输出:2

解释:

2 种到达台阶 0 的方案为:

  • 虎老师从台阶 1 开始。
    • 执行第一种操作,从台阶 1 向下走到台阶 0 。
  • 虎老师从台阶 1 开始。
    • 执行第一种操作,从台阶 1 向下走到台阶 0 。
    • 执行第二种操作,向上走 20 级台阶到台阶 1 。
    • 执行第一种操作,从台阶 1 向下走到台阶 0 。

示例 2:

输入:k = 1

输出:4

解释:

4 种到达台阶 1 的方案为:

  • 虎老师从台阶 1 开始,已经到达台阶 1 。
  • 虎老师从台阶 1 开始。
    • 执行第一种操作,从台阶 1 向下走到台阶 0 。
    • 执行第二种操作,向上走 20 级台阶到台阶 1 。
  • 虎老师从台阶 1 开始。
    • 执行第二种操作,向上走 20 级台阶到台阶 2 。
    • 执行第一种操作,向下走 1 级台阶到台阶 1 。
  • 虎老师从台阶 1 开始。
    • 执行第一种操作,从台阶 1 向下走到台阶 0 。
    • 执行第二种操作,向上走 20 级台阶到台阶 1 。
    • 执行第一种操作,向下走 1 级台阶到台阶 0 。
    • 执行第二种操作,向上走 21 级台阶到台阶 2 。
    • 执行第一种操作,向下走 1 级台阶到台阶 1 。

提示:

  • 0 <= k <= 10^9

        先来解释一下这个题目的意思,说是最小的阶梯是0,从1阶梯开始,要求我们走到k阶梯,有两种操作,但是是有条件的。

        操作一:向下走一级

        操作二:向上走 2^jump 级

        那么很容易想到使用暴力搜索改成记忆化的方法来求解。

        画一个图来帮助我们理解一下——

        那么递归的出口又在哪里呢?

        这需要我们在来分析一下了——

        首先,分析出一个原理,在递归的过程中,数字 i 是逐渐变大的。

        当 i 已经等于 k 的时候我们不能结束,因为他继续搜下去可能会再有一个答案。

        当 i 等于 k + 1 的时候我们还不能结束,因为这个时候只要执行了操作一就可以给结果再加上一个一,变成 i 等于 k,回到第一点。

        当 i 等于 k+2的时候,我们就可以结束了,因为这个时候无论如何 i 都不可能能等于 k 了,直接返回0即可。

        还有一点值得注意的就是我们需要再参数中加上一个bool类型的变量,用来说明喔当前这种情况是否是两个操作都可以做。

最后代码如下:

class Solution:
    def waysToReachStair(self, k: int) -> int:
        @cache
        def dfs(i:int,j:int,p:bool)->int:
            if i >= k+2:
                return 0
            ans = 1 if i==k else 0
            ans += dfs(i+(1<<j),j+1,True)
            if p:
                ans += dfs(i-1,j,False)
            return ans
        return dfs(1,0,True)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值