简体   繁体   中英

Number of multiples less than the max number

For the following problem on SingPath:

Given an input of a list of numbers and a high number, 
return the number of multiples of each of 
those numbers that are less than the maximum number.
For this case the list will contain a maximum of 3 numbers 
that are all relatively prime to each
other.

Here is my code:

def countMultiples(l, max_num):
    counting_list = []
    for i in l:
        for j in range(1, max_num):
            if (i * j < max_num) and (i * j) not in counting_list:
                counting_list.append(i * j)
    return len(counting_list)

Although my algorithm works okay, it gets stuck when the maximum number is way too big

>>> countMultiples([3],30)
9      #WORKS GOOD

>>> countMultiples([3,5],100)
46     #WORKS GOOD

>>> countMultiples([13,25],100250)
Line 5: TimeLimitError: Program exceeded run time limit. 

How to optimize this code?

3 and 5 have some same multiples, like 15.

You should remove those multiples, and you will get the right answer

Also you should check the inclusion exclusion principle https://en.wikipedia.org/wiki/Inclusion-exclusion_principle#Counting_integers

EDIT: The problem can be solved in constant time. As previously linked, the solution is in the inclusion - exclusion principle.

Let say you want to get the number of multiples of 3 less than 100, you can do this by dividing floor(100/3), the same applies for 5, floor(100/5). Now to get the multiplies of 3 and 5 that are less than 100, you would have to add them, and subtract the ones that are multiples of both. In this case, subtracting multiplies of 15. So the answer for multiples of 3 and 5, that are less than 100 is floor(100/3) + floor(100/5) - floor(100/15). If you have more than 2 numbers, it gets a bit more complicated, but the same approach applies, for more check https://en.wikipedia.org/wiki/Inclusion-exclusion_principle#Counting_integers

EDIT2:

Also the loop variant can be speed up. Your current algorithm appends multiple in a list, which is very slow. You should switch the inner and outer for loop. By doing that you would check if any of the divisors divide the number, and you get the the divisor.

So just adding a boolean variable which tells you if any of your divisors divide the number, and counting the times the variable is true.

So it would like this:

def countMultiples(l, max_num):
  nums = 0
  for j in range(1, max_num):
    isMultiple = False
    for i in l:  
      if (j % i == 0):
    isMultiple = True
    if (isMultiple == True):
      nums += 1
  return nums

print countMultiples([13,25],100250)

If the length of the list is all you need, you'd be better off with a tally instead of creating another list.

def countMultiples(l, max_num):
    count = 0
    counting_list = []
    for i in l:
        for j in range(1, max_num):
            if (i * j < max_num) and (i * j) not in counting_list:
                count += 1
    return count

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