Example 1:
Input:
n = 1
Output: 1
Explanation: Digital root of 1 is 1
Example 2:
Input:
n = 99999
Output: 9
Explanation: Sum of digits of 99999 is 45
which is not a single digit number, hence
sum of digit of 45 is 9 which is a single
digit number.
Could someone help what is the time complexity of my code? I think its O(loglog(N)) but not sure.
def sumOfDigits(n):
if n==0:
return 0
else:
return int(n%10) + sumOfDigits(n//10)
def digitalRoot(n):
ans = n
if n<=9:
return n
else:
while ans>9:
ans = sumOfDigits(ans)
return ans
Let's calculate the complexity for the first step
If an algorithm depends on the number of digits it contains the time complexity of such algorithm is:
O(log10(n))
This is because we represent numbers in base 10 notation.
For example, this would make the relation crystal clear:
O(log10(100)) = 2
O(log10(1000)) = 3
O(log10(10000)) = 4
Now this answers the question to some extent, if we were only adding all digits once, we'd stop here.
But since we're not, let's move forward. Now if all the digits are added once, we again add the digits of that resultant number. Making it a convergent series.
Thus the answer could be:
O(log10(n)) + O(log10(log10(n))) + O(log10(log10(log10(n)))) + ...
This is my best estimation for the upper bound of complexity.
Related
Python.
It's a problem:
The algorithm receives a natural number N > 1 as input and builds a new number R from it as follows:
We translate the number N into binary notation.
Invert all bits of the number except the first one.
Convert to decimal notation.
Add the result with the original number N.
The resulting number is the desired number R. Indicate the smallest odd number N for which the result of this algorithm is greater than 310. In your answer, write this number in decimal notation.
This is my solution:
for n in range(2, 10000):
s = bin(n)[2:]
for i in range(len(s)):
if s[i+1] == 0:
s[i] = '1'
else:
s[i] = 'k'
for i in range(len(s)):
if s[i] == 'k':
s[i] = '0'
h = int(s, 2)
r = h + n
if n % 2 == 1 and r > 310:
print(n)
break
So it doesn't work and i dont know why. I am now preparing for the exam, so I would be grateful if you could explain the reason to me
the bin function returns a string and my idea is to go through the binary elements of this string, starting from the second element, to replace 0 with 1, and 1 with k. Then iterate over the elements of a new line again and replace k with 0
Took me longer than I expected but feels good.
Comments might make it look chaotic but will make it easily understandable.
#since N is supposed to be odd and >1 the loop is being run from 3
for N in range(3, 10000,2):
#appending binary numbers to the list bin_li
bin_li=[]
bin_li.append((bin(N)[2:]))
for i in bin_li:
#print("bin_li item :",i)
#storing 1st digit to be escaped in j
j=i[:1]
#reversing the digits
for k in i[1:]:
if k=='0':
#putting together the digits after reversing
j=j+'1'
else:
j=j+'0'
#print("reversed item :",j) #note first digit is escaped
#converting back to decimal
dec=int(j,2)
R=dec+N
#print("current sum:---------" ,R)
if R > 310:
print("The number N :",N)
print("The reversed binary number:",dec)
print("Sum :",R)
break
#break will only break the inner loop
# for reference https://www.geeksforgeeks.org/how-to-break-out-of-multiple-loops-in-python/
else:
continue
break
Given a number N, the function should convert the number to binary form, count the number of consecutive zero (the binary gap), and return the maximum binary gap. For example, 9 = 1001, the binary gap of length 2. The number 529 = 1000010001, has 2 binary gaps with length 4 and 3. If the number has 2 or more binary gaps, the function should return the maximum binary gap i.e. 4 in the case of N = 529.
I tried this function:
def solution(N):
binaryN = bin(N)[2:]
n = len(binaryN)
binaryGap = []
for i in range(n):
if binaryN[i] == 0 and binaryN[i + 1] == 0:
m = len(binaryN)
else:
return 0
binaryGap = binaryGap.append(m)
return max(binaryGap)
The function returns 0 for all values of N which is incorrect. How do I debug/improve the code to produce the accurate result?
Check out the below code. It would solve your problem.
The code is self-explanatory, yet let me know in-case of any doubts.
The Code:
import sys
num = int(sys.argv[1])
# Function to get the binary gap.
def binaryGapFinder(num):
binnum = bin(num).replace("0b", "") # binnum is binary form of the given number.
i = 0
x = 0
x_list = []
while i <= len(binnum)-1:
if binnum[i] == "0":
x += 1
if i == len(binnum)-1: # This loop will also consider if binary form is ending with 0. for example: 12 -> 1100
x_list.append(x)
else:
x_list.append(x)
x = 0
i += 1
return f"The Number: {num}\nIt's Binary Form: {binnum}\nMaximum Consecutive 0's: {max(x_list)}"
print(binaryGapFinder(num))
The Output:
python3 /the/path/to/your/script/binarygap.py 529
The Number: 529
It's Binary Form: 1000010001
Maximum Consecutive 0's: 4
python3 /the/path/to/your/script/binarygap.py 12
The Number: 12
It's Binary Form: 1100
Maximum Consecutive 0's: 2
python3 /the/path/to/your/script/binarygap.py 512
The Number: 512
It's Binary Form: 1000000000
Maximum Consecutive 0's: 9
There's a few issues here worth mentioning to aid you. (Just a side note to start with is that, in Python, it's recommended/best practice to use all lower case for variable names, so I'll replace them in my examples below.)
The bin() built in function returns a string. So you should be checking for equality with "0" (or '0') instead of an integer. e.g.
if binaryN[i] == "0" and binaryN[i + 1] == "0":
With Python you don't need to bother with checking for lengths of strings (or any other iterables) to use in a for loop in scenarios like this. e.g. You can replace:
n = len(binaryN)
for i in range(n):
with the more "Pythonic" way:
for bit in binary_number:
You can then use the variable bit (call it whatever you want of course, bearing in mind that good variable names make code more readable) instead of binary_number[index]. In this case, with each iteration of the for loop, bit will be replaced with the next character in the binary_number string.
From there on in your code:
m = len(binaryN)
will always be the same value, which is the total length of the string binaryN. e.g. 4 for '1001'.) This is not what you intended.
The first statement in your else block of code return 0 will terminate your function immediately and return 0 and thus your binaryGap = binaryGap.append(m) code will never, ever execute as it's unreachable due to that preceding return stopping any further execution of code in that suite.
You've got the right idea(s) and heading towards the right track for a solution but I don't think your code, even when the issues above are corrected, will match all possible binary numbers you may encounter. So, another possible alternative (and yet roughly sticking with the solution I think that you had in mind yourself) would be something like this which I hope will help you:
def solution(n):
binary_no = bin(n)[2:]
binary_gaps = []
gap_counter = 0
for bit in binary_no:
if bit == "0":
gap_counter += 1
else:
# Encountered a 1 so add current count of 0's -- if any -- to list and reset gap_counter
if gap_counter > 0:
binary_gaps.append(gap_counter)
gap_counter = 0
else:
# A for else suite (block of code) is run when all iterables have been exhausted.
if gap_counter > 0:
binary_gaps.append(gap_counter)
if binary_gaps: # If there is at least one element in the list
if len(binary_gaps) > 1:
return max(binary_gaps)
else:
return binary_gaps[0]
else:
# The list is empty, so no gaps were found at all. i.e. Binary number was all 1's.
return 0
print(solution(529))
I am using a function to get the number from user, and I am trying to use a while loop to separate the digits of a number. And I am trying to add the digits of the number. But my code runs infinitely.
Example : 2345 -> 15
def sumDigits(n):
sum=0
while len(str(n))>0:
a = n%10
n = n//10
sum += a
return sum
print(sumDigits(2345))
Expected: 15
Actual: I had to shut down the jupyter kernel to stop the while loop.
Edit 2: Removed the updated code as it was answered by the community.
This condition len(str(n))>0 can never be false as long as n is an integer, because str(0) is '0', which has a length of 1.
You need to change the looping condition to exit where there is no more digit to sum, which happens when n reaches 0:
def sum_digits(n):
total = 0
while n > 0:
a = n % 10
n = n // 10
total += a
return total
print(sum_digits(2345))
Note: sum is a built-in in python, so naming a variable sum is not advised. Also, method names usually are written in snake_case, so sum_digits is recommended.
def all_sum(number):
total = 0
if number > 0:
for e in str(number):
if e.isdigit():
total += int(e)
else:
pass
return total
a = all_sum(567897)
This should do your work. Instead of doing two arithmetic operations to 'fetch' the digits, better to change the argument to string and just use each digit. Its faster and saves memory (though it's not too memory consuming).
here is my code... It's considering only 8 and 88 among 1 to 100 which aren't karpekar numbers...failing at if condition(s==n)
def kaprekarNumbers(p, q):
for i in range(p,q+1):
n=i
m=str(i*i);
sl1=m[:int(len(m)/2)]
sl2=m[int(len(m)/2):]
if(sl2==""):
sl2=0
s=int(sl2)+int(sl2)
print(s==n)
if s==n:
print(i)
Using strings to process numbers is not usually a good idea.
You can get the number of digits of a number n with
math.ceil(math.log10(n))
You can get the last a digits of a number n with
n % a
(See: How does % work in Python?)
You can get the first a digits of a number n with
p // (10 ** a)
Those would be useful for base-10 Kaprekar numbers.
[Please note, I do not have a copy of Python to hand to check those.]
We are given a string which consists of digits 0-9. We have to count number of sub-strings divisible by a number k. One way is to generate all the sub-strings and check if it is divisible by k but this will take O(n^2) time. I want to solve this problem in O(n*k) time.
1 <= n <= 100000 and 2 <= k <= 1000.
I saw a similar question here. But k was fixed as 4 in that question. So, I used the property of divisibility by 4 to solve the problem.
Here is my solution to that problem:
int main()
{
string s;
vector<int> v[5];
int i;
int x;
long long int cnt = 0;
cin>>s;
x = 0;
for(i = 0; i < s.size(); i++) {
if((s[i]-'0') % 4 == 0) {
cnt++;
}
}
for(i = 1; i < s.size(); i++) {
int f = s[i-1]-'0';
int s1 = s[i] - '0';
if((10*f+s1)%4 == 0) {
cnt = cnt + (long long)(i);
}
}
cout<<cnt;
}
But I wanted a general algorithm for any value of k.
This is a really interesting problem. Rather than jumping into the final overall algorithm, I thought I'd start with a reasonable algorithm that doesn't quite cut it, then make a series of modifications to it to end up with the final, O(nk)-time algorithm.
This approach combines together a number of different techniques. The major technique is the idea of computing a rolling remainder over the digits. For example, let's suppose we want to find all prefixes of the string that are multiples of k. We could do this by listing off all the prefixes and checking whether each one is a multiple of k, but that would take time at least Θ(n2) since there are Θ(n2) different prefixes. However, we can do this in time Θ(n) by being a bit more clever. Suppose we know that we've read the first h characters of the string and we know the remainder of the number formed that way. We can use this to say something about the remainder of the first h+1 characters of the string as well, since by appending that digit we're taking the existing number, multiplying it by ten, and then adding in the next digit. This means that if we had a remainder of r, then our new remainder is (10r + d) mod k, where d is the digit that we uncovered.
Here's quick pseudocode to count up the number of prefixes of a string that are multiples of k. It runs in time Θ(n):
remainder = 0
numMultiples = 0
for i = 1 to n: // n is the length of the string
remainder = (10 * remainder + str[i]) % k
if remainder == 0
numMultiples++
return numMultiples
We're going to use this initial approach as a building block for the overall algorithm.
So right now we have an algorithm that can find the number of prefixes of our string that are multiples of k. How might we convert this into an algorithm that finds the number of substrings that are multiples of k? Let's start with an approach that doesn't quite work. What if we count all the prefixes of the original string that are multiples of k, then drop off the first character of the string and count the prefixes of what's left, then drop off the second character and count the prefixes of what's left, etc? This will eventually find every substring, since each substring of the original string is a prefix of some suffix of the string.
Here's some rough pseudocode:
numMultiples = 0
for i = 1 to n:
remainder = 0
for j = i to n:
remainder = (10 * remainder + str[j]) % k
if remainder == 0
numMultiples++
return numMultiples
For example, running this approach on the string 14917 looking for multiples of 7 will turn up these strings:
String 14917: Finds 14, 1491, 14917
String 4917: Finds 49,
String 917: Finds 91, 917
String 17: Finds nothing
String 7: Finds 7
The good news about this approach is that it will find all the substrings that work. The bad news is that it runs in time Θ(n2).
But let's take a look at the strings we're seeing in this example. Look, for example, at the substrings found by searching for prefixes of the entire string. We found three of them: 14, 1491, and 14917. Now, look at the "differences" between those strings:
The difference between 14 and 14917 is 917.
The difference between 14 and 1491 is 91
The difference between 1491 and 14917 is 7.
Notice that the difference of each of these strings is itself a substring of 14917 that's a multiple of 7, and indeed if you look at the other strings that we've matched later on in the run of the algorithm we'll find these other strings as well.
This isn't a coincidence. If you have two numbers with a common prefix that are multiples of the same number k, then the "difference" between them will also be a multiple of k. (It's a good exercise to check the math on this.)
So this suggests another route we can take. Suppose that we find all prefixes of the original string that are multiples of k. If we can find all of them, we can then figure out how many pairwise differences there are among those prefixes and potentially avoid rescanning things multiple times. This won't find everything, necessarily, but it will find all substrings that can be formed by computing the difference of two prefixes. Repeating this over all suffixes - and being careful not to double-count things - could really speed things up.
First, let's imagine that we find r different prefixes of the string that are multiples of k. How many total substrings did we just find if we include differences? Well, we've found k strings, plus one extra string for each (unordered) pair of elements, which works out to k + k(k-1)/2 = k(k+1)/2 total substrings discovered. We still need to make sure we don't double-count things, though.
To see whether we're double-counting something, we can use the following technique. As we compute the rolling remainders along the string, we'll store the remainders we find after each entry. If in the course of computing a rolling remainder we rediscover a remainder we've already computed at some point, we know that the work we're doing is redundant; some previous scan over the string will have already computed this remainder and anything we've discovered from this point forward will have already been found.
Putting these ideas together gives us this pseudocode:
numMultiples = 0
seenRemainders = array of n sets, all initially empty
for i = 1 to n:
remainder = 0
prefixesFound = 0
for j = i to n:
remainder = (10 * remainder + str[j]) % k
if seenRemainders[j] contains remainder:
break
add remainder to seenRemainders[j]
if remainder == 0
prefixesFound++
numMultiples += prefixesFound * (prefixesFound + 1) / 2
return numMultiples
So how efficient is this? At first glance, this looks like it runs in time O(n2) because of the outer loops, but that's not a tight bound. Notice that each element can only be passed over in the inner loop at most k times, since after that there aren't any remainders that are still free. Therefore, since each element is visited at most O(k) times and there are n total elements, the runtime is O(nk), which meets your runtime requirements.