• 请不要在回答技术问题时复制粘贴 AI 生成的内容
hzlzh
63.68D
V2EX  ›  程序员

[一道有趣的算法题] 各种语言都来试试吧~

  •  
  •   hzlzh ·
    hzlzh · Apr 3, 2013 · 8624 views
    This topic created in 4963 days ago, the information mentioned may be changed or developed.
    ## 目的
    没什么目的,就是好玩,最近大伙在做一道有趣的算法题,拿来大家分享一下,有兴趣的可以试试。

    ## 题目描述:
    Have the function ArrayAdditionI(arr) take the array of numbers stored in arr and return the string true if any combination of numbers in the array can be added up to equal the largest number in the array, otherwise return the string false. For example: if arr contains [4, 6, 23, 10, 1, 3] the output should return true because 4 + 6 + 10 + 3 = 23. The array will not be empty, will not contain all the same elements, and may contain negative numbers.

    ## 也就是说:
    如:[4, 6, 23, 10, 1, 3] 这个数组(数字不重复,可以为负数)中选出最大的数字是 23
    4+6+10+3 = 23
    然后剩余的任意个数字数相加之和若等于23,则 true,否则false

    ## 测试用例:
    输出--输入
    false--[5, 7, 16, 1, 2]
    false--[1, 22, 23, 24, 27, 29, 33]
    true--[1, 22, 23, 25, 26] 注:25+1 = 26
    true--[3, 5, -1, 8, 1, -2, 12] 注:5+(-1)+8 = 12

    ## 要求:
    书写语言不限,不能是思路或伪代码,用如: php,python,js...等都可以在网站里运行检查

    ## 出处:
    题目来源:
    http://coderbyte.com/
    时间要求:当然是越快越好

    enjoy!

    ps: 写出来的童鞋可以 [只贴Gist ID,如:/xxxx/123456] ,你懂得,别影响了别人思路。
    Supplement 1  ·  Apr 3, 2013
    ## 此题目的原地址:
    http://coderbyte.com/CodingArea/information.php?ct=Array%20Addition%20I
    ## 官方定级:easy
    30 replies  •  1970-01-01 08:00:00 +08:00
    AlloVince
    AlloVince
    Apr 3, 2013
    1
    用内置函数只需2行

    function testArray(array $array){
    sort($array);
    if(array_pop($array) == array_sum($array))
    return true;
    return false;
    }
    echo testArray(array(4, 6, 23, 10, 3));

    PS:你给出的例子是错的,[4, 6, 23, 10, 1, 3], 4+6+10+1+3 = 24
    SonicXP
    SonicXP
    Apr 3, 2013
    2
    @AlloVince if any combination of numbers in the array can be added up to equal the largest number in the array
    alexrezit
    alexrezit
    Apr 3, 2013 via iPad
    3
    只会穷举的算法弱菜灰过...
    best1a
    best1a
    Apr 3, 2013
    4
    目测排序后DP?
    算了,还是去做毕设吧。。。
    xunyu
    xunyu
    Apr 3, 2013
    5
    不要用排序,一次遍历求和,同时找到最大值,用和减去最大值判断是否等于最大值就可以了
    200
    200
    Apr 3, 2013
    6
    背包 = =
    hzlzh
    hzlzh
    OP
    Apr 3, 2013
    7
    @AlloVince 你理解错误,我给的例子没错。没要求剩下数字都要用
    如:true--[1, 22, 23, 25, 26] 注:25+1 = 26
    66450146
    66450146
    Apr 3, 2013
    8
    去掉最大数之后就是很典型的 01 背包问题
    lookhi
    lookhi
    Apr 3, 2013
    9
    一场复杂的背包啊
    我就选择跳过了 看楼上楼下的了
    kilimanjaroup
    kilimanjaroup
    Apr 3, 2013
    11
    @66450146 不是吧,01背包要求非负
    zxc111
    zxc111
    Apr 3, 2013
    12
    @kilimanjaroup 全加上最大负数的绝对值,结果作相应处理
    AlloVince
    AlloVince
    Apr 3, 2013
    13
    @SonicXP
    @hzlzh

    sorry,没有仔细看题。

    php的话更多应该是求一个数组的子集:

    https://gist.github.com/AlloVince/5298390
    limu
    limu
    Apr 3, 2013
    14
    RisingV
    RisingV
    Apr 3, 2013
    15
    穷举的危害是会有很多重复的子计算,只要在穷举基础上加上简单的防止重复子计算的措施就行了。
    简单且高效。
    laskuma
    laskuma
    Apr 3, 2013
    16
    01背包+binary search优化
    bhuztez
    bhuztez
    Apr 3, 2013
    17
    这分明就是Hello, world!级的Prolog题

    $ swipl
    Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.0.2)
    Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
    SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
    and you are welcome to redistribute it under certain conditions.
    Please visit http://www.swi-prolog.org for details.

    For help, use ?- help(Topic). or ?- apropos(Word).

    ?- ['addition.pl'].
    % library(clpr) compiled into clpr 0.06 sec, 2,498 clauses
    % library(option) compiled into swi_option 0.00 sec, 32 clauses
    % pure_input compiled into pure_input 0.00 sec, 48 clauses
    % library(pio) compiled into pio 0.00 sec, 52 clauses
    % library(simplex) compiled into simplex 0.08 sec, 2,835 clauses
    % addition.pl compiled 0.08 sec, 2,867 clauses
    true.

    ?- once(solve([4, 6, 23, 10, 1, 3], _)).
    true.

    ?- once(solve([4, 6, 23, 10, 1, 3], R)).
    R = [{10, 1}, {6, 1}, {4, 1}, {3, 1}, {1, 0}].

    ?- once(solve([5, 7, 16, 1, 2], _)).
    false.

    ?- once(solve([1, 22, 23, 24, 27, 29, 33], _)).
    false.

    ?- once(solve([1, 22, 23, 25, 26], _)).
    true.

    ?- once(solve([1, 22, 23, 25, 26], R)).
    R = [{25, 1}, {23, 0}, {22, 0}, {1, 1}].

    ?- once(solve([3, 5, -1, 8, 1, -2, 12], _)).
    true.

    ?- once(solve([3, 5, -1, 8, 1, -2, 12], R)).
    R = [{8, 1}, {5, 1}, {3, 0}, {1, 0}, {-1, 1}, {-2, 0}].

    ?-
    hzlzh
    hzlzh
    OP
    Apr 3, 2013
    18
    @bhuztez 看这里,这题的官方定级是 easy,
    [Array Addition I]
    http://coderbyte.com/CodingArea/Challenges/
    hpyhacking
    hpyhacking
    Apr 4, 2013
    19
    排序后剔除max,计算剩余sum
    sum < max -> false
    sum = max -> true
    sum > max -> combos(sum).each do |c|
    sum(c) == max ? true : continue
    false
    hpyhacking
    hpyhacking
    Apr 4, 2013
    20
    肯定还有其他更好的解法,数组长了上面的程序直接PASS掉。
    breakind
    breakind
    Apr 4, 2013
    21
    这道题实质上就是求一个数组所有的子集,下面用python实现一个,使用的二进制取位来列举所有的子集
    test1 = [5, 7, 16, 1, 2]
    test2 = [1, 22, 23, 24, 27, 29, 33]
    test3 = [1, 22, 23, 25, 26]
    test4 = [3, 5, -1, 8, 1, -2, 12]

    def getSubArraySum(array,index):
    arrayLength = len(array)
    sum = 0
    for i in range(arrayLength):
    if (index>>(arrayLength - i - 1))&1 == 1:
    sum += array[i]
    return sum
    def checkArray(array):
    tempArray = array
    maxValue = max(tempArray)
    del tempArray[tempArray.index(maxValue)]
    istrue = False
    for i in range(2**len(tempArray)):
    if maxValue == getSubArraySum(array,i):
    istrue = True
    return istrue
    return istrue

    print checkArray(test1)
    print checkArray(test2)
    print checkArray(test3)
    print checkArray(test4)
    breakind
    breakind
    Apr 4, 2013
    22
    错了一点,上面if maxValue == getSubArraySum(array,i):应该为if maxValue == getSubArraySum(tempArray,i):
    skywalker
    skywalker
    Apr 5, 2013
    23
    Haskell:

    import Data.List

    chkArr :: Int -> [Int] -> Bool
    chkArr amount arr
    | amount == 0 = True
    | null arr || amount < 0 = False
    | otherwise = chkArr (amount-(head arr)) (tail arr) || chkArr amount (tail arr)

    testArr :: [Int] -> Bool
    testArr xs = chkArr (head ys) (tail ys)
    where ys = sortBy (flip compare) xs
    monkeylyf
    monkeylyf
    Apr 5, 2013
    24
    https://gist.github.com/monkeylyf/5315975

    ”if any combination of numbers in the array can be added up to equal the largest number in the array“ 我对题目的理解是任意组合加起来等于最大的那个, 没说任意组合里不可以有最大的这个数
    所以有一个test case 说我的结果不正确:[10,12,500,1,-5,1,0]
    私以为, 所以存在组合0 + 500 = 500. 应该return true

    思路是0/1 knapsack 没有优化 目测这个网站的大数据测试很水
    skywalker
    skywalker
    Apr 5, 2013❤️1
    25
    @monkeylyf 如果可以包含最大那个元素, 那肯定都要返回true了, 因为最大元素自己肯定等于自己.
    monkeylyf
    monkeylyf
    Apr 5, 2013
    26
    @skywalker 有道理. 题目可以写的再清晰点.
    monkeylyf
    monkeylyf
    Apr 5, 2013
    27
    又看了下题目 这题含有负数 背包解不了 还是直接穷举吧
    hzlzh
    hzlzh
    OP
    Apr 5, 2013
    28
    @monkeylyf 用递归做一个最优递归。
    lehui99
    lehui99
    Apr 5, 2013
    29
    @xunyu 不要用排序,一次遍历求和,同时找到最大值,用和减去最大值判断是否等于最大值就可以了
    +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1
    hzlzh
    hzlzh
    OP
    Apr 5, 2013
    30
    @xunyu
    @lehui99 建议仔细看下题目和用例。
    true--[1, 22, 23, 25, 26] 注:25+1 = 26
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1631 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 72ms · UTC 18:04 · PVG 02:04 · LAX 10:04 · JFK 13:04
    ♥ Do have faith in what you're doing.