|
| 1 | +''' |
| 2 | +Fancy Sequence |
| 3 | +
|
| 4 | +Write an API that generates fancy sequences using the append, addAll, and multAll operations. |
| 5 | +
|
| 6 | +Implement the Fancy class: |
| 7 | +- Fancy() Initializes the object with an empty sequence. |
| 8 | +- void append(val) Appends an integer val to the end of the sequence. |
| 9 | +- void addAll(inc) Increments all existing values in the sequence by an integer inc. |
| 10 | +- void multAll(m) Multiplies all existing values in the sequence by an integer m. |
| 11 | +- int getIndex(idx) Gets the current value at index idx (0-indexed) of the sequence modulo 109 + 7. If the index is greater or equal than the length of the sequence, return -1. |
| 12 | +
|
| 13 | +Input: ["Fancy", "append", "addAll", "append", "multAll", "getIndex", "addAll", "append", "multAll", "getIndex", "getIndex", "getIndex"] |
| 14 | +[[], [2], [3], [7], [2], [0], [3], [10], [2], [0], [1], [2]] |
| 15 | +Output: [null, null, null, null, null, 10, null, null, null, 26, 34, 20] |
| 16 | +Output explanation: |
| 17 | + Fancy fancy = new Fancy(); |
| 18 | + fancy.append(2); // fancy sequence: [2] |
| 19 | + fancy.addAll(3); // fancy sequence: [2+3] -> [5] |
| 20 | + fancy.append(7); // fancy sequence: [5, 7] |
| 21 | + fancy.multAll(2); // fancy sequence: [5*2, 7*2] -> [10, 14] |
| 22 | + fancy.getIndex(0); // return 10 |
| 23 | + fancy.addAll(3); // fancy sequence: [10+3, 14+3] -> [13, 17] |
| 24 | + fancy.append(10); // fancy sequence: [13, 17, 10] |
| 25 | + fancy.multAll(2); // fancy sequence: [13*2, 17*2, 10*2] -> [26, 34, 20] |
| 26 | + fancy.getIndex(0); // return 26 |
| 27 | + fancy.getIndex(1); // return 34 |
| 28 | + fancy.getIndex(2); // return 20 |
| 29 | +
|
| 30 | +========================================= |
| 31 | +The program is meant to be called many times (more than a million), and because of that, each operation should be constant time. |
| 32 | +When getIndex is called all we need to do is to take the first (getIndex index) adding+multiplying values and the last adding+multiplying values |
| 33 | +and using these 2 values do math and determine the real adding+multlplying values. |
| 34 | +When there is a new adding value, just increase the adding value with that one. |
| 35 | +When there is a new multiplying value, multiply the both adding and multiplying values. |
| 36 | +Example x=append(8): (((x + 5) + 6) + 7) * 2 = (x + 17) * 2 = x * 2 + 34 |
| 37 | +So total multiplayer is 2. |
| 38 | +And total adder is 18 (from 36/2). |
| 39 | +The result is (8+18)*2 = 52. |
| 40 | +Example y=append(9) after addAll(6) operation: |
| 41 | +(y + 7) * 2 = y * 2 + 14 |
| 42 | +The total multiplayer is the same, 2 (the previous is 1, the last is 2 that's equal to 2/1=2). |
| 43 | +But the total adder is 7, the total last adder is 18 (from 36/2) minus the previous 11 (from 5+6 with no multiplyers till that moment). |
| 44 | +The result is (9+7)*2 = 32. |
| 45 | + Time Complexity (The whole program, N operations): O(N) |
| 46 | + Time Complexity (Only one operation): O(1) |
| 47 | + Space Complexity: O(N) |
| 48 | +''' |
| 49 | + |
| 50 | +############ |
| 51 | +# Solution # |
| 52 | +############ |
| 53 | + |
| 54 | +class Fancy: |
| 55 | + def __init__(self): |
| 56 | + self.appending = [] |
| 57 | + self.adding = [] |
| 58 | + self.multiplying = [] |
| 59 | + |
| 60 | + |
| 61 | + def append(self, val: int) -> None: |
| 62 | + self.appending.append(val) |
| 63 | + |
| 64 | + if len(self.appending) > 1: |
| 65 | + self.adding.append(self.adding[-1]) |
| 66 | + self.multiplying.append(self.multiplying[-1]) |
| 67 | + else: |
| 68 | + self.adding.append(0) |
| 69 | + self.multiplying.append(1) |
| 70 | + |
| 71 | + def addAll(self, inc: int) -> None: |
| 72 | + if len(self.appending) == 0: |
| 73 | + return |
| 74 | + |
| 75 | + self.adding[-1] += inc |
| 76 | + |
| 77 | + |
| 78 | + def multAll(self, m: int) -> None: |
| 79 | + if len(self.appending) == 0: |
| 80 | + return |
| 81 | + |
| 82 | + self.adding[-1] *= m |
| 83 | + self.multiplying[-1] *= m |
| 84 | + |
| 85 | + |
| 86 | + def getIndex(self, idx: int) -> int: |
| 87 | + length = len(self.appending) |
| 88 | + if idx >= length: |
| 89 | + return -1 |
| 90 | + |
| 91 | + prevAdding = 0 |
| 92 | + prevMultiplying = 1 |
| 93 | + if idx > 0: |
| 94 | + prevMultiplying = self.multiplying[idx-1] |
| 95 | + prevAdding = self.adding[idx-1] |
| 96 | + |
| 97 | + currMultiplying = self.multiplying[-1] // prevMultiplying |
| 98 | + currAdding = self.adding[-1] - (prevAdding * currMultiplying) |
| 99 | + |
| 100 | + return (self.appending[idx] * currMultiplying + currAdding) % 1000000007 |
| 101 | + |
| 102 | + |
| 103 | +########### |
| 104 | +# Testing # |
| 105 | +########### |
| 106 | + |
| 107 | +# Test 1 |
| 108 | +fancy = Fancy() |
| 109 | +fancy.append(2) # fancy sequence: [2] |
| 110 | +fancy.addAll(3) # fancy sequence: [2+3] -> [5] |
| 111 | +fancy.append(7) # fancy sequence: [5, 7] |
| 112 | +fancy.multAll(2) # fancy sequence: [5*2, 7*2] -> [10, 14] |
| 113 | +print(fancy.getIndex(0)) # return 10 |
| 114 | +fancy.addAll(3) # fancy sequence: [10+3, 14+3] -> [13, 17] |
| 115 | +fancy.append(10) # fancy sequence: [13, 17, 10] |
| 116 | +fancy.multAll(2) # fancy sequence: [13*2, 17*2, 10*2] -> [26, 34, 20] |
| 117 | +print(fancy.getIndex(0)) # return 26 |
| 118 | +print(fancy.getIndex(1)) # return 34 |
| 119 | +print(fancy.getIndex(2)) # return 20 |
0 commit comments