Search code examples
algorithmlanguage-agnostictime-complexitycomplexity-theoryrecurrence

Time complexity for a very complicated recursion code


I have some problem while trying to calculate time complexity for this code:

function foo (int a):
    if a < 1: 
        return 1
    else:
        for i = 1 to 4:
            foo(a - 3)
        for i = 1 to 4:
            foo(a / 2)
end function

As far as I can go:

T(n) = 1 if n<1

T(n) = 4T(n-3) + 4T(n/2)     if n>=1

     = 4(4T(n-6) + 4T((n-3)/2))  +  4(4T(n/2 - 3) + 4T(n/4))

     ~ 4^2 (T(n-6) + T((n-3)/2) + T(n/2-3) + T(n/4))

Now, it is very complicated, since number of the next T increase by 2^n and also the child is quite complicated.

Is there any other ways to solve this problem?


Solution

  • Let's expand the recursive cost function:

    T(n) = 4   [T(n-3) + T(n/2)]
    T(n) = 4^2 [T(n-6) + T((n-3)/2) + T((n-6)/2) + T(n/4)]
    T(n) = 4^n [T(n-9) + 2*T((n-6)/2) + T((n-9)/2) + T((n-12)/4) + T((n-3)/4) + T((n-6)/4) + T(n/8)]
    

    From the moment the x in T(x) drops below 1, you should replace T(x) with 1. And from that moment on, the T(x) doesn't generate any "children" anymore so to speak.

    what does this means? It means that after the k-'th expansion of T(n), the function will look like:

    T(n) = 4^k [number of paths with length `k`]
    

    and keep increasing k until all paths have "died". This is definitely the case after n/3 iterations, because that's the longest possible path.

    We thus have some kind of graph, for instance for n=9:

    9 + 6 + 3 + 0
      |   |   ` 1
      |    `3 + 0
      |       ` 1
       `4 + 1
          ` 2 + -1
             `  1
    

    so 6 paths. Now the problem is how to count the number of paths. In order to do this we will first represent the main path: n, n-3, n-6, etc. as a horizontal line of nodes, this is definitely the longest path:

    n    n-3  n-6  n-9  ...  1
    

    Now out of all these nodes, do originate nodes of i -> i/2 (except for one)

    n    n-3      n-6      n-9     ...   4   1
    |     |        |         |
    n/2  (n-3)/2  (n-6)/2  (n-9)/2 ...   2
    

    (the second row shows all nodes created by divisions by 2). Now these nodes, generate again offsprong n -> n-3, which is, since it is divided by two n/2 -> (n-6)/2, in other words, there are edges that make jumps of two:

    n    n-3      n-6      n-9     ...   4   1
    |     |  /-----+-------(n-9)/2       |
    n/2  (n-3)/2  (n-6)/2  (n-9)/2 ...   2
      \---------->(n-6)/2 \------->...
    

    on other words, except for the first two elements, all other nodes in the second row count for two. If we would represent it as some kind of graph with the nodes labeled by their weight, it would look like:

       1 -- 1 -- 1 -- 1 -- 1 -- .. -- .. -- 1
       |    |    |    |    |    |     |
       1 -- 1 -- 2 -- 2 -- 2 -- .. -- 2
    

    Or if we keep doing this for this process:

       1 -- 1 -- 1 -- 1 -- 1 -- .. -- .. -- .. -- .. -- ..-- 1
       |    |    |    |    |    |     |     |     |     |
       1 -- 1 -- 2 -- 2 -- 2 -- .. -- .. -- .. -- .. -- 2
       |    |    |    |    |    |     |     |
       1 -- 1 -- 2 -- 2 -- 3 -- .. -- .. -- 4
    

    (the third row generates children 4 items further)

    Now we need to calculate the sum of the last row. This is at most O(log n).

    Which thus results in an upper bound of O(4^(n/3)*log n) maximum. It is definitely possible that the bound is tighter, or 4^(n/3+epsilon), the log doesn't really matter when it comes down to the exponent.

    Experiments

    One can turn the program into a program that calculates the cost (used Python):

    def memodict(f):
        """ Memoization decorator for a function taking a single argument """
        class memodict(dict):
            def __missing__(self, key):
                ret = self[key] = f(key)
                return ret
        return memodict().__getitem__
    
    @memodict
    def foo (a):
      if a < 1:
        return 1
      else:
        return 1+4*(foo(a-3)+foo(a//2))
    
    for i in range(1000) :
        print '{0} {1}'.format(i,foo(i))
    

    mind the 1+ (this is due to the fact that calling a method not at the leaves requires computational cost as well).

    It shows the following graph (with the y axis in log space):

    complexity graph

    If one looks very closely it looks as if log n is a better estimate. Although I don't know if it is safe to say this.

    This results in a table (below, calculated it further up to 2'000).

    1 9
    2 41
    3 41
    4 201
    5 329
    6 329
    7 969
    8 2121
    9 2121
    10 5193
    11 9801
    12 9801
    13 22089
    14 43081
    15 43081
    16 96841
    17 180809
    18 180809
    19 395849
    20 744009
    21 744009
    22 1622601
    23 3015241
    24 3015241
    25 6529609
    26 12149321
    27 12149321
    28 26290761
    29 48769609
    30 48769609
    31 105335369
    32 195465801
    33 195465801
    34 422064713
    35 782586441
    36 782586441
    37 1688982089
    38 3131929161
    39 3131929161
    40 6758904393
    41 12530692681
    42 12530692681
    43 27038593609
    44 50129261129
    45 50129261129
    46 108166435401
    47 200529105481
    48 200529105481
    49 432677802569
    50 802142540361
    51 802142540361
    52 1730759807561
    53 3208618758729
    54 3208618758729
    55 6923087827529
    56 12834580197961
    57 12834580197961
    58 27692546388553
    59 51338515870281
    60 51338515870281
    61 110770380632649
    62 205354484822601
    63 205354484822601
    64 443082304393801
    65 821418721153609
    66 821418721153609
    67 1772329999438409
    68 3285676572873289
    69 3285676572873289
    70 7089323128099401
    71 13142709421838921
    72 13142709421838921
    73 28357295642743369
    74 52570844443284041
    75 52570844443284041
    76 113429195098690121
    77 210283390300852809
    78 210283390300852809
    79 453716792922477129
    80 841133588239028809
    81 841133588239028809
    82 1814867221812679241
    83 3364534403078885961
    84 3364534403078885961
    85 7259468937373487689
    86 13458137720469918281
    87 13458137720469918281
    88 29037875950010995273
    89 53832551082396717641
    90 53832551082396717641
    91 116151504000561025609
    92 215330204762252612169
    93 215330204762252612169
    94 464606016804360524361
    95 861320819851126870601
    96 861320819851126870601
    97 1858424068019558519369
    98 3445283281135218692681
    99 3445283281135218692681
    100 7433696275286804238921
    101 13781133127749444932169
    102 13781133127749444932169
    103 29734785104355787117129
    104 55124532517920818958921
    105 55124532517920818958921
    106 118939140430257623503433
    107 220498130084517750870601
    108 220498130084517750870601
    109 475756561733864969048649
    110 881992520365763354792521
    111 881992520365763354792521
    112 1903026246986798196986441
    113 3527970081514391739961929
    114 3527970081514391739961929
    115 7612104987998531108737609
    116 14111880326168337145401929
    117 14111880326168337145401929
    118 30448419952199478498431561
    119 56447521304878702645088841
    120 56447521304878702645088841
    121 121793679809003268057207369
    122 225790085219957892102885961
    123 225790085219957892102885961
    124 487174719236834490168119881
    125 903160340880652986350834249
    126 903160340880652986350834249
    127 1948698876948159378611769929
    128 3612641363524384274620912201
    129 3612641363524384274620912201
    130 7794795507795923189331694153
    131 14450565454100822773368263241
    132 14450565454100822773368263241
    133 31179182031186978432211391049
    134 57802261816410380413470806601
    135 57802261816410380413470806601
    136 124716728124761056435137057353
    137 231209047265654664360174719561
    138 231209047265654664360174719561
    139 498866912499057368446839722569
    140 924836189062647014733211275849
    141 924836189062647014733211275849
    142 1995467649996282044625046245961
    143 3699344756250640629770532459081
    144 3699344756250640629770532459081
    145 7981870599985180749337872339529
    146 14797379025002675948264700809801
    147 14797379025002675948264700809801
    148 31927482399940933280729262494281
    149 59189516100010914076436576375369
    150 59189516100010914076436576375369
    151 127709929599763943406294823113289
    152 236758064400044110022526700261961
    153 236758064400044110022526700261961
    154 510839718399056614758740495864393
    155 947032257600177281223668004459081
    156 947032257600177281223668004459081
    157 2043358873596227300168523186868809
    158 3788129030400710939761843707744841
    159 3788129030400710939761843707744841
    160 8173435494384912565208445703590473
    161 15152516121602847123581727787094601
    162 15152516121602847123581727787094601
    163 32693741977539653625368135770477129
    164 60610064486411395753795798399095369
    165 60610064486411395753795798399095369
    166 130774967910158627959610155397452361
    167 242440257945645596473320805911925321
    168 242440257945645596473320805911925321
    169 523099871640634525296578233905353289
    170 969761031782582414931158973141652041
    171 969761031782582414931158973141652041
    172 2092399486562538155018863817501086281
    173 3879044127130329713557186774446281289
    174 3879044127130329713557186774446281289
    175 8369597946250152673908006151884018249
    176 15516176508521318970380250897829106249
    177 15516176508521318970380250897829106249
    178 33478391785000610910962228937122943561
    179 62064706034085276096851207920903295561
    180 62064706034085276096851207920903295561
    181 133913567140002443859179120078078644809
    182 248258824136341104852010847685857284681
    183 248258824136341104852010847685857284681
    184 535654268560009776298037299361325027913
    185 993035296545364420269364209792439587401
    186 993035296545364420269364209792439587401
    187 2142617074240039106053470016494310560329
    188 3972141186181457682935880906387200447049
    189 3972141186181457682935880906387200447049
    190 8570468296960156427659163345381749723721
    191 15888564744725830735188806904953309270601
    192 15888564744725830735188806904953309270601
    193 34281873187840625714081936660931506377289
    194 63554258978903322948188923891891471159881
    195 63554258978903322948188923891891471159881
    196 137127492751362502870108879768266900279881
    197 254217035915613291806536828692106759410249
    198 254217035915613291806536828692106759410249
    199 548509971005450011494216652197608475890249
    200 1016868143662453167255882099869574254596681