Related
This question already has answers here:
Difference between b=b++ and b++ [duplicate]
(4 answers)
What is x after "x = x++"?
(18 answers)
Closed 1 year ago.
The title is self-explanatory. Consider the following code:
int n = 5;
n = n--;
It gives n = 5.
As far as I understood the expression n-- is first evaluated, returning 5 (i.e. POSTdecrement). This expression gets assigned to the LHS, here n.
After this execution, n gets diminished. Thus I expected n = 4.
Why don't I see 4?
n-- yields 5 and then sets n to 4
n = sets n to the value of the right-hand expression, which is 5
Mixing the increment/decrement operators with an assignment to the same variable rarely does anything useful.
This is not fully correct, there is 2 forms to do it --n and n--, thats is where you will do the rest on N.
With the --n before you first rest and then return the value, and the other side is the opposite.
You first pass the value and then rest the value, try doing it the other way.
Given n=5, n-- return 5 but n value is 4.
Given n=5, --n return 4 and n value is 4.
That's why n has still the same vlaue
I have a midterm tomorrow, and we are supposed to be able to analyze code. This is honestly the only thing that I don't understand at all. Basically we are given something like this:
Consider this Java method for comparing two strings. This method has two inputs and so we should use two variables to express the running time. Let n be the length of a and let m be the length of b. We can express the running time as a function of n and/or m. It will help if we assume without loss of generality that n < m.
private static int compareStrings ( String a , String b) {
int i = 0;
while ( i < a . length () && i < b. length ( ) ) {
if (a . charAt ( i ) < b. charAt ( i ) ) return −1;
if (a . charAt ( i ) > b. charAt ( i ) ) return 1;
i ++;
}
if (a . length () < b. length ( ) ) return −1;
if (a . length () > b. length ( ) ) return 1;
}
a) Express the worst case running time of this method as a sum.
b) Simplify this sum and state its big-oh bound.
the notation I need it in is :
n
Σ i
i= 1
I don't understand how to build a sum out of this code, or get it's running time. Step by step instructions would be great. This problem given was a practice problem and not homework. I really want to understand this!!!
The worst case run time is O(n).
Why?
1. Because we assume that n < m and this algorithm only compares characters as long as there are characters remaining in both strings [characters yet to be compared].
Naturally this condition fails to hold when there are no more characters in the shortest string, a.
Because the worst case must occur when the while loop is not interrupted by a return.
This can coincide with case in which we evaluate n times.
The only stipulation is that a be a substring of b such that a[0] == b[0] also.
Cost is the sum of
evaluating the while condition
the cost of the two comparisons, etc. in the body of the loop
incrementing i
It is bounded above by nc + k where c is the worst case cost of the while loop body, k is the cost of the operations only evaluated once (such as the return statement), and n has the previously agreed-upon significance.
If you allow n to rise without bound you can see that this fits the definition of O(n).
Looking at the code, it creates an iterator (i), then iterates through until it reaches the end of one of the strings (the shorter, obviously, represented by length n).
Since there's only one loop, and that loop only iterates through n times, the "running time" of the algorithm could probably be described as counting the "if" statements that would result, or "2n+2". In Big-O notation, that comes out to O(n). The extra two if checks at the end are constant, so not used in the computation.
Hmm, the sum you're looking for would seem to be:
n
Σ k
i = 1
Read this as "for each value from 1 to n of i, add k to the total", which should result in k*n (and a resulting big-O of O(n)). I use k here because I don't know the cost of the inner loop, but it should be constant. If you feel your class would use 1 for "one time through the body of the loop", then that's fine too.
Ok, first of all the code is buggy. It has a Unicode character instead of a minus sign and it doesn't return anything if none of the conditions match. This won't work as method has to return an integer.
Following is the fixed method.
private static int compareStrings ( String a , String b) {
int i = 0;
while ( i < a . length () && i < b. length ( ) ) {
if (a . charAt ( i ) < b. charAt ( i ) ) {
return -1;
}
if (a . charAt ( i ) > b. charAt ( i ) ) {
return 1;
}
i ++;
}
if (a . length () < b. length ( ) ) {
return -1;
}
if (a . length () > b. length ( ) ) {
return 1;
}
return 0;
}
Now lets start breaking it down to calculate the complexity.
First complexity as sum
To do this we have to count the number of operations done by this method. Lets say that a stand alone operation takes 1 unit of execution time.
There are 5 types of different independent operations in this method.
Declaration of a variable
Look up of length of string
Condition evaluation (Logical condition)
Logical expression evaluation of 2 boolean values
Returning a value from the method.
Assuming that all the above stand alone operations take 1 unit of time we can go ahead and calculate the total time taken by the method.
int i = 0;
//time taken 1 unit.
while ( i < a . length () && i < b. length ( ) )
//time taken 5n + 2 unit
loop statement consists of 5 operations
2 length lookups for a and b
2 length comparisons with i
1 comparison of the output of length comparison ( && operation)
Since we are considering the worst case loop would have to run n times.
Since loop runs at max n times as n is less than m and loop breaks whenever i is less than n. So this gives us 5n unit of time
However would be one more check for i when it's value is incremented to n when the loop will break as i < a.length() <=> i < n will result in false. Here only first 2 operations will be evaluated as the second operation will be short circuited.
a.length() //1 unit of time
i < a.length() //1 unit of time
That gives us 5n+2 unit of time for while statement.
Next two statements are almost identical if statements. Since we are considering the worst case neither of the two will result in true otherwise loop would break.
if (a . charAt ( i ) < b. charAt ( i ) ) {
return -1;
}
//3n unit of time
if (a . charAt ( i ) > b. charAt ( i ) ) {
return 1;
}
//3n unit of time
Both of these statements get executed n times. Each consists of 3 stand alone operations (2 charAt(i) lookups and 1 condition evaluation).
So total time taken by both of these statements will be 6n unit of time.
Next is
i++;
//n unit of time
This is simple as loop runs n times and it is stand alone operation.
Finally next and last statement is
if (a . length () < b. length ( ) ) {
return -1;
}
//4 units of time
It has 4 operations (2 length lookups, 1 condition, and 1 return statement)
Now no more statements will be executed as we know for a fact that n < m
Total sum of execution time will be as following.
sum = 1 + (5n+2) + (6n) + n + 4
= 12n + 7
sum = 12n + 7
Now this is still not the worst case, as n has an upper bound that's m
We have to maximize n in order to make the worst case possible. Maximum value that n can assume is m-1 as n < m (strictly less than)
so in the worst case
n = m - 1
replacing that in the sum expression 12n + 7
sum = 12n + 7
= 12(m-1) + 7
= 12m - 5
sum = 12m - 5
This is our answer of first part
worst case running time of the method as sum
12m - 5
Now since Big-O bound for this function would be O(m)
As following is the definition of Big-O
f(x) is bounded by g(x)
if and only if for some sufficiently large constant x0 for which there exists an M for which below is true.
Here
f(m) = 12m -5
g(m) = m
m0 = 5/12
M = 12
so O(g(x) = O(m) is the upper bound for the sum.
Simplified sum in big-oh bound is
O(m)
I got the following code given:
public class alg
{
public static int hmm (int x)
{
if (x == 1)
{
return 2;
}
return 2*x + hmm(x-1);
}
public static void main (String[] args)
{
int x = Integer.parseInt(args[0]);
System.out.println(hmm(x));
}
}
So first question is, what does this algorithm count?
I have just typed and runned it in eclipse
so I can see better what it does (it was pseudocode before, I couldn't type it here so I typed the code). I have realized that this algorithm does following: It will take the input and multiply it by its following number.
So as examples:
input = 3, output = 12 because 3*4 = 12.
Or Input = 6, output 42 because 6*7 = 42.
Alright, the next question is my problem. I'm asked to analyze the runtime of this algorithm but I have no idea where to start.
I would say, at the beginning, when we define x, we have already got time = 1
The if loop gives time = 1 too I believe.
Last part, return 2x + alg(x-1) should give "something^x" or..?
So in the end we got something like "something^x" + 2, I doubt thats right : /
edit, managed to type pseudocode too :)
Input: Integer x with x > 1
if x = 1 then
return 2;
end if
return 2x + hmm(x-1);
When you have trouble, try to walk through the code with a (small) number.
What does this calculate?
Let's take hmm(3) as an example:
3 != 1, so we calculate 2 * 3 + hmm(3-1). Down a recursion level.
2 != 1, so we calculate 2 * 2 + hmm(2-1). Down a recursion level.
1 == 1, so we return 2. No more recursions, thus hmm(2-1) == hmm(1) == 2.
Back up one recursion level, we get 2 * 2 + hmm(1) = 2 * 2 + 2 = 4 + 2 = 6. Thus hmm(2) = 6
Another level back up, we get 2 * 3 + hmm(2) = 6 + 6 = 12
If you look closely, the algorithm calculates:
2*x + ... + 4 + 2
We can reverse this and factor out 2 and get
2 * (1 + 2 + ... + x).
Which is an arithmetic progression, for which we have a well-known formula (namely x² + x)
How long does it take?
The asymptotic running time is O(n).
There are no loops, so we only have to count the number of recursions. One might be tempted to count the individual steps of calculation, but those a are constant with every step, so we usually combine them into a constant factor k.
What does O(n) mean?
Well ... we make x - 1 recursion steps, decreasing x by 1 in every step until we reach x == 1. From x = n to x = 1 there are n - 1 such steps. We thus need k * (n - 1) operations.
If you think n to be very large, - 1 becomes negligible, so we drop it. We also drop the constant factor, because for large n, O(nk) and O(n) aren't that much different, either.
The function calculates
f(x) = 2(x + x-1 + x-2 + ... + 1)
it will run in O(x), i.e. x times will be called for constant time O(1).
I am new to computer science and learning recursion methods. Can someone explain this method briefly?
import java.util.Scanner;
public class factorial {
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
System.out.print(factorial(n));
}
private static long factorial(int n) { // HERE I DON'T UNDERSTAND HOW
// THE MACHINE NOWS WHAT IS "factorial"
if (n == 1)
return 1;
else
return n * factorial(n - 1); // ??
}
}
The machine does not know what factorial is, the code there tells it how to calculate a factorial. It does this by saying "Is the number you gave me 1?" and until it is, returns the number times the function return of n - 1, essentially this will cascade into the calculation of a factorial.
This is easily seen if you take an example:
3! = 3*2*1
Or
3! = 3*2!
Which is what the return method gives in the form:
factorial(n) = n * factorial(n-1)
The program given:
factorial(3);
Will go through the following:
Is 3 equal to 1?
It is not so it returns 3*factorial(2)
In order to obtain 3*factorial(2), it calculates factorial(2).
Now it checks: is 2 equal to 1?
It is not so it returns 2*factorial(1), since it is returning to the step three, that overall return will now be 3*2*factorial(1).
Next the program checks: is 1 equal to 1?
It is so it returns 1.
This is returned to our call in step five: 2*factorial(1) becomes 2*1 = 2, which returns to the call from step 3, our first call, giving us 3*2 = 6, which is what the function will return overall.
This method could do with some tweaking though. Imagine you supplied it with 0? It would continuously call the factorial method on an infinite recursion because the sequence 0,-1,-2,-3,-4,... will never reach 1. A better method could look like this:
private static long factorial(int n) {
if (n == 1 || n == 0) {
return 1;
} else if (n < 0) { // factorials are not defined below 0, they can be interpolated
return null; // though, see note below
} else {
return n * factorial(n - 1);
}
}
This function will now cover factorials for the whole range of integers, using a null solution for negative numbers. The definition for a factorial of n is defined as the product of the integers between 1 and n; see this. Factorials of negative integers, floating point numbers, and complex values are also defined or can be interpolated as noted in the link in the previous sentance, but these are much more complex than a simple recursive factorial.
It knows what factorial is because you defined it to be factorial.
You've created a private static long factorial(int n) which means "A method named factorial with a single parameter n that returns a long, is available statically on the factorial class, and is private to that class.
You can call factorial from anywhere that has access to it, which in this case is within the factorial class itself. This means you can call it from the main method, or you can call it from the factorial method itself. It's just a function call that, well, happens to call itself.
We know the definition of factorial, 1 * 2 * ... (n-1) * n. We can also define it as n! = n * (n - 1)! or in other words, factorial(n) = n * factorial(n-1) which is exactly what you see in the last line.
Just take a sheet of paper and trace your code:
factorial(5):
5!=1:
return 5*factorial(4):
4!=1:
return 4*factorial(3):
3!=1:
return 3*factorial(2):
2!=1:
return 2*factorial(1):
1==1:
return 1;
So, at the end we have:
return 5*4*3*2*1 statement
Your code:
private static long factorial(int n) {
if (n == 1)
return 1;
else
return n * factorial(n - 1);
}
defines a method named factorial. It could have been named func, fred, or anything you like; it would not change its behavior.
It's behavior is as follows:
if the argument n is equal to 1, then it simply returns 1
otherwise, it returns the product of n with the result of calling factorial with an argument equal to n - 1. This is the recursive step. Note that the function can call itself and it won't return until the recursive call returns. The chain of calls are pushed onto the stack, each one waiting for the next one to return before it computes the product and returns.
With a little thought, you should be able to see that the above behavior exactly matches a common textbook definition of the factorial function.
Assuming that factorial is called with an argument greater than 0, the recursion will always eventually end with a call to factorial with an argument equal to 1. As written, this function will fail with a stack overflow exception if it is called with a value of n that is less than 1.
It's all about breaking the problem into smaller versions of itself.
What is 1! ?
It's 1.
That's represented by the following code
if (n == 1)
return 1;
Can you find n! if you know (n-1)! ? Of course you can!
Just multiply it by n
represented by the other part of the code.
else
return n * factorial(n - 1);
What you're doing is calling the function from within itself, eventually n will be 1, and the cycle will stop.
The rest of your code is irrelevant, lets break down your recursive function:
private static long factorial(int n) {
if (n == 1)
return 1;
else
return n * factorial(n - 1);
}
What the first line, or signature, says, is "I am a private method (private) that is not attached to a specific object instance (static) that returns a long (which is a long integer value). I'm named 'factorial' because, presumably, the output is the factorial of the input. As input I take an int, which I'm naming n for my purposes.
We know factorials are defined as f(n) = n*(n-1)*...*1. Another way to write this is:
f(n) = n * f(n-1)
Or:
f(n) = n * (n-1) * f(n-2)
f(n) = n * (n-1) * (n-2) * f(n-3)
and so on. But when do you stop? when n == 1. We see this reflected in the method:
if (n == 1)
return 1;//If n == 1, return 1. This is the 'base case'
else
return n * factorial(n - 1);//Multiply n by the factorial of n-1 (duh, right?)
The recursive call here is in that last line: it's using the same function to figure out the solution to a problem that is smaller by a discrete amount. After all, we know that if we multiply n by the result of this smaller problem, we get the correct answer.
Factorial of a number (n=number) is the product of all positive integers less than or equal to n.
factorial of n can denote as n!
ex/
factorial of 5 = 5!
factorial of 100 =100!
factorial of 5 means (5!) -> 5 * 4 * 3 * 2 * 1
ex/ according to this method
1 private static long factorial(int n) {
2 if (n == 1){
3 return 1;
4 } else{
5 return n * factorial(n - 1);
6 }
7 }
if we need to find 5! - (factorial of 5) you have to call the above method using number 5.
ex/
factorial(5)
if (n == 1) condition in line no:2 check the number you pass whether equal to 1 (because 1! is equal to 1) we use this line as our base case(where the place that recursive function stop)
base case
when we call recursion function it keeps calling again and again until our stack becomes overflow. therefore we need a "stopping point" to our recursive function. That endpoint we call as the base case
The main goal is to understand this line-
return n * factorial(n - 1);
in our first iteration n = 5 and n-1 = 4 (according to our example)
Imagine function calls like this
1st iteration 5! = 5 * factorial(4) - inside this line we keep 5 separately and * we call factorial(4) again
2nd iteration 4! = 4 * factorial(3) - inside this line we call factorial(3) again
3rd iteration 3! = 3 * factorial(2) - inside this line we call factorial(2) again
4th iteration 2! = 2 * factorial(1) - inside this line we call factorial(1) again
5th iteration 1! = 1 - start to return 1
Imagine return values like this
ex/
return 5 * factorial(4) -> 5 * [receive (4 * 3* 2* 1)] = 5 * (24)
factorial(4) - 4 * factorial(3) -> 4 * [receive (3 * 2 * 1) = 4 * (6)
factorial(3) -------> 3 * factorial(2) -> 3 * [recieve (2 * 1)] = 3 * (2)
factorial(2) --------------->2 * factorial(1) -> 2 * [return 1] = 1
this image will helpful (image I got from quora.com)
it keeps calling until our n equals to 1
once our function meets the base case which is n=1 it starts to return 1.
(keep in mind until it meets base case it keeps calling the function factorial(n) and until we meet our base case our function do not return anything)
we need to understand how call stack work to understand this.
Let me try explain as per your code :
System.out.print(factorial(n)); /*at this line ,lets assume n=3 ; as soon as we call factorial(3) , this method stores in Stack */
Above line will call method ; private static long factorial(int n) { ... } //n=3
i)it go inside and check if n==1 //false
ii)its goes to else block : 3 * factorial(2) /* again here 3 * factorial(2) will store in stack on top of factorial(3) */
i)it checks again in if n==2 //false
ii)goes to else : 2 * factorial(1) //stores on top of 3 * factorial(2) in stack
i)it checks again in if n==1 // True , this returns value 1.
STACK looks like below in LIFO order:
2 * factorial(1)
3 * factorial(2)
factorial(3)
now question comes where this returned value 1 will go , It will go to top call from stack.
which is ;2 * factorial(1)--> return 2 * 1
value 2 will go to stack of 3 * factorial(2) -- > which 3 * 2 =6
finally value 6 will go to called method : factorial(3).
def factorial(n):
if n < 2:
return 1
else:
return n * factorial(n-1)
factorial(4) # = 24
#You can replace code with your prefered language
Here is how it works
If the value less than 2, it is actullay not returing mulitplication of two numbers, instead function returns multiplication of a number and a number return from a function call (n * factorial(n-1))
At last we return 1
Example (Factorial of 4)
Firstly it returns 4 * factorial (3)
Then it returns 4 * 3 * factorial(2)
Then it returns 4 * 3 * 2 * factorial(1). Here the else part of function ends
Then at last it returns 4 * 3 * 2 * 1 = 24
recently I became interested in the subset-sum problem which is finding a zero-sum subset in a superset. I found some solutions on SO, in addition, I came across a particular solution which uses the dynamic programming approach. I translated his solution in python based on his qualitative descriptions. I'm trying to optimize this for larger lists which eats up a lot of my memory. Can someone recommend optimizations or other techniques to solve this particular problem? Here's my attempt in python:
import random
from time import time
from itertools import product
time0 = time()
# create a zero matrix of size a (row), b(col)
def create_zero_matrix(a,b):
return [[0]*b for x in xrange(a)]
# generate a list of size num with random integers with an upper and lower bound
def random_ints(num, lower=-1000, upper=1000):
return [random.randrange(lower,upper+1) for i in range(num)]
# split a list up into N and P where N be the sum of the negative values and P the sum of the positive values.
# 0 does not count because of additive identity
def split_sum(A):
N_list = []
P_list = []
for x in A:
if x < 0:
N_list.append(x)
elif x > 0:
P_list.append(x)
return [sum(N_list), sum(P_list)]
# since the column indexes are in the range from 0 to P - N
# we would like to retrieve them based on the index in the range N to P
# n := row, m := col
def get_element(table, n, m, N):
if n < 0:
return 0
try:
return table[n][m - N]
except:
return 0
# same definition as above
def set_element(table, n, m, N, value):
table[n][m - N] = value
# input array
#A = [1, -3, 2, 4]
A = random_ints(200)
[N, P] = split_sum(A)
# create a zero matrix of size m (row) by n (col)
#
# m := the number of elements in A
# n := P - N + 1 (by definition N <= s <= P)
#
# each element in the matrix will be a value of either 0 (false) or 1 (true)
m = len(A)
n = P - N + 1;
table = create_zero_matrix(m, n)
# set first element in index (0, A[0]) to be true
# Definition: Q(1,s) := (x1 == s). Note that index starts at 0 instead of 1.
set_element(table, 0, A[0], N, 1)
# iterate through each table element
#for i in xrange(1, m): #row
# for s in xrange(N, P + 1): #col
for i, s in product(xrange(1, m), xrange(N, P + 1)):
if get_element(table, i - 1, s, N) or A[i] == s or get_element(table, i - 1, s - A[i], N):
#set_element(table, i, s, N, 1)
table[i][s - N] = 1
# find zero-sum subset solution
s = 0
solution = []
for i in reversed(xrange(0, m)):
if get_element(table, i - 1, s, N) == 0 and get_element(table, i, s, N) == 1:
s = s - A[i]
solution.append(A[i])
print "Solution: ",solution
time1 = time()
print "Time execution: ", time1 - time0
I'm not quite sure if your solution is exact or a PTA (poly-time approximation).
But, as someone pointed out, this problem is indeed NP-Complete.
Meaning, every known (exact) algorithm has an exponential time behavior on the size of the input.
Meaning, if you can process 1 operation in .01 nanosecond then, for a list of 59 elements it'll take:
2^59 ops --> 2^59 seconds --> 2^26 years --> 1 year
-------------- ---------------
10.000.000.000 3600 x 24 x 365
You can find heuristics, which give you just a CHANCE of finding an exact solution in polynomial time.
On the other side, if you restrict the problem (to another) using bounds for the values of the numbers in the set, then the problem complexity reduces to polynomial time. But even then the memory space consumed will be a polynomial of VERY High Order.
The memory consumed will be much larger than the few gigabytes you have in memory.
And even much larger than the few tera-bytes on your hard drive.
( That's for small values of the bound for the value of the elements in the set )
May be this is the case of your Dynamic programing algorithm.
It seemed to me that you were using a bound of 1000 when building your initialization matrix.
You can try a smaller bound. That is... if your input is consistently consist of small values.
Good Luck!
Someone on Hacker News came up with the following solution to the problem, which I quite liked. It just happens to be in python :):
def subset_summing_to_zero (activities):
subsets = {0: []}
for (activity, cost) in activities.iteritems():
old_subsets = subsets
subsets = {}
for (prev_sum, subset) in old_subsets.iteritems():
subsets[prev_sum] = subset
new_sum = prev_sum + cost
new_subset = subset + [activity]
if 0 == new_sum:
new_subset.sort()
return new_subset
else:
subsets[new_sum] = new_subset
return []
I spent a few minutes with it and it worked very well.
An interesting article on optimizing python code is available here. Basically the main result is that you should inline your frequent loops, so in your case this would mean instead of calling get_element twice per loop, put the actual code of that function inside the loop in order to avoid the function call overhead.
Hope that helps! Cheers
, 1st eye catch
def split_sum(A):
N_list = 0
P_list = 0
for x in A:
if x < 0:
N_list+=x
elif x > 0:
P_list+=x
return [N_list, P_list]
Some advices:
Try to use 1D list and use bitarray to reduce memory footprint at minimum (http://pypi.python.org/pypi/bitarray) so you will just change get / set functon. This should reduce your memory footprint by at lest 64 (integer in list is pointer to integer whit type so it can be factor 3*32)
Avoid using try - catch, but figure out proper ranges at beginning, you might found out that you will gain huge speed.
The following code works for Python 3.3+ , I have used the itertools module in Python that has some great methods to use.
from itertools import chain, combinations
def powerset(iterable):
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
nums = input("Enter the Elements").strip().split()
inputSum = int(input("Enter the Sum You want"))
for i, combo in enumerate(powerset(nums), 1):
sum = 0
for num in combo:
sum += int(num)
if sum == inputSum:
print(combo)
The Input Output is as Follows:
Enter the Elements 1 2 3 4
Enter the Sum You want 5
('1', '4')
('2', '3')
Just change the values in your set w and correspondingly make an array x as big as the len of w then pass the last value in the subsetsum function as the sum for which u want subsets and you wl bw done (if u want to check by giving your own values).
def subsetsum(cs,k,r,x,w,d):
x[k]=1
if(cs+w[k]==d):
for i in range(0,k+1):
if x[i]==1:
print (w[i],end=" ")
print()
elif cs+w[k]+w[k+1]<=d :
subsetsum(cs+w[k],k+1,r-w[k],x,w,d)
if((cs +r-w[k]>=d) and (cs+w[k]<=d)) :
x[k]=0
subsetsum(cs,k+1,r-w[k],x,w,d)
#driver for the above code
w=[2,3,4,5,0]
x=[0,0,0,0,0]
subsetsum(0,0,sum(w),x,w,7)