Calculating while Loop time complexity for the Given code - python-3.x

def smallestSubWithSum(self, a, n, x):
min1 = float('inf')
i = 0
while (i < n):
if a[i] > x :
return 1
else:
sum1 = a[i]
j = i + 1
while (j < n):
sum1 += a[j]
if sum1 > x:
m = j - i + 1
min1 = min(m,min1)
break
else:
j +=1
i +=1
return min1
I was solving the question and just thinking that time complexity for the given code should be O(n^2) since it involved two for loops. but while submitting the code it got accepted under O(n).
can someone explain me this if it O(n) or O(n^2). I know question is beginner level, any help would be appreciated. Thanks in Advance.

Related

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. Find the sum of all the primes below two million

sum_ans=17
for i in range(11,2000000):
for j in range(2,int(i**0.5)):
if i%j==0:
break
else:
sum_ans+=i
print(sum_ans)
The code i have return gives answer 143064094781 and the correct answer is 142913828922 but i can not figure out where i have gone wrong. So can any one help me.
Range's stop parameter is exclusive. This means that your code is only calculating j from 2 to 1 less than i**0.5. To fix this you can add 1, meaning that your end code will look a little like this, providing the correct output of 142913828922:
sum_ans=17
for i in range(11,2000000):
for j in range(2,int(i**0.5+1)):
if i%j==0:
break
else:
sum_ans+=i
print(sum_ans)
What about about this:
def isPrime(x):
prime = True
for i in range(2, x):
if x % i == 0:
prime = False
break
else:
continue
return prime
primes = (a for a in range(2, 2000000) if isPrime(a))
print(sum(primes))
# output
142913828922
This code will take a few minutes to execute. Buckle up!!
def sumPrimes(n):
sum =0
for i in range(2 ,n):
for j in range(2, int(i / 2) +1):
if (i % j) == 0:
break
else:
sum += i
return sum
print(sumPrimes(2000000))
If you iterating over all numbers below 2 million, you might as well sieve them using the Sieve of Eratoshenes:
from math import ceil, sqrt
def sieve(n):
nums = list(range(2,n+1))
primes = []
p = 2
k = 1+ ceil(sqrt(n))
while p < k:
primes.append(p)
nums = [num for num in nums[1:] if num % p > 0]
p = nums[0]
return primes + nums
Then sum(sieve(2000000)) evaluates to 142913828922. It takes about 5 seconds to run on my machine.

Recursive merge sort - RecursionError: maximum recursion depth exceeded while calling a Python object

I'm very new in programming and Python, so please excuse in advance my lack of knowledge.
I’m trying to implement a recursive merge sort method in a class. However, when I try to run the program I get the following error:
RecursionError: maximum recursion depth exceeded while calling a Python object
This is because of left = self.merge(lst[:middle]) and right = self.merge(lst[middle:]).
Does someone know how this problem could be solved?
def merge(self, lst, reverse=False):
middle = len(lst) // 2
left = self.merge(lst[:middle])
right = self.merge(lst[middle:])
result = []
i, j = 0, 0
if not len(left) or not len(right):
return left or right
while i < len(left) and j < len(right):
if reverse:
if left[i] > right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
else:
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
if i == len(left) or j == len(right):
result.extend(left[i:] or right[j:])
break
return result
def _merge_sort(self, reverse=False):
lst = list(self.unsorted_tuple)
if len(lst) < 2:
return lst
return self.merge(lst)
The problem is that you don't have a properly defined base case. In case of merge sort this would be checking if the passed list is either empty or has only one element (it is trivially true that it is sorted).
I'm guessing you're trying to do this with if not len(left) or not len(right). There's two problems with that. First, I don't think this code does what you think it does, play with it a bit in isolation to see how it behaves. See how I changed it and try to improve it.
Second, the test for the base case must be checked before calling the function again recursively. You never even come to this part because first thing that your merge function does is to call itself again! Here's a standalone merge function (not defined as a class method, I leave this to you):
def merge(lst, reverse=False):
if len(lst) <= 1:
return lst
middle = len(lst) // 2
left = merge(lst[:middle])
right = merge(lst[middle:])
result = []
i, j = 0, 0
while i < len(left) and j < len(right):
if reverse:
if left[i] > right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
else:
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
if i == len(left):
result.extend(right[j:])
if j == len(right):
result.extend(left[i:])
return result
I strongly recommend you Aditya Bhargava's Grokking Algorithms - it uses Python and is a good introductory book.

Given a non-negative integer num, repeatedly add all its digits until the result has only one digit

I don't understand why this code gives me 'Error' and not 2. I am trying to do this without recursion. An example with recursion would also be appreciated.
def addDigits(num):
num = str(num)
if(len(num) > 1):
for i in range(0, len(num)-1):
for j in range(1, len(num)):
if(len(str(int(num[i]) + int(num[j]))) > 1):
x = len(str(int(num[i]) + int(num[j])))
for i2 in range(0, x-1):
for j2 in range(1, x):
if(x == 1):
return(int(num[i]) + int(num[j]))
else:
return('Error')
else:
return('Error2')
else:
return(num)
print(addDigits(38))
Like you mentioned, recursive is the best way to do it. If you ever write a code with more than 2 loops, just think again whether it is absolutely necessary.
def add_digits(x):
if x/10>1:
x=add_digits(sum([int(i) for i in str(x)]))
else:
return x
if x/10<1:
return x
add_digits(123456)
output:
3
The above code will help you sum the digits until its a single digit number.
Unlike C or C++, python is not a super fast language. Avoiding loops will make a significant difference.
I think if you output x and you will find x=2 rather than x=1, so the program run execute the else: return('Error').
Here is one way to do it with loops,i am from java so bear with me with semicolons.
def addDigits(num):
while(num >= 10):
int temp = 0;
while(num > 0):
temp = temp + num % 10;
num = num/10;
num = temp;
return num;
addDigits(38)
this should give you the correct answer which is 2

Is it possible to merge these two functions as one calls on another

Would like to know if it is possible to merge these two functions together it seems like it could be a singular function through recursion but i'm not sure. I don't really do a lot of programming but this works as intended i just thought it would be nice to have it as a single function. Just not sure how to program recursion any advice would be great thanks
def sieve(A, n):
for i in A:
if i % n == 0 and i > n:
A.remove(i)
return A
def primelist(N):
A = [i for i in range(2, N + 1)]
for i in A:
A = (sieve(A, i))
print(A)
Decided on a new approach and solved:
def primelist(N):
k = 0
A = [i for i in range(2, N + 1)]
while k < len(A):
for i in A:
if i % A[k] == 0 and i > A[k]:
A.remove(i)
k += 1
return(A)
Decided on a new approach and solved:
We can do better -- your solution, and that of #ikuamike, have the same issue. These lines in particular are inefficient:
for i in A:
if i % A[k] == 0 and i > A[k]:
First, when possible, we should do an easier test before a harder test, so the if should really be:
for i in A:
if i > A[k] and i % A[k] == 0:
to do the comparison (subtraction) test ahead of the modulus (division) test. (Why do all those divisions when you don't need too?)
The next issue is that all the numbers from A[0] to A[k] don't need to be tested as they're eliminated by the comparison, so why not leave them out in the first place:
for i in A[k + 1:]:
if i % A[k] == 0:
Revised code:
def primelist(N):
k = 0
A = [i for i in range(2, N + 1)]
while k < len(A):
for i in A[k + 1:]:
if i % A[k] == 0:
A.remove(i)
k += 1
return A
With N set to 10,000, you can measure the time improvement.
def primelist(N):
A = [i for i in range(2, N + 1)]
new_a = A
for i in A:
for n in new_a:
if n % i == 0 and n > i:
new_a.remove(n)
print(new_a)
This should work well for you, I just replaced the for loop in seive onto the primelist function.

Given a positive integer, determine if it's the nth Fibonacci number for some n

I try to find out the index of a certain Fibonacci number. However my program returned to me this result "Your program took too long to execute. Check your code for infinite loops, or extra input requests" after typing in 1134903171.
num = 1
num_prev = 1
n = int(input())
i = 1
if n < 2:
print(1, 2)
else:
while i <= n + 2:
num_prev, num = num, num + num_prev
i += 1
if n == num:
print(i + 1)
break
elif i == n + 3:
print(-1)
#break`
Thank you guys. The problem of last code is that: if the number isn't a Fibonacci number and meanwhile it is too large, it will took to many loops for the calculation. As I used a web compiler to calculate, they do not allow such "infinity" loop to operate. Then I used a math methode to limite the loop.
import math
N=int(input())
root1=math.sqrt(5*N*N+4)
root2=math.sqrt(5*N*N-4)
i=1
num, num_prev = 1, 1
if root1%1==0 or root2%1==0:
while i <= N+2:
num_prev,num = num,(num+num_prev)
i+=1
if N==num:
print(i+1)
break
else:
print(-1)
But the best answer could be:
prev, next = 1, 1
index = 2
possible_fib = int(input())
while possible_fib > next:
prev, next = next, prev + next
index += 1
if possible_fib == next:
print(index)
else:
print(-1)

Resources