简体   繁体   中英

Sum of quotients when all array elements is divided by each array elements

Came across a question in the coding test, suppose we have array, arr = [4,3,8] . Dividing array by 4 gives 1(4/4) + 0(3/4) + 2(8/4) = 3. Similarly by 3 gives 4 and by 8 gives 1. So the output is 3+4+1 = 8. O(n2) solution gave TLE, so I tried to do better.

I thought of sorting and using lower bound. Lower Bound of arr[i]*k , for k = 1,2,3... , till arr[i]*k<=max(arr) , will give me number of elements greater than the multiple taken, this will add in the final result. But this gave me wrong answer. How can I solve this problem efficiently, any suggestions are welcome.

If I understand your question correctly, you want (in this example) three arrays which are the orignal array divided (with whole number division) by each of its three elements and then sum over them.

arr = [4,3,8]
sum([el//i for i in arr for el in arr])

will give you the wanted result. For understanding, the resulting list is:

In [8]: [el//i for i in arr for el in arr]
Out[8]: [1, 0, 2, 1, 1, 2, 0, 0, 1]

Summing over this gives the result 8 . If you really need the three arrays seperate and not concatenated in this way, I will edit this answer.

EDIT So I misunderstood the question, sorry. If you are allowed to use numpy, I would propose this algorithm, which (I think) still is O(n²), but overall much faster:

arr = np.random.randint(1,10,n)
np.sum(np.tile(arr, n)//np.repeat(arr,n))

Maybe I can come up with something more intelligent tomorrow

EDIT 2 Sorting actually is a good idea and speeds up the algorithm a bit. I tested the three solutions so far with this litte script (I know, that time.time is not good for exact times, but it just shows the general speed of each algorithm):

for n in range(100, 500):
    arr = np.random.randint(1,10,n)
    #sorted
    t = time.time()
    arr2 = sorted(arr)
    sum([el1//el2 for i, el2 in enumerate(arr2) for el1 in arr2[i:]])
    t2 = time.time()-t
    times_sorted.append(t2)

    #standard
    t = time.time()
    arr = sorted(arr)
    sum([el1//el2 for el2 in arr for el1 in arr])
    t2 = time.time()-t
    times_standard.append(t2)

    #numpy
    t = time.time()
    arr = sorted(arr)
    np.sum(np.tile(arr, n)//np.repeat(arr, n))
    t2 = time.time()-t
    times_numpy.append(t2)
    if not n%50:
        print(n)

Plotting with

plt.figure()
plt.plot(times_numpy)
plt.plot(times_sorted)
plt.plot(times_standard)
plt.legend(["numpy", "sorted", "standard"])
plt.xlabel("n")
plt.ylabel("time in s")

Gives:

对照

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM