While looking up solutions for the Pascal's triangle problem which takes in the number of rows as input (int numRows), and outputs a List containing all rows of the triangle, I tried this code:-
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> rows = new ArrayList<List<Integer>>();
List<Integer> pre, row = null;
for(int i=0; i<numRows; ++i){
row = new ArrayList<Integer>();
for(int j=0; j<=i; ++j){
if(j==0 || j==i)
row.add(1);
else
row.add(pre.get(j-1)+pre.get(j));
}
pre=row;
rows.add(row);
}
return rows;
}
}
This gave me the error:-
Line 12: error: variable pre might not have been initialized
row.add(pre.get(j-1)+pre.get(j));
^
However, by changing the fourth line to:-
List<Integer> row, pre = null;
The code worked just fine. What's the reason behind this?
A variable initializer only initializes the variable before it, regardless of how many variables the declaration statement creates. So
only initializes
rowwithnullwhereasonly initializes
prewithnullwhich would be the same aswhich demonstrates that is not an issue of the variable order.
The first statement of your loop body is
row = new ArrayList<Integer>();Therefore,
rowdoes not need to be initialized before the loop. The loop body will not be executed ifnumRowsis zero or less, but this is not a problem, becauserowis not accessed after the loop. All accesses torowoccur after the variable has been initialized.In fact, you could move the declaration of
rowinto the loop at the place where you initialize it.In contrast, the
pre.get(j-1)occurs before the first assignment, i.e.pre=row;, therefore, the compiler considers this an access to a potentially uninitialized variable for the first loop iteration. An experienced reader may recognize that this line will never be executed in the first loop iteration and theprevariable is initialized in subsequent iterations. But the compiler does not analyze the conditions to that depth.So you need to initialize
preas withList<Integer> row, pre = null;even if you know that this initial value will never be used.An alternative is to move the logic of the first iteration before the loop, e.g.
The adds the invariant first row to the rows before the loop and starts the loop with the second row (index one). Note that this requires handling the empty case at the beginning. But the advantage is that this code doesn’t need to initialize a variable with an unused value.