System.out.println("1 + 2 = " + 1 + 2);
output: 12
can you explain why this is ? I tried to look through some documentation but did not find anything...
Because the + operator works from left to right, it adds the string "1 + 2 = " to 1 first, and gets "1 + 2 = 1", then adds 2 to get "1 + 2 = 12".
It's equivalent to
System.out.println(("1 + 2 = " + 1) + 2);
Try this instead.
System.out.println("1 + 2 = " + (1 + 2));
Since the left-hand operand is a String, then the left-hand operand gets cast to a String.
"1 + 2 = " + 1 is evaluated first. The result is the String "1 + 2 = 1". Then the next operation is "1 + 2 = 1" + 2. The result of that operation is "1 + 2 = 12"
The operator + always groups from left to right. So you get "1 + 2 = " + 1, (which gives "1 + 2 = 1"), and then the 2 gets added on last, giving "1 + 2 = 12".
If you want it to group from right to left, you need to use parentheses, like "1 + 2 = " + (1 + 2) and this will give "1 + 2 = 3"
This is because of priority. It goes from left to right, if you are using only +. First, the string 1 + 2 = is created, then you add number to the string, resulting in string 1 + 2 = 1 and then you add next int to string resulting in string 1 + 2 = 12.
You can avoid that by using brackets "1 + 2 = " + (1 + 2)
According to the Java Specification §15.7:
The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
And §15.18:
The additive operators have the same precedence and are syntactically left-associative (they group left-to-right).
If the type of either operand of a + operator is String, then the operation is string concatenation.
So the first half, "1 + 2 = " + 1, is the first part to get evaluated. Because the first half of that is a String, it evaluates to: "1 + 2 = 1". The whole expression is now "1 + 2 = 1" + 2. Once again, one of the two operands in this expression is a String, so the + operand concatenates. The whole expression then evaluates to the String "1 + 2 = 12", which is then printed.
Related
I am trying to understand what is time complexity of leetcode 241. Different ways to add parentheses. I have used memoization technique. My friend was asked in Google coding round, he couldn't give correct time and space complexity. I found same problem in Leetcode.
Problem:
Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are +, - and *.
Example 1:
Input: "2-1-1"
Output: [0, 2]
Explanation:
((2-1)-1) = 0
(2-(1-1)) = 2
Example 2:
Input: "2 * 3 - 4 * 5"
Output: [-34, -14, -10, -10, 10]
Explanation:
(2*(3-(4*5))) = -34
((23)-(45)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
Code:
import java.util.*;
class Solution {
Map<String, List<Integer>> map = new HashMap<>();
public List<Integer> diffWaysToCompute(String input) {
if(map.containsKey(input)) {
return map.get(input);
}
List<Integer> result = new ArrayList<>();
int length = input.length();
for(int i = 0; i< length; i++) {
char character = input.charAt(i);
if(isOperator(character)) {
String part1 = input.substring(0, i);
String part2 = input.substring(i + 1);
List<Integer> part1Result = diffWaysToCompute(part1);
List<Integer> part2Result = diffWaysToCompute(part2);
computeAndStoreResult(input, result, i, part1Result, part2Result);
}
}
//store in map...
map.put(input, result);
//this is when only one input is present.
// input 3 ==> nothing is added in result so add 3 ...
if(result.size() == 0) {
result.add(Integer.valueOf(input));
}
return result;
}
private boolean isOperator(char character) {
return character == '-' || character == '*' || character == '+';
}
private void computeAndStoreResult(String input, List<Integer> result, int i, List<Integer> part1Result, List<Integer> part2Result) {
for(Integer p1 : part1Result) {
for(Integer p2 : part2Result) {
int c= 0;
switch (input.charAt(i)) {
case '+':
c = p1+p2;
break;
case '-':
c = p1-p2;
break;
case '*':
c = p1*p2;
break;
}
result.add(c);
}
}
}
}
I have research on many sites could not find good explanation
This is how recursive tree looks like: Techinque used is divide and conquer with memoization.
Some useful links that I found.
https://www.cnblogs.com/yrbbest/p/5006196.html
https://just4once.gitbooks.io/leetcode-notes/content/leetcode/divide-and-conquer/241-different-ways-to-add-parentheses.html
Observation
If an expression consists of a single number, then there's 1 way to place parentheses.
If there's only 1 math operator in an expression, then there's only 1 way to place parentheses to obtain a relevant result. For example, for 3 + 4 it's (3 + 4).
If there are 2 math operators in an expression, then there are 2 ways to place parentheses. For example, for 3 + 4 - 2, the method will split the expression by + into 3 and 4 - 2, and then by - into 3 + 4 and 2. So, it's 2 ways.
If there are 3 math operators in an expression, then it's 5 results. For example, 1 + 2 - 3 * 4 can be split into 1 and 2 - 3 * 4, 1 + 2 and 3 * 4, 1 + 2 - 3 and 4. As we've learned from 2) and 3), the number of ways is 2 + 1 + 2 = 5` ways.
If there are 4 math operators in an expression, then it's 14 results. For example, 1 + 2 - 3 * 4 + 5 can be split into 1 and 2 - 3 * 4 + 5, 1 + 2 and 3 * 4 + 5, 1 + 2 - 3 and 4 + 5, 1 + 2 - 3 * 4 and 5. As we've learned from 2), 3) and 4) the number of ways is 5 + 2 + 2 + 5 = 14 ways correspondingly.
If the sequence is continued then it will be 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, .... As you can see, it grows exponentially.
Such sequence of numbers has a name and is called Catalan numbers.
Application for your algorithm
As you may have already realised, your algorithm will become exponential even after you obtain results for your left and right subexpressions split by the first math operator.
So, if there are 10 math operators, then after computing the results for the first configuration (expression is split by the first math operator) their number will be 4862.
So, not only is your time complexity exponential, but also your space complexity since you save all the results in a list.
I am having some problems with Recursion in Java.
Here is my code
public class recursionTrial {
public static void main(String[] args)
{
System.out.println(doSomething(6));
}
public static int doSomething(int n)
{
if (n==0 || n==1)
return 0;
else
return n + doSomething(n-1) + doSomething(n-2);
}
}
Which gives me an output of 38. However I am unable to trace the recursive function in my head or on paper. How will the working out look? 6+5.... and so on.
I get if it were just
return n + doSomething(n-1)
then it would be 6+5+4+3+2 = 20 ; it is the second part of the code that is confusing me. If someone could explain to me how to trace the recursive function properly and write the working out I would appreciate it! Also is there a way to write a piece of code that prints the value of n before it changes each time?
In the absence of side effects one can think of this recursive function as of a regular function. You can draw a small table showing the results of invocation of your function, starting with zero:
n res computation
- --- -----------
0 0 0
1 0 0
2 2 2+0+0
3 5 3+2+0
4 11 4+5+2
5 21 5+11+5
6 38 6+21+11
No special mental treatment is required for the second recursive invocation: it is the same as the first one.
Note: your function will be taking progressively longer time as the value of n goes up, because it would be re-doing a lot of computations it has already done. Fortunately, this can be addressed with a simple and very common trick, called memoization.
Your recursive function is
f(n) = n + f(n-2) + f(n-1)
The execution flow is as follows.
f(n-2) is evaluated first... To compute f(n-2) the program again makes a recursive call to f(n-4) and f(n-3) and so on...
Next, f(n-1) is evaluated... this again depends on computed values of f(n-3) and f(n-2) and so on...
These two values are added with n to get the final result...
For example, the recursion tree for n=4 is as follows (I'm not showing the addition with n for simplicity):
f(4) {
f(2) {
f(0) {0}
f(1) {0}
}
f(3) {
f(1) {0}
f(2) {
f(0) {0}
f(1) {0}
}
}
}
doSomething(1)= return 0,
doSomething(2)== 2+dosomething(1)= 2+0=2,
doSomething(3)=3+doSomething(2)=3+2=5,
doSomething(4)=4+doSomething(3)+doSomething(2)=4+5+2=11
doSomething(5)=5+doSomething(4)+doSomething(3)=5+11+5=21,
doSomething(6)=6+doSomething(5)+doSomething(4)=6+21+11=38
Start at doSomething(6), it calls: doSomething(5) go to that line, to figure out doSomething(5) we need to know doSomething(4) and doSomething(3).... and work your way up the tree, till you get to an actual "Return value" which in this case would be when we reach doSomething(1), then put those values in as you back down the tree.
public static int doSomething(int n) {
if (n==0 || n==1)
return 0;
else
return n + doSomething(n-1) + doSomething(n-2);
}
You could try to expand recursively, this is conceptually what the program does.
doSomething(6) expands to 6 + doSomething(5) + doSomething(4)
doSomething(5) expands to 5 + doSomething(4) + doSomething(3)
doSomething(4) expands to 4 + doSomething(3) + doSomething(2)
...
Simply go down the recursion. For example (I use dS for doSomething):
dS(6) = 6 + dS(5) + dS(4) =
6 + 5 + dS(4) + dS(3) + 4 + dS(3) + dS(2) =
6 + 5 + 4 + dS(3) + dS(2) + 3 + dS(2) + dS(1) + 4 + 3 + dS(2) + dS(1) + 2 + dS(1) + dS(0) =
6 + 5 + 4 + 3 + dS(2) + dS(1) + 2 + dS(1) + dS(0) + 3 + 2 + dS(1) + dS(0) + 0 + 4 + 3 + 2 + dS(1) + dS(0) + 0 + 2 + 0 + 0 =
6 + 5 + 4 + 3 + 2 + dS(1) + dS(0) + 0 + 2 + 0 + 0 + 3 + 2 + dS(1) + 0 + 0 + 4 + 3 + 2 + 0 + 0 + 0 + 2 + 0 + 0 =
6 + 5 + 4 + 3 + 2 + 0 + 0 + 0 + 2 + 0 + 0 + 3 + 2 + 0 + 0 + 0 + 4 + 3 + 2 + 0 + 0 + 0 + 2 + 0 + 0 =
38 <-- Final result
Beware that this has exponential complexity.
doSomething(6) calls doSomething(5) and doSomething(4)
doSomething(5) calls doSomething(4) and doSomething(3)
doSomething(4) calls doSomething(3) and doSomething(2)
doSomething(3) calls doSomething(2) and doSomething(1)
doSomething(2) calls doSomething(1) and doSomething(0)
doSomething(1) is 0
doSomething(0) is 0
This illustrates callings of doSomething(), they are not results, since you are adding n for each call.
6
_______|_______
/ \
5 4
____|____ _|_
/ \ / \
4 3 3 2
_|_ | | |
/ \ / \ / \ / \
3 2 2 1 2 1 1 0
/ \ / \ / \ / \
2 1 1 0 1 0 1 0
/ \
1 0
Consider
int a = 20;
a = a + (a = 5); // a == 25, why not 10?
Don't parentheses trump all precedence rules? Are some variables on the RHS prepopulated before evaluation of certain expressions?
Because a is loaded first in the example you have, and then the bit in parenthesis is evaluated. If you reversed the order:
int a = 20;
a = (a = 5) + a;
System.out.println(a);
10
... you do indeed get 10. Expressions are evaluated from left to right.
Consider this:
f() + g()
f will be called before g. Imagine how unintuitive it would be, in
f() + (g())
to have g be called before f.
This is all detailed in JLS §15.7.1 (thanks to #paisanco for bringing it up in the comments).
From the JLS
The Java programming language guarantees that the operands of
operators appear to be evaluated in a specific evaluation order,
namely, from left to right.
and
The left-hand operand of a binary operator appears to be fully
evaluated before any part of the right-hand operand is evaluated.
Wrapping an expression in parentheses just helps grouping (and associativity), it doesn't force its evaluation to happen before anything to its left.
Generated bytecode:
BIPUSH 20
ISTORE 1
ILOAD 1
ICONST_5
DUP
ISTORE 1
IADD
ISTORE 1
RETURN
LOCALVARIABLE a I
First, you assign 20 to the first variable (a):
BIPUSH 20
ISTORE 1
Then, you load the contents of the first variable to stack (20 is put on stack):
ILOAD 1
Then, you push the constant '5' to the stack twice (20 5 5):
ICONST_5
DUP
Then, you store the top of the stack to the first variable (a):
ISTORE 1
a is now 5, stack is now (20 5). We add both operands and put their sum to the first variable (a):
IADD
ISTORE 1
As a consequence, a is now 20 + 5 = 25. We end:
RETURN
You asked why and the latest JLS provides a clearer explanation of what is happening in JLS 17:
In particular, the presence or absence of parentheses around an
expression does not affect whether a variable is definitely assigned,
definitely assigned when true, definitely assigned when false,
definitely unassigned, definitely unassigned when true, or definitely
unassigned when false.
In effect they are saying that parentheses do not prompt assignment, which explains why assignment occurs left-to-right, unlike evaluation, which occurs in innermost-to-outermost order.
But that still does not answer why.
It's not because of compatibility with Java's predecessor, at least not in its present form, because the behavior does not match C:
Java 17:
int j = 3, k = 4, l = 5, m = 6, n = 7;
System.out.println(((j = 3) + j) + j); // 3 + 3 + 3 = 9
System.out.println(k + (k + (k = 3))); // 4 + 4 + 3 = 11
System.out.println(l + ((l = 3) + l)); // 5 + 3 + 3 = 11
System.out.println((m + (m += 3)) + m); // 6 + 9 + 9 = 24
System.out.println(n + (n += n / 2) + ++n); // 7 + 11 + 12 = 28
GCC 7.5.0:
printf("%d\n",((j = 3) + j) + j); // 3 + 3 + 3 = 9
printf("%d\n",k + (k + (k = 3))); // 3 + 3 + 3 = 9
printf("%d\n",l + ((l = 3) + l)); // 3 + 3 + 3 = 9
printf("%d\n",(m + (m += 3)) + m); // 9 + 9 + 9 = 27
printf("%d\n",n + (n += n / 2) + ++n); // 10 + 10 + 11 = 31
This leaves us with the explanation used elsewhere for Java awkwardness: upgradeability. Java happened to do it this way at the time it was written; changing it to work in alignment with C would potentially break existing code. I'd be curious to know of any discussion that might have taken place when the initial design was decided.
in this code im confused as to why it prints out "0 1 2 3" instead of "3 2 1 0"
int y = 3;
String s = " ";
while (y>-1)
{
s = y + " " + s;
y--;
}
System.out.print(s);
Thanks.
s = y + " " + s;
adds y at the front of the string so:
s = 3
s = 2 3
s = 1 2 3
s = 0 1 2 3
step 1:
s = 3
step 2:
s = 2 3;
step 3:
s = 1 2 3
like wise in every loop y's value is added to the starting point of the string s
This is because you prepend the newest value to the string. If you want the output to be "3 2 1 0" you should change your line from
s = y + " " + s;
to
s = s + " " + y;
I am trying to practice understanding recursion but the following program has me stumped. How is the answer being returned as 14? Can someone show me how this is calculating? I tried to put in afew print statments to help me identify what is going on but I do not see how spot is decremented after it goes up to 4. I have the program and output to console below, please help.
from console:
The spot 1 is 0
The spot 1 is 1
The spot 1 is 2
The spot 1 is 3
The spot 1 is 4
when spot = length. the spot is 4
The value is 4
spot after return 3
the spot 2 is 3
The value is 8
spot after return 2
the spot 2 is 2
The value is 11
spot after return 1
the spot 2 is 1
The value is 13
spot after return 0
the spot 2 is 0
The answer is 14
Code:
public class Recurs1 {
public static void main (String [] arg) {
Recurs1 r = new Recurs1();
r.compute();
}
public void compute() {
int [] stuff = {1, 2, 3, 4};
int answer = go(stuff, 0);
System.out.println("The answer is " + answer);
}
private int go(int[] numbers, int spot) {
System.out.println("The spot 1 is " + spot);
//System.out.println("0 is " + numbers[0] + " 1 is " + numbers[1] + " 2 is " + numbers[2] + " 1 is " + numbers[3]);
if (numbers.length == spot) {
System.out.println("when spot = length. the spot is " + spot); return spot;
}
int value = go(numbers, spot + 1 );
System.out.println(" The value is " + value);
System.out.println("spot after return " + spot);
System.out.println(" the spot 2 is " + spot);
return value + numbers[spot];
}
}
Try returning 0 instead of spot when you've reached the end. You're tacking 4 (the current value of spot) onto the end.
If your goal is to write a method which is summing the array, then the problem is that on the line of go() where you have if(numbers.length == spot) you are returning spot, which is 4, and it is adding that to the total value (because the method that called go(numbers, 4) is setting value to that and adding it.) Instead, you should be returning 0 to stop recursion (because the result will be 1+2+3+4+0)
Try this on for size:
private int go(int[] numbers, int spot){
if(numbers.length == spot) return 0;
return go(numbers, spot+1) + numbers[spot];
}
Maybe I can help walk you through it. Your program works it's way up until it calls go(numbers, 3+1), which returns 4, because numbers has 4 elements and spot is of value 4 (3+1).
At this point you are looking at a call stack of something like this:
answer = go(stuff, 0);
value = go(numbers, 0 + 1);
value = go(numbers, 1 + 1);
value = go(numbers, 2 + 1);
value = go(numbers, 3 + 1) = 4
Now it will work it's way back up the stack.
go(numbers, 2 + 1 );
Calling this will give you value+numbers[3], which is 4 + 4, with value coming from go(numbers, 3 + 1).
Next we have
go(numbers, 1 + 1 );
This will return go(numbers, 2 + 1 ) + numbers[2], which is 8 + 3 (or 11).
And then go(numbers, 0 + 1 ) is called, which returns go(numbers, 1 + 1 ) + numbers[1], which is 11 + 2 or 13.
Lastly, go(stuff, 0) can be calculated. This returns go(numbers, 0 + 1 ) + numbers[0], which is 13+1, or 14 - the answer you are currently getting.
I'm not sure if I actually explained much, but hopefully walking through it can show where your confusion is.
Another way of visualizing it would be something like this:
answer = go(stuff, 0);
go(stuff, 0) = go(numbers, 0 + 1) + 1;
go(numbers, 0 + 1) = go(numbers, 1 + 1) + 2;
go(numbers, 1 + 1) = go(numbers, 2 + 1) + 3;
go(numbers, 2 + 1) = go(numbers, 3 + 1) + 4;
go(numbers, 3 + 1) = 4;