当前位置: 首页 > 知识库问答 >
问题:

Brut Force“Subarray产品小于K”

刘博雅
2023-03-14

我试图使用递归来解决这个问题,获取所有连续的子数组,然后检查

给你一个正整数数组nums。计算并打印子数组中所有元素的乘积小于k的(连续)子数组的数量

此时我写了这部分代码:

def product_arr(array):
    counter = 1
    for i in range(len(array)):
        counter *= array[i]
    return counter


def numSubArray(array, k):
    if len(array) == 0:
        return 0
    if product_arr(array) <= k:
        return 1
    res_1 = numSubArray(array[1:], k//array[0])
    res_2 = numSubArray(array[:-1], k//array[-1])

    return 1 + res_1 + res_2

但它不起作用...它现在正在打印“15”而不是“8”,用于:

arr = [10, 5, 2, 6]
print(numSubArray(arr, 100))

感谢您抽出时间:)

共有1个答案

李招
2023-03-14

如果你用简单的英语(或者你最熟悉的任何语言)拼出你认为递归关系是什么样子的,这通常会有所帮助,而且我有理由相信你的递归想法是错误的。你写的是这样的:

  1. 在空数组中,没有子数组(但您返回而不是0。为什么?
  2. 如果数组中所有数字的乘积小于k,则子数组的数量为1。
  3. 否则,如果我们删除第一项,则是子数组的数量,如果我们删除第二项,则加上子数组的数量。

这三点都有问题。首先,在1中,应该返回0而不是“nothing”。空数组没有连续子数组,因此“0”是正确答案。

现在来看第2行。您的<code>返回1

该逻辑的修复方法是:不返回1,而是返回'1 res1 res2'。

现在让我们来看看你的递归逻辑:

您说:“要计算给定数组的所有连续子数组,使其乘积小于 k,我们首先计算该数组中不包含数组第一个元素的所有连续子数组。然后,我们计算该数组中不包含数组最后一个元素的所有连续子数组。我们将这两个数字相加,最后,我们检查总数组的乘积是否小于或等于k,如果是这种情况,则加1。

递归逻辑的问题是您将重复计算数组“中间”的一些数组!它们既不包含第一个也不包含最后一个元素!

不过,你的思维方向是正确的!这种“除了第一个之外的一切”和“除了最后一个之外的一切”的递归在comp sci和数学中到处出现。诀窍是你需要稍微调整一下,以“强制”你的公式考虑第一个元素:

我们想要的是:给定我的数组,有多少个合适的连续子数组肯定包含第一个元素,但肯定不包含最后一个元素?以及有多少个连续的子数组肯定包含最后一个元素,但肯定不包含第一个元素?

您已经获得了“不包含第一个/最后一个”元素部分,以及数组索引。现在,我们如何“强制”它包含第一个元素?通过也将其从索引中删除并相应地调整k。

以下是我的意思的一个例子:

有多少个连续子阵列满足< code>[10,5,2,6]的条件,其中< code>k = 100,因此它们包含< code>10,但不包含< code>6?

与满足[5,2]条件且k=10的连续子数组一样多。基本上,通过从数组中删除10并将k除以10我们说:“哦,是的,我们肯定是在选择10,所以我们必须相应地调整k”。

因此,在递归中,在这两种情况下,它都将是数组[1:-1]k,替换为k/array[0]k/array[-1](请确保选择正确的一个,并花一些时间思考整数除法和舍入,这是我留给您的练习:p)

这应该会让你很好地解决它,但是现在这里有一个额外的技巧来加快速度。快速问题,无需太多思考,[1,2,3,4,5,]的多少连续子数组的乘积小于1000?答案:所有。所以如果你先计算数组的乘积,并且它小于k,你就不需要再进行蛮力递归了!你“只”需要计算这些连续子数组的总数!根据你的背景,这是一个简单的组合问题。

编辑:再思考一下:)好的,让我们思考一下如何解决这个问题。首先,如果你真的想使用暴力,你只需要创建每一个可能的连续子阵列并检查其乘积:

count = 0
for start in range(0, len(array)):
  for end in range(start+1, len(array)):
    if product_arr(array[start:end]) <= k:
      count += 1

不幸的是,它的运行时间是O(N^3),因为你实际上有三个嵌套循环。

这一切让我想起的是最大和邻接子阵列问题:https://www.geeksforgeeks.org/largest-sum-contiguous-subarray/

这可以用O(N)来解决,我认为一般的想法也可以用在这里,但是你不用跟踪最大值,而是跟踪“工作”的子阵列的数量,并且你以一种聪明的方式这样做...

您将运行一个具有“子数组的开始”的循环,然后在另一个具有“子数组的结束”的循环中运行。您不断将末尾增加1,并检查将该额外整数添加到产品中是否使您低于“k”。如果是这样,你继续前进,并通过“结束 - 开始1”增加你的子数组计数。这是加快速度的关键技巧。基本上,您不仅要计算一个新识别的子阵列,还要计算通过删除第一个,第二个,第三个元素等元素获得的所有其他子阵列。因为如果 a * b * c

这是一个有点棘手的数字边界和确切的细节,但我不能帮助你。

 类似资料:
  • 先说面试感受:一脸懵逼。。。 自我介绍 询问对B/C端理解 介绍一下简历里某一个需求,没问问题 介绍一下实习里做发版工作的流程,没问问题 然后就很突然地开始了英语面试。在此之前根本不知道有英语要求 晕倒 英语问题 实习里印象最深的事情是什么 为什么 掌握了产品经理的哪些软能力 怎么习得的 通过什么方式培养的 后续要求来北京实习的话 base方便吗 直接结束 无反问环节给到 还是太没见过世面了 ,很

  • 1.三句话介绍一下自己 2.人工智能在家居层面能给用户带来什么 3.深挖实习和项目经历 4.未来还想做策略产品吗?

  • #非技术2024笔面经# 昨天面试了小米,整体下来还是聊的很开心的,但是觉得应该还在鱼,,发发面经积攒人品了! 1.自我介绍 2.介绍美团的实习中最满意的项目 3.用什么指标评价你这个产品的好坏和下一步迭代方向 (本人是做对内的产品,所以其实评价好坏很主观...) 4.下一步迭代做什么 (本来是想实习转正的,这个问题也确实想到过) 5.快手的项目 (扒简历....) 6.快手的实习中,你的项目成果

  • 很像数据分析的一次面试,没准备好,只能说感谢面试官的时间吧 1.自我介绍 2.SQL题 可能难度比不上大厂数据分析笔试题,但是我能力不行没答上来,还是需要多练才行 占个坑,明天补上 3.Excel题 1.对多列数据怎么去除重复值 合并两列成一列再去重 2.Excel怎么实现随机取出1000条数据 用rand生成随机数降序排列取1000条 然后挂了,但是心态良好,笑着准备和小姐姐咨询一下策略产品的内

  • 对小米产品运营岗位的认识?(上来没让自我介绍,还挺“反套路”的,这种不用自我介绍直接开问的会莫名让人感觉挺慌张的。我讲完了之后,面试官给我再细讲了一下岗位具体的工作职责) 深挖之前的实习经历(具体目标用户是谁?做了哪些事得到了哪些反馈?反馈里面有多少是因为你的事情导致的?) 看到简历上写了做过数据埋点,再简单问了下相关的问题(跟实习项目有关的,比如为啥做数据埋点,想知道什么?等等) 问了下A/B

  • 岗位:ai产品经理-小爱语音 日常实习(已oc) 8.22二面 1.个人自我介绍 2.实习里广告投放的类型 3.漏斗模型的用户分层,对广告账户划分哪几类,打了什么样的标签? 4.如何判断客群具备更高消费能力? 5.基于什么样的考虑向换产品的工作方向呢 6.讲一下快手的实习经验 7.流量策略分发的内容具体是什么? 8.在全站流量中,你所在业务占比多少 9.实习时间、就业方向是否确定、最快到岗时间 反