I am looking at the code for Permutations problem on leetcode. For example,
[1,2,3] have the following permutations:
[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1].
And I found there is one sentence
ArrayList<Integer> temp = new ArrayList<Integer>(l);
I have no idea why here needs to assign the "l" to "temp". And I tried current.add(l) direclty but gave me the wrong answer. Can you help me with this?
public class Solution {
public ArrayList<ArrayList<Integer>> permute(int[] num) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
//start from an empty list
result.add(new ArrayList<Integer>());
for (int i = 0; i < num.length; i++) {
//list of list in current iteration of the array num
ArrayList<ArrayList<Integer>> current = new ArrayList<ArrayList<Integer>>();
for (ArrayList<Integer> l : result) {
// # of locations to insert is largest index + 1
for (int j = 0; j < l.size()+1; j++) {
// + add num[i] to different locations
l.add(j, num[i]);
ArrayList<Integer> temp = new ArrayList<Integer>(l);
current.add(temp);
//System.out.println(temp);
// - remove num[i] add
l.remove(j);
}
}
result = new ArrayList<ArrayList<Integer>>(current);
}
return result;
}
}
I have no idea why here needs to assign the "l" to "temp"
He's not - that would just be:
ArrayList<Integer> temp = l;
Instead, the code creates a copy of the content of the list l refers to, in a new ArrayList. That means that future changes to the list that l refers to (such as the call to l.remove(j) immediately afterwards) don't affect the new list.
As a simple stand-alone example of that, consider:
List<String> original = new ArrayList<>();
original.add("foo");
List<String> copy = new ArrayList<>(original);
System.out.println(copy.size()); // 1
original.add("bar");
System.out.println(copy.size()); // Still 1
Admittedly the code is written in a very odd manner - until the final statement, result only ever has a single element, so iterating over it is pretty pointless - but I believe that explains the single statement you were asking about.
If you did
current.add(l);
you would be adding the same reference to the ArrayList l to current. So, if you made some changes in one of those lists, both would be modified. In order to avoid that issue, in the line
ArrayList<Integer> temp = new ArrayList<Integer>(l);
you are creating a different ArrayList but with the same content. So, they will be different objects (different references).
Related
This question already has answers here:
Why does one arraylist change when a copy of it is modified
(6 answers)
Closed 3 years ago.
I'm setting a temporary ArrayList equal to a pre-established ArrayList. Changes to the temporary ArrayList seem to also transfer over to the pre-established one. Why does this occur and how can I keep the pre-established ArrayList unchanged?
I know that this phenomenon does not occur in situations that involve ints.
ArrayList<Integer> array = new ArrayList<>();
for (int i = 0; i < 3; i++){
array.add(i);
}
ArrayList<Integer> tempArr = array;
tempArr.remove(0);
I expect array to be [0,1,2], but I get [1,2]. I would like the output to be array = [0,1,2] and tempArr = [1,2].
You just copied the reference of the list to the new variable. That means you have 2 references array and tempArr that are pointing to the same object. You could create a new ArrayList from the old one:
ArrayList<Integer> tempArr = new ArrayList<>(array);
Variables array and tempArr booth point to same instance of ArrayList<Integer> object, hence modifying one will make changes to other.
What you need is to create new instance and then transfer all elements to it:
ArrayList<Integer> array = new ArrayList<>();
for (int i = 0; i < 3; i++){
array.add(i);
}
ArrayList<Integer> tempArr = new Arraylist<>();
tempArr.addAll(array);
tempArr.remove(0);
This code can also be simplified since Arraylist<> is offering you constructor that will add elements from another collection:
ArrayList<Integer> tempArr = new Arraylist<>(array);
tempArr.remove(0);
I am trying to grasp the concept. I have never worked with ArrayLists before (just arrays).
What I have is:
ArrayList<ArrayList<String>> movies = new ArrayList<ArrayList<String>>();
What this will look like or the way I picture it is:
[[Ratatouille, A Bug's Life], [Tangled, Zootopia, Finding Dory], [Harry Potter]]
And say the userInput = 2; then I would subtract 1 from the user input (because Array's and ArrayList's index at 0 that much I know) so userInput= 1; (based on their multiple choice selection, not very important).
Then what I want to do is take the index 1 so [Tangled, Zooptopia, Finding Dory] and loop through that index and add it to an ArrayList (not ArrayList of an ArrayList).
No need to loop - You can access an ArrayList by an index, and then use the addAll method to add all the elements of the ArrayList in that position to your result:
result.addAll(movies.get(userInput - 1));
following with following code you can iterate through an arrayList
private ArrayList<String> myArrayList = new ArrayList<>();
for(int i=0;i<myArrayList.size();i++){
myArrayList.get(i);
// Perform whatever operation here
}
Let me know if it doesn't work. And also what's the error given
The ArrayList.get(int index) method can help you out.
ArrayList myList = fullList.get(1);
would give you your desired list and you can iterate over it like:
for (String currString: myList){
//Do things with currString
}
I hope I explained it well :)
You should learn how to use Java Lambdas. you can use a lambda to iterate through an ArrayList since ArrayLists are Iterable.
ArrayList<ArrayList<String>>arrayListofarrayList = new ArrayList<ArrayList<String>>();
arrayListofarrayList.forEach((arrayList) -> {System.out.println(arrayList.get(1));});
or
ArrayList<ArrayList<String>>arrayListofarrayList = new ArrayList<ArrayList<String>>();
arrayListofarrayList.forEach((arrayList) -> {\*code here!*\});
if you're trying nest iterations you can:
ArrayList<ArrayList<String>>arrayListofarrayList = new ArrayList<ArrayList<String>>();
arrayListofarrayList.forEach((arrayList) -> {
arrayList.forEach((item) -> {
System.out.println(item);
});
});
Declare your variable as following
private ArrayList<String> arrayList = new ArrayList<>();
Then in a method add following
for(int j=0; j < arrayList.size() ; j++){
arrayList.get(i);
// Your code goes here
}
This should work
You can use either for-each loop or simple for loop to print elements in ArrayList of ArrayList. For example,
ArrayList<Integer> list1 = new ArrayList<>();
list1.add(1);list1.add(2);
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(3);list2.add(4);
ArrayList<Integer> list3 = new ArrayList<>();
list3.add(5);list3.add(6);
ArrayList<ArrayList<Integer>> listOfList = new ArrayList<>();
listOfList.add(list1);
listOfList.add(list2);
listOfList.add(list3);
// Printing elements using for-each loop
for(ArrayList<Integer> eachList : listOfList){
for(Integer elementInList : eachList){
System.out.print(elementInList + "\t");
}
System.out.println();
}
// Printing elements using for loop
for(int i = 0;i < listOfList.size();i++){
ArrayList<Integer> eachList = listOfList.get(i);
for(int j = 0;j < eachList.size();j++){
System.out.print(eachList.get(j) + "\t");
}
System.out.println();
}
Output:
I have been struggling on this problem for two days. This problem comes from some problem I am doing. Basically, when I use
List<List<Integer>> temp = new ArrayList<>(result);
to create a new ArrayList copy of result, the result will change when I try to change temp within an advanced for loop. For example,
List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList<>());
List<List<Integer>> temp = new ArrayList<>(result);
int j = 0;
for (List<Integer> list: temp) {
list.add(x[j]);
j ++;
}
I did nothing to the result inside the loop but the result ends up with [[1]], which is the same as temp.
Why is this happening? Thanks a lot.
Update: thank everybody for answering my question. I learn the shallow copy was the reason. However, I still run into a similar problem. The result is updated while I try to change the temp in the following code:
List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList<>());
List<List<Integer>> temp = new ArrayList<>();
for (List<Integer> list: result) {
list.add(10000);
temp.add(new ArrayList(list));
}
I do not know why the result turns out to be [[10000]] as well as the temp. Is there anything wrong with the add method like temp.add(new ArrayList(list))?
This is happening because the List<List<Integer>> temp = new ArrayList<>(result); statement copies only the top-level list. It will be the new list that contains references to the original items (aka sublists) from the original result.
You can fix this with a deep copy:
List<List<Integer>> temp = new ArrayList<>(); // empty list
for (List<Integer> sublist : result) {
temp.add(new ArrayList<Integer>(result)); // copying a sublist and adding that
}
temp = new ArrayList<>(result) only does a shallow copy of result, i.e. it copies the "outer" list, but not its elements.
temp.get(0) == result.get(0) - and I don't mean equals - they are exactly the same instance.
As such, anything you add to temp.get(0) will also appear in result.get(0).
This is not surprising because you have only one list to iterate upon. If you add a second list you will see a second digit coming in.
int[] x = new int[]{1,2,3,4,5};
List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList());
result.add(new ArrayList());
List<List<Integer>> temp = new ArrayList<>(result);
for (Integer xx: x) {
result.add(new ArrayList(xx));
}
System.out.println(result.toString());
If you try this code it will display you:
[[1],[2]]
This is my snippet. record[i] is an object with 2 variables id and number. And I'm getting the error unexpected type : required variable; found : value.
int Shuffle = 0;
List<Integer> randomID = new ArrayList<Integer>();
List<Integer> randomNumber = new ArrayList<Integer>();
for (int i=0;i<100 ;i++) {
randomID.add(new Integer(i));
}
Collections.shuffle(randomID);
for (int i=0;i<100000;i++) {
randomNumber.add(new Integer(i));
}
Collections.shuffle(randomNumber);
for (int i=0;i<length;i++) {
if (randomID.contains(record[i].ID)) {
randomID.indexOf(record[i].ID)=null; //ERROR : REQUIRED VARIABLE FOUND VALUE
}
}
for (int i=0;i<length;i++) {
if (randomNumber.contains(record[i].getNumber())) {
randomNumber.indexOf(record[i].getNumber())=null;
}
}
Your call to randomID.indexOf(record[i].ID) returns some value. You have put it on the left side of an equals sign, so the compiler is looking for something to which it can ASSIGN a value. It can't assign a value to a value, it must have a variable.
I suppose you might mean to assign null to the ID of that element of the array: record[i].ID = null;
Or you might need the index into randomID:
int index = randomID.indexOf(record[i].ID);
randomID.set(index, null);
but you end up with a list that has a bunch of nulls in it. Is that really what you want?
Anyway, your question was about the error. If you have a different question, ask it in a different post.
With java collections, there are several types of storage.
The List collection allows for duplicate entries.
The Set collection does not allow duplicates.
Set set = new HashSet<Integer>(); //assuming you want Integer
int randomNumberCount = 10
while(set.size() < randomNumberCount) {
int temp = Math.random() * 100;
set.add(new Integer(temp));
}
Adding entries to a set that already exist will just replace it.
I know that for arrays you can add an element in a two dimensional array this way:
array[0][1] = 17; //just an example
How can I do the same thing with ArrayList?
myList.get(0).set(1, 17);
maybe?
This assumes a nested ArrayList, i.e.
ArrayList<ArrayList<Integer>> myList;
And to pick on your choice of words: This assigns a value to a specific place in the inner list, it doesn't add one. But so does your code example, as arrays are of a fixed size, so you have to create them in the right size and then assign values to the individual element slots.
If you actually want to add an element, then of course it's .add(17), but that's not what your code did, so I went with the code above.
outerList.get(0).set(1, 17);
with outerList being a List<List<Integer>>.
Remember that 2-dimensional arrays don't exist. They're in fact arrays or arrays.
ArrayList<ArrayList<String>> data = new ArrayList<ArrayList<String>>();
data.add(new ArrayList<String>());
data.get(0).add("String");
ArrayList<ArrayList<String>> contains elements of type ArrayList<String>
Each element must be initialised
These elements contain elements of type String
To get back the String "String" in the 3-line example, you would use
String getValue = data.get(0).get(0);
the way i found best and convinient for me was to declare ur 2d arrayList and then also a nornal mono-dimension array.
ArrayList<ArrayList<String>> 2darraylist = new ArrayList<>();
ArrayList<String> 1darraylist=new ArrayList<>();
then fill the '1D'array list and later add the 1D to the 2D array list.
1darraylist.add("string data");
2darraylist.add(idarraylist);
this will work as long as your problem is simply to add to elements to the list. if u want to add them to specific positions in the list, the the .get().set(); is what u wanna stick to.
ArrayList<ArrayList<Integer>> FLCP = new ArrayList<ArrayList<Integer>>();
FLCP.add(new ArrayList<Integer>());
FLCP.get(0).add(new Integer(0));
Each element must be instantiated. Here the outer ArrayList has ArrayList element, and first you need to add an element to reference it using get method.
Some additional notes; after reading other answers and comments:
1> Each element must be instantiated; initialization is different from instantiation (refer to flexJavaMysql's answer)
2> In Java, 2-dimensional arrays do exist; C# doesn't have 2D arrays (refer to JB Nizet's answer)
String[] myList = {"a","b","c","d"};
ArrayList<ArrayList<String>> data = new ArrayList<ArrayList<String>>();
data.add(new ArrayList<String>());
int outerIndex =0;
int innerIndex =0;
for (int i =0; i<list.length; i++) {
data.get(outerIndex).add(innerIndex, list[i]);
innerIndex++;
}
System.out.println(data);
Simple for loop to add data to a multidimensional Array.
For every outer index you need to add
data.add(new ArrayList<String>());
then increment the outer index, and reset the inner index.
That would look something like this.
public static String[] myList = {"a", "b","-","c","d","-","e","f","-"};
public static ArrayList<ArrayList<String>> splitList(String[] list) {
ArrayList<ArrayList<String>> data = new ArrayList<ArrayList<String>>();
data.add(new ArrayList<String>());
int outerIndex =0;
int innerIndex =0;
for (int i=0; i<list.length; i++) {
System.out.println("will add: " + list[i]);
if(!list[i].contains("-")) {
System.out.println("outerIndex: " + outerIndex +" innerIndex: "+ innerIndex);
data.get(outerIndex).add(innerIndex, list[i]);
innerIndex++;
} else {
outerIndex++; // will move to next outerIndex
innerIndex = 0; // reset or you will be out of bounds
if (i != list.length-1) {
data.add(new ArrayList<String>()); // create an new outer index until your list is empty
}
}
}
return data;
}
public static void main(String[] args) {
System.out.println(splitList(myList));
}