鱼C论坛

 找回密码
 立即注册
查看: 2945|回复: 32

[已解决]Python:每日一题 308

[复制链接]
发表于 2020-1-17 20:11:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
今天的题目:


给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 k 个值从 0 变成 1 。

返回仅包含 1 的最长连续子数组的长度。

示例 1:

输入:A = [1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0],k = 2
输出:6
解释:[1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1]
粗体数字从 0 变为 1,最长的子数组长度为 6。
示例 2:

输入:A = [0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1],k = 3
输出:10
解释:[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1]
粗体数字从 0 变为 1,最长的子数组长度为 10。


欢迎大家一起答题!
最佳答案
2020-1-18 11:52:36
  1. def fun308(A, k):
  2.     res = [-1]+[i for i in range(len(A)) if not A[i]]+[len(A)]
  3.     if len(res)-k-2 <= 0: return len(A)   
  4.     return max([max(res[i+k]-res[i-1]-1,0) for i in range(1, len(res)-k)])
复制代码

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-1-17 21:32:20 | 显示全部楼层
  1. def func308(l:list,k:int):
  2.     l.append(2)
  3.     prev=1
  4.     count=0
  5.     ret,temp=0,0
  6.     prev_blank=0
  7.     que=[deque(),deque()]
  8.     for i in l:
  9.         if i!=prev:
  10.             que[prev].append(count)
  11.             temp+=count
  12.             if prev==0:
  13.                 k-=count
  14.                 while k<0:
  15.                     temp-=que[1].popleft()
  16.                     prev_blank=que[0].popleft()
  17.                     k+=prev_blank
  18.                     temp-=prev_blank
  19.             ret=max(ret,temp+min(prev_blank,k))
  20.             count=0
  21.             prev=i
  22.         count+=1
  23.     return ret
复制代码

评分

参与人数 1荣誉 +10 鱼币 +10 收起 理由
zltzlt + 10 + 10 80 ms

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-17 21:50:19 | 显示全部楼层
本帖最后由 阴阳神万物主 于 2020-1-17 22:33 编辑

跟昨天好像啊。
代码:
  1. def solve(A:'list of 0 or 1',k:int):
  2.     res = 0
  3.     le = len(A)
  4.     pos = [-1]+[i for i in range(le) if not A[i]]+[le]
  5.     for i in range(1,len(pos)-k):
  6.         res = max(pos[i+k]-pos[i-1]-1,res)
  7.     return res
  8. if __name__ == '__main__':
  9.     print('示例1 输出:',solve(A = [1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0],k = 2))
  10.     print('示例2 输出:',solve(A = [0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1],k = 3))
复制代码


评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-17 22:54:54 | 显示全部楼层
  1. list1 = input().split()
  2. k = int(input())
  3. m = k
  4. list1_result = []
  5. list2 = list1.copy()
  6. first = 0
  7. count = 0
  8. while True:
  9.     for i in range(first,len(list1)):
  10.         if list1[i] == '0':
  11.             list2[i] = '1'
  12.             k-=1
  13.             if k == 0:
  14.                 for j in list2:
  15.                     if j == '1':
  16.                         count+=1
  17.                     else:
  18.                         list1_result.append(count)
  19.                         count = 0
  20.                 list1_result.append(count)
  21.                 count = 0
  22.                 first+=1
  23.                 list2 = list1.copy()     
  24.                 k = m
  25.                 break
  26.     if list1[first:len(list1)].count('0') == 0:#消除尾数全是1的BUG
  27.         break
  28.     if first == len(list1):
  29.         break         
  30. print(max(list1_result))
复制代码

#感觉有点像暴力求解

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-17 23:16:28 | 显示全部楼层
阴阳神万物主 发表于 2020-1-17 21:50
跟昨天好像啊。
代码:

大佬的代码,有些难于理解,可否解释一下啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-17 23:26:13 | 显示全部楼层
本帖最后由 阴阳神万物主 于 2020-1-17 23:34 编辑
wanting-for 发表于 2020-1-17 23:16
大佬的代码,有些难于理解,可否解释一下啊


首先,把0的位置标出来。
然后,依次把相邻的跨度为k个0的位置的索引作差,就得到一个相对长的子数组的长度。
最后,把最大的那个长度返回就好了。
这个思路主要基于 最长连续子数组 一定具有的特性:两头的外面相邻的,不是 0 就是 A的边界,其中包含的 0 的数量一定为 k. 但是满足这个特性的,不一定是 最长连续子数组 ,所以就要在满足这个特性的 连续子数组 中选出最长的那个。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-17 23:42:28 | 显示全部楼层
本帖最后由 sunrise085 于 2020-1-17 23:54 编辑

#设置一定宽度窗口在输入列表上进行滑动(窗体初始大小为列表长度),并检查窗体内0的个数
#若窗体内的count(0)=k,返回当前窗体大小,
#若滑动到列表尾部,都不满足条件,则缩小窗体再次寻找
  1. def fun308(list1,k):
  2.     length= len(list1)
  3.     for i in range(length,k-1,-1):
  4.         for j in range(length-i+1):
  5.             if list1[j:i+j].count(0)==k:
  6.                 return i

  7. list1=[1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0]
  8. list2=[0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1]
  9. print(fun308(list1,2))
  10. print(fun308(list2,3))
  11. print(fun308([0,0,0,0,0,0,0],4))
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-18 11:23:38 | 显示全部楼层
本帖最后由 kinkon 于 2020-1-18 11:28 编辑

偷换阴阳神解法
  1. def fun308(A, k):#以0解法
  2.     res = [-1]+[i for i in range(len(A)) if not A[i]]+[len(A)]
  3.     if len(res) == 2: return len(A)   
  4.     return max([max(res[i+k]-res[i-1]-1,0) for i in range(1, len(res)-k)])
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-18 11:31:09 | 显示全部楼层

deque 是从 collections 模块来的吧?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-18 11:33:20 | 显示全部楼层
阴阳神万物主 发表于 2020-1-17 21:50
跟昨天好像啊。
代码:

解答错误

输入:A = [0,0,0,1],k = 4
输出:0
预期结果:4
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-18 11:34:46 | 显示全部楼层
wanting-for 发表于 2020-1-17 22:54
#感觉有点像暴力求解

输入 A = [1,1,1,0,0,0,1,1,1,1,0],k = 2 出错

ValueError: max() arg is an empty sequence
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-18 11:35:55 | 显示全部楼层
sunrise085 发表于 2020-1-17 23:42
#设置一定宽度窗口在输入列表上进行滑动(窗体初始大小为列表长度),并检查窗体内0的个数
#若窗体内的cou ...

解答错误

输入:A = [0,0,0,1],k = 4
输出:None
预期结果:4
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-18 11:37:15 | 显示全部楼层
kinkon 发表于 2020-1-18 11:23
偷换阴阳神解法

输入 A = [0, 0, 0, 1],k = 4 出错

ValueError: max() arg is an empty sequence
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-18 11:45:05 | 显示全部楼层
本帖最后由 776667 于 2020-1-18 12:00 编辑
  1. def fun308(A,k):
  2.     result = []
  3.     for i in range(len(A)-1):
  4.         for j in range(len(A))[i+1:][::-1]:
  5.             if A[i:j+1].count(0) == k:
  6.                 result.append(j - i + 1)
  7.                 break
  8.     return max(result)
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-18 11:46:04 | 显示全部楼层

解答错误

输入:[0,0,0,1],k = 4
输出:0
预期结果:4
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-18 11:52:36 | 显示全部楼层    本楼为最佳答案   
  1. def fun308(A, k):
  2.     res = [-1]+[i for i in range(len(A)) if not A[i]]+[len(A)]
  3.     if len(res)-k-2 <= 0: return len(A)   
  4.     return max([max(res[i+k]-res[i-1]-1,0) for i in range(1, len(res)-k)])
复制代码

评分

参与人数 1荣誉 +10 鱼币 +10 收起 理由
zltzlt + 10 + 10 恭喜通过,执行用时为 100 ms

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-18 12:21:17 | 显示全部楼层
zltzlt 发表于 2020-1-18 11:31
deque 是从 collections 模块来的吧?

恩,忘了粘贴那一句,list的pop(0)代价太高。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-18 12:49:39 | 显示全部楼层
本帖最后由 zltzlt 于 2020-1-18 15:41 编辑
  1. import itertools

  2. def max_1(lis):  #求由0,1组成的A数组仅包含 1 的最长连续子数组的长度
  3.     c = 0
  4.     re = 0
  5.     for i in lis:
  6.         if i == 1:
  7.             c += 1
  8.         else:
  9.             if c > re :
  10.                 re = c
  11.             c = 0
  12.     if c > re:
  13.         re = c
  14.     return re

  15. def zc(A,k):
  16.     index = []
  17.     re = 0
  18.     for i in range(len(A)):
  19.         if A[i] == 0:
  20.             index.append(i)    #分析数组A,找到数字为0的位置
  21.             
  22.     if k > len(index):  #k比0的个数还多的情况
  23.         return len(A)
  24.    
  25.     for i in itertools.combinations(index,k):   #从index列表记录的0的位置中取出k个0的位置,每一个i是一种不同取法
  26.         temp = A.copy()  #必须用一个复制的原列表用作计算
  27.         for j in range(k):  #把对应该种取法的0位置换为1
  28.             temp[i[j]] = 1
  29.         max_temp = max_1(temp)  #计算最大子组的长度
  30.         if max_temp > re:
  31.             re = max_temp
  32.     return re

  33. if __name__ == '__main__':
  34.     A = [1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0]
  35.     k = 2
  36.     print(zc(A,k))
  37.     A = [0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1]
  38.     k = 3
  39.     print(zc(A,k))
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-1-18 12:50:39 | 显示全部楼层
godfishs 发表于 2020-1-18 12:49
import itertools

def max_1(lis):  #求由0,1组成的A数组仅包含 1 的最长连续子数组的长度

解答错误

输入:[0, 0, 0, 1],k = 4
输出:None
预期结果:4
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-18 15:40:38 | 显示全部楼层
帮godfishs改下,看看效率怎样
  1. from itertools import combinations as ct
  2. def max_1(lis):  #求由0,1组成的A数组仅包含 1 的最长连续子数组的长度
  3.     c, re = 0, 0
  4.     for i in lis:
  5.         if i == 1: c += 1
  6.         else:
  7.             if c > re : re = c
  8.             c = 0
  9.     if c > re: re = c
  10.     return re

  11. def zc(A,k):
  12.     index = []
  13.     re = 0
  14.     for i in range(len(A)):
  15.         if A[i] == 0: index.append(i)    #分析数组A,找到数字为0的位置
  16.     if k > len(index): return len(A)     #k比0的个数还多的情况
  17.         
  18.     for i in ct(index,k):   #从index列表记录的0的位置中取出k个0的位置,每一个i是一种不同取法
  19.         temp = A.copy()  #必须用一个复制的原列表用作计算
  20.         for j in range(k):  #把对应该种取法的0位置换为1
  21.             temp[i[j]] = 1
  22.         max_temp = max_1(temp)  #计算最大子组的长度
  23.         if max_temp > re:
  24.             re = max_temp
  25.     return re
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-23 17:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表