新手分析Python3每日一题

2020/4/21 统计「优美子数组」

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-number-of-nice-subarrays

题目 给你一个整数数组 nums 和一个整数 k。
如果某个 连续 子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。
请返回这个数组中「优美子数组」的数目
在这里插入图片描述
在这里插入图片描述
新手分析
第一眼看题目,首先想到的是暴力法,全部列出,然后来个判断,但这一般都会超时,不好

下面开始思考,摸索一下例题的规律
例二给的启示就是整个数组如果没有奇数
在这里插入图片描述就直接 return 0
例一告诉了我们题目的意思
那么看例三,只给了答案,分析一下
大致想到的是k=2,而整个数组就两个奇数,那就把数组框到1221,发现数组规律在1221的左右分别有三个2,也就是在1221的基础上,左边可以0,1,2,3个2,右边也是,在左边0,1,2,3个2的时候,右边也分别可以0,1,2,3个2,所以是4x4=16
那么算法的话,因为正好k=当前的奇数个数,所以可能具有特殊性。
此时我们再来看示例1
用我们刚刚想的,找到k个奇数的最小数组,但示例1中,找到的最小数组之后,发现只有一个2,也就是说找到了也只能最多一个,反而后面是1,可以遍历过去,那么就又想到,找最小满足数组?然后在结合刚刚找到后怎么做?想到这,我决定自己来个示例看看
在这里插入图片描述
圈出最小满足的数组,有5个,先看第一个,左边没有东西,右边是1,那他就直接结束,就一个,第二个圈,左边有2,右边2个2,那就是多出2x3=6个,再看第三个,左边1,右边1,那就是一个直接结束,第四个,左边2个2,右边1,那就是3个,因为右边是1不用考虑,左边分别是0,1,2个2,就是3个,第五个圈也就是最后一个圈,显然也就一个,因为左边1,右边啥都没,所以答案应该就是1+6+1+3+1=12
想到这,可能我发现了此题就是找这最小的数组,也就是没有多余的偶数在外,也就是左右两边肯定是1
,然后满足k,往里面塞k-2个1,OK好像有思路了。
哦,我们忘了k>=1,所以还得说下k=1,这个简单,也就是圈画成一个1一个圈
化繁为简,先不考虑那么多,慢慢来捋捋

k=1,找1(化繁为简,先说1 )
k>1 ,找1xxx1形式,xxx里满足k-2个1.

找完后,每个数组开始找旁边的2,一直找到又到1.就结束,然后左边有n个2,右边有n个2,结果就是(n+1)(n+1),验算,没错对的
化简为繁
前面找的1就是找奇数,找的2就是找偶数
难题重现
1.找到1xxx1形式
2.找到1xxx1形式后找2
品味难题
怎么找1xxx1形式呢,这时候就想到一个题目,删除最外括号,利用count,因为括号只有左和右,发现左括号,就加一,不然减一,这样0就是说明左右括号一致,那么来到这题,我没想到利用count,count为k结束,找k个奇数,每一个奇数都是开始寻找的点,
在这里插入图片描述

class Solution:
    def numberOfSubarrays(self, nums: List[int], k: int) -> int:
        sum = 0 #最终结果
        leftevennumber = 0
        rightevennumber = 0
        for i in range(len(nums)):
            if nums[i]%2==0: #遍历列表入股为偶数
                leftevennumber+=1 #偶数就左边加一到时候用来计算多余数组
            else:  #遍历到奇数,开始找最小数组
                count = 0 #寻找奇数个数
                for j in range(i,len(nums)): #从奇数开始遍历
                    if count<k and nums[j]%2!=0: #没到,奇数就加1
                        count+=1
                        if (count==k)and(j==len(nums)-1):                            
                            sum+=(leftevennumber+1)*(rightevennumber+1)
                            leftevennumber = 0  #左右边归零
                            rightevennumber = 0
                            break
                        else:
                            continue
                    elif count==k and nums[j]%2==0: #到了,开始计算后面的多余偶数个数
                        rightevennumber+=1
                        if (count==k)and(j==len(nums)-1):                            
                            sum+=(leftevennumber+1)*(rightevennumber+1)
                            leftevennumber = 0  #左右边归零
                            rightevennumber = 0
                            break
                    elif count==k and nums[j]%2!=0:  #超过规定奇数个数,算出当前最小数组的最多个数,结束此次最小数组的遍历
                        sum+=(leftevennumber+1)*(rightevennumber+1)
                        leftevennumber = 0  #左右边归零
                        rightevennumber = 0
                        break
                    elif count<k and nums[j]%2==0:
                        continue
                    elif count>k:
                        continue
                    else:
                        sum+=(leftevennumber+1)*(rightevennumber+1)
                        leftevennumber = 0  #左右边归零
                        rightevennumber = 0
                        break
            
        return sum
		
	

结果,很遗憾,超出时间限制。
好吧,只能取看看别人怎么想的了,这题就这样失败了

高手分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值