楼主: SDFS
跳转到指定楼层
上一主题 下一主题
收起左侧

[Leetcode] 求问一道面经算法题,不知道用哪种方法

🔗
a49481 2022-3-31 14:14:56 | 只看该作者
全局:
本帖最后由 a49481 于 2022-3-30 23:26 编辑
a49481 发表于 2022-3-30 22:07
这是一个np问题,简单的证明如下:
(1)可以简单的理解为原问题是:限制子数组的和,求二维数组的长度最 ...

原先的证明思路太绕,而且不严谨,但是可以很确定地说这个就是一个NP问题,证明NP的更好的思路是这样:
(1)首先,可以简单的理解为原问题是:限制子数组的和不超过Limit,求二维数组的长度Length最小值L_min。我们假设我们有一个算法A,可以在T时间内得到这个问题的解;
(2)现在,记原数组内所有数的和为s,然后令Limit = s / 2,求二维数组的长度Length最小值L_min。我们发现,一旦知道了L_min的值,通过比较L_min和2的大小关系,我们就可以得到以原数组为input的Partition Problem的解(如果L_min > 2,Partition Problem的答案就是no,否则就是yes)。因此,在知道原问题的算法A的运行结果情况下,我们可以在常数时间内得到Partition Problem的答案,也就是说通过算法A,Partition Problem也能在T时间内得到答案。
(3)因此,原问题至少和Partition Problem有一样计算复杂度。由于Partition Problem是NP问题,因此原问题是NP问题。


关于什么是Partition Problem,可以看这里:https://en.wikipedia.org/wiki/Partition_problem
回复

使用道具 举报

🔗
lu9999 2022-3-31 15:14:26 来自APP | 只看该作者
全局:
换个思路,还是取最大数,剩下递归,找最长数列,然后剩下的继续?
回复

使用道具 举报

🔗
yangff 2022-3-31 18:07:07 | 只看该作者
全局:
回复

使用道具 举报

🔗
yangff 2022-3-31 18:15:52 | 只看该作者
全局:
a49481 发表于 2022-3-31 01:14
原先的证明思路太绕,而且不严谨,但是可以很确定地说这个就是一个NP问题,证明NP的更好的思路是这样:
...

是Bin packing problem,没理解错的话应该是一摸一样
回复

使用道具 举报

全局:
lu9999 发表于 2022-03-31 00:14:26
换个思路,还是取最大数,剩下递归,找最长数列,然后剩下的继续?
肯定也不对
第一,如何找最长序列?
第二,最长序列肯定是从小数开始。如果把小数都用了,后面的大数就不好配对了
回复

使用道具 举报

🔗
HOI3CHI 2022-4-1 01:40:47 | 只看该作者
全局:

881可以greedy,因为881最多两个人一艘船,这里则没有限定。
回复

使用道具 举报

🔗
南宫狗剩 2022-4-1 03:57:41 | 只看该作者
全局:
这道题不能用greedy来算,我来个反例:list = [2,2,2,2,3,3], limit = 7。greedy的结果是[2],[2,2,2],[3,3],但结果应该是[2,2,3],[2,2,3]。记得leetcode上有个类似的周赛题,印象中最后就是暴力算的。
不过考虑到这是公司面试题,盲猜是考官没想明白打算让你greedy的
回复

使用道具 举报

全局:
yangff 发表于 2022-03-31 03:15:52
是Bin packing problem,没理解错的话应该是一摸一样
很棒,直觉告诉我这一定是一个有名字的问题,但是我找不到,只能想办法证明。非常感谢科普!
回复

使用道具 举报

🔗
SoWhat0309 2022-4-1 05:28:26 | 只看该作者
全局:
感觉是直球BinPacking, Greedy应该只能用来估算的(这个问题还有一堆估计算法)。

NP completeness and Hardness proof: https://cs.ubishops.ca/home/cs567/more-np-complete/rangasamy-bin-packing.pdf

乱写的DP解:

  1. from typing import List
  2. class Solution:
  3.     def minimumBinPacking(self, nums: List[int], capacity: int):
  4.         # if the sum of a subset is less than capacity
  5.         def valid_subset(mask):
  6.             acc = 0
  7.             for i, x in enumerate(nums):
  8.                 if (mask>>i)&1 == 0:
  9.                     continue
  10.                 acc += x
  11.                 if acc > capacity:
  12.                     return False
  13.             return True
  14.         
  15.         n = len(nums)     
  16.         valid_subsets = {state for state in range(1<<n) if valid_subset(state)}
  17.         dp = [float('inf') for _ in range(1<<n)]
  18.         dp[0] = 0
  19.         
  20.         # iterate through all states
  21.         for state in range(1, 1<<n):
  22.             subset = state
  23.             # iterate through all subsets
  24.             while subset > 0:
  25.                 if subset in valid_subsets:
  26.                     dp[state] = min(dp[state], 1 + dp[state-subset])
  27.                 subset = (subset-1)&state
  28.         return dp[-1]


  29. if __name__ == "__main__":
  30.     s = Solution()
  31.     assert s.minimumBinPacking([1, 2, 2, 3, 4, 5, 6], 6)==4, "first test case failed"
  32.     assert s.minimumBinPacking([2, 2, 2, 3, 3, 5], 6)==3, "second test case failed"
  33.     assert s.minimumBinPacking([2,4,4,6,7,7,10], 20) == 2, "third test case failed"
复制代码
回复

使用道具 举报

全局:
HOI3CHI 发表于 2022-03-31 10:40:47
881可以greedy,因为881最多两个人一艘船,这里则没有限定。
用一个stack就能greedy了。stack里的元素是船,数组从大到小往船上加,船装满了==limit就pop出去,没装满<limit但装不下next person就留在stack里,往里push下一条船。最后看一共create了几条船

补充内容 (2022-04-02 04:18 +08:00):
错了,不是stack,是min pq
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

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