Why "res.add(new ArrayList<>(list));" here? - java

class Solution {
public List<List<Integer>> pathSum(TreeNode root, int sum) {
List<List<Integer>> res = new ArrayList<>();
if(root == null) return res;
List<Integer> list = new ArrayList<>();
helper(res, list, root, sum);
return res;
}
public void helper(List<List<Integer>> res, List<Integer> list, TreeNode root, int sum){
list.add(root.val);
if(root.left == null && root.right == null){
if(root.val == sum)
res.add(new ArrayList<>(list));
}
if(root.left != null)
helper(res, list, root.left, sum-root.val);
if(root.right != null)
helper(res, list, root.right, sum-root.val);
list.remove(list.size()-1);
}
}
I am working on Leetcode 113. Path Sum II. It's not about the problem itself. I want to know why I have to write res.add(new ArrayList<>(list)); instead of writing res.add(list); directly in line 13.

Writing new ArrayList<>(list) creates a new list, containing all the elements in list. This is required, since at the end of the function you are calling list.remove(list.size()-1);, you are thus modifying the list variable.
If you were to add list directly in res, the remove call would also modify res.
Another relevant example:
class MyClass {
public int modify = 5;
}
class Test {
public static void myFunction() {
MyClass object = new MyClass();
System.out.println(object.modify); // prints 5.
ArrayList<MyClass> myList = new ArrayList<>();
myList.add(object);
object.modify = 800;
for(MyClass item : myList) {
System.out.println(item.modify); // prints 800.
}
}
}

new ArrayList<>(list) will make a copy of list, which will make sure the elements be stored into res.
Otherwise, after list.remove(list.size()-1), the elements in res will be removed.

Related

Linkedlist polynomial why my output only print first term

I just wrote a program that add two polynomial linked-list. my output only prints first term of the polynomials.
I cannot figure out what bug is. I want to get some help here. could someone tell what's wrong with my code.
public void addNode(int cof, int exp) {
PNode node = new PNode(cof, exp);
if (first == null) {
first = last = node;
return;
}
last.next = node;
last = node;
}
public PolynomialLinkedList add(PolynomialLinkedList s) {
PolynomialLinkedList sum = new PolynomialLinkedList();
//implement this method
PNode list1 = first;
PNode list2 = s.first;
while (list1 != null && list2 != null) {
if (list1.exp == list2.exp) {
sum.addNode(list1.coe + list2.coe, list1.exp);
list1 = list1.next;
list2 = list2.next;
} else if (list1.exp > list2.exp) {
sum.addNode(list1.coe, list1.exp);
list1 = list1.next;
} else if (list2.exp > list1.exp) {
sum.addNode(list2.coe, list2.exp);
list2 = list2.next;
}
}
return sum;
}
If one of the lists finishes first, the rest of the items in other list are ignored and are not getting added to the sum.
Add additional loops
while(list1 != null) {
sum.addNode(list1.coe,list1.exp);
list1=list1.next;
}
and
while(list2 != null) {
sum.addNode(list2.coe,list2.exp);
list2=list2.next;
}

Any idea why Collections.sort() is not working in the below program?

I am trying to solve a question on Leetcode that is related to Vertical traversal of a binary tree and I have written the below code.
Here Collections.sort() is not working and I am unable to understand why. need some pointers in fixing this code/
class Solution {
Map<Integer,List<Integer>>map = new TreeMap<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> verticalTraversal(TreeNode root) {
if(root == null)
return null;
rec(0,root);
for(Integer i : map.keySet())
{
result.add((map.get(i)));
}
return result;
}
public void rec(int pos, TreeNode node)
{
if(node == null)
return;
List<Integer>list = map.get(pos);
if(list == null)
{
list = new ArrayList<Integer>();
list.add(node.val);
Collections.sort(list);
map.put(pos,list);
}
else
list.add(node.val);
rec(pos-1,node.left);
rec(pos+1,node.right);
}
}
Input:
[0,8,1,null,null,3,2,null,4,5,null,null,7,6]
Expected: [[8],[0,3,6],[1,4,5],[2,7]]
Actual: [[8],[0,3,6],[1,4,5],[7,2]]
You only sort the inner lists once, when you create them. It would make more sense to sort them after adding all the elements.
Remove your current
Collections.sort(list);
and add
for (List<Integer> list : map.values()) {
Collections.sort(list);
}
after you finish adding all the numbers to all the Lists.
If you need to have the Lists sorted after each element added (which would be less efficient), you need to sort the List every time you add an element.
if(list == null)
{
list = new ArrayList<Integer>();
list.add(node.val);
Collections.sort(list);
map.put(pos,list);
}
else
list.add(node.val);
would become
if(list == null)
{
list = new ArrayList<Integer>();
list.add(node.val); // no need to sort a List with a single element
map.put(pos,list);
}
else {
list.add(node.val);
Collections.sort(list);
}
if (list == null) {
list = new ArrayList<Integer>();
list.add(node.val);
Collections.sort(list);
map.put(pos, list);
}
Please try to sort the elements after you add all the elements in the map.

How to make a generic concat method in java

I wanted to make a generic method for appending a copy of two linked list together and putting it in another linked list. list a and list b in list c.
here is the code that I have so far.
public static LinkedSequence<?> concatenaton(LinkedSequence<?> s1, LinkedSequence<?> s2) throws java.lang.NullPointerException
{
// Create a new sequence that contains all the elements from one sequence followed by another.
LinkedSequence<?> concat = new LinkedSequence();
if(s1 == null || s2 == null) {
return null;
}
else {
LinkedSequence h1;
LinkedSequence h2;
h1 = s1.clone();
h2 = s2.clone();
concat.addAll(h1);
concat.addAll(h2);
}
return concat;
}
public LinkedSequence<T> clone() {
// Generate a copy of this sequence.
LinkedSequence<T> copy = new LinkedSequence<T>();
//Node<T> newNode = new Node<T>(element);
Node<T> curr = first;
if(getCurrent() == null) {
return null;
} else {
while(curr != null) { //iterate through current list
copy.addLast(curr.getValue());
curr = curr.getLink();
}
}
return copy;
}
public void addLast(T element) {
Node<T> newNode = new Node<T>(element);
if (isCurrent() == false) {
current = newNode;
first = newNode;
last = newNode;
}
else {
//Node newNode = new Node(element);
last.setLink(newNode);
last = newNode;
}
}
the clone copies the whole list in a new list.
I keep getting an error saying that I make a generic type in a static type.
One thing is for sure... you need to use a type-parameter in your concat static method to impose the constraint that both input sequences have the same element type like so:
public static <E> LinkedSequence<E> concat(LinkedSequence<E> s1, LinkedSequence<E> s2) {
if(s1 == null || s2 == null) {
return null;
}
LinkedSequence<E> concat = new LinkedSequence<>();
concat.addAll(s1);
concat.addAll(s2);
return concat;
}
I took the liberty of edit the code a bit removing what seem to be redundant or inefficient.
You can make it a bit more general and accept inputs that contains type that are subclasses of the return type:
public static <E> LinkedSequence<E> concat(LinkedSequence<? extends E> s1, LinkedSequence<? extends E> s2) { ... }
You probably will need to change the addAll definition to accept ? extends E rather than E typed input collections.

Shuffling a singly linked list using up to log N extra memory and N log N time

I am trying to shuffle a linked list by recursively, breaking it into two lists and then merging them to ensure a random shuffle.
The two problems I face are:
While I run the program, there is an infinite loop at line 56 where I tell the program to shuffle the first list.
I am unable to figure out how to add a dummy variable in case the lengths of list 1 and list 2 vary to ensure randomness in shuffling.
PS - I found it through internet search that the length of 2 lists should be same to ensure randomness but I do not know the logic behind it. Also, please let me know if there is a better way of doing it than I am trying.
Thanks in advance!
public class LinkedListShuffle
{
static public class LinkedList<E> // static nested class
{
private int N = 0;
private Node first = null;
public class Node
{
E elem;
Node next;
}
public boolean isEmpty()
{ return N == 0; }
public void push (E elem)
{
Node oldfirst = first;
first = new Node();
first.elem = elem;
first.next = oldfirst;
N++;
}
public E pop()
{
E elem = first.elem;
first = first.next;
N--;
return elem;
}
public int size ()
{ return N; }
}
public static void shuffle(LinkedList l)
{
if (l.size() == 1) return;
LinkedList.Node current = l.first;
LinkedList l1 = new LinkedList();
LinkedList l2 = new LinkedList();
while (! l.isEmpty())
{
l1.push(l.pop());
if (! l.isEmpty()) l2.push(l.pop());
}
shuffle(l1);
shuffle(l2);
/*------------------------------------------
* if (l2.size() < l1.size())
* introduce a dummy node to ensure the
* randomness in the process of shuffling
-----------------------------------------*/
merge(l, l1, l2);
/*-----------------------------------------------
* remove the dummy variable
* ----------------------------------------------*/
}
public static void merge (LinkedList l, LinkedList l1, LinkedList l2)
{
while (l1.size() != 0 && l2.size() != 0)
{
double chance = StdRandom.uniform(1);
if (chance < 0.5) l.push(l1.pop());
else l.push(l2.pop());
}
if (! l1.isEmpty())
while (! l1.isEmpty()) l.push(l1.pop());
if (! l2.isEmpty())
while (! l2.isEmpty()) l.push(l2.pop());
}
public static void main (String[] args)
{
LinkedList<String> l = new LinkedList<String>();
LinkedList<String> copy = new LinkedList<String>();
l.push("A"); l.push("B"); l.push("C"); l.push("D");
l.push("E"); l.push("F"); l.push("G"); l.push("H");
copy = l;
while (copy.size() != 0) StdOut.println(copy.pop()+" ");
shuffle(l);
while (l.size() != 0) StdOut.println(l.pop()+" ");
}
}
Your problem is that you are emptying the list when you print it in your main method, prior to calling shuffle(l).
You are assigning the list l to a variable called copy, but this variable doesn't contain a copy of the list. It refers to the same list. When you call copy.pop(), you remove an element from the original list. Therefore you call shuffle on an empty list.
public static void main (String[] args)
{
LinkedList<String> l = new LinkedList<String>();
LinkedList<String> copy = new LinkedList<String>();
l.push("A"); l.push("B"); l.push("C"); l.push("D");
l.push("E"); l.push("F"); l.push("G"); l.push("H");
copy = l;
while (copy.size() != 0) StdOut.println(copy.pop()+" "); // remove this line
// and your method will
// work
shuffle(l);
while (l.size() != 0) StdOut.println(l.pop()+" ");
}
Of course, this means your shuffle method can't handle an empty list as input.
This can be solved with a tiny fix :
public static void shuffle(LinkedList l)
{
if (l.size() <= 1) return; // instead of == 1
...
I think the randomness can be introduced in the splitting stage, in which case the merge simply needs to concatenate 2 randomly shuffled lists. Following is an implementation using a LinkedBag Linked List implementation from Robert Sedgewick's algo course, which is clearly where you got your homework from.
public static <T> LinkedBag<T> shuffle(LinkedBag<T> ll) {
if (ll.size() <= 1) return ll;
LinkedBag<T>[] sublists = split(ll);
LinkedBag<T> l1 = shuffle(sublists[0]);
LinkedBag<T> l2 = shuffle(sublists[1]);
return merge(l1, l2);
}
private static <T> LinkedBag<T>[] split(LinkedBag<T> ll) {
LinkedBag<T> l1 = new LinkedBag<>();
LinkedBag<T> l2 = new LinkedBag<>();
Iterator<T> it = ll.iterator();
while (it.hasNext()) {
if (StdRandom.bernoulli())
l1.add(it.next());
else
l2.add(it.next());
}
return (LinkedBag<T>[]) new LinkedBag<?>[]{l1, l2};
}
private static <T> LinkedBag<T> merge(LinkedBag<T> l1, LinkedBag<T> l2) {
Iterator<T> it = l2.iterator();
while (it.hasNext()) {
l1.add(it.next());
}
return l1;
}

What is wrong with my Preorder traversal?

I am trying to solve this problem https://oj.leetcode.com/problems/binary-tree-preorder-traversal/ , i.e. preorder traversal with recursive slution.
EDIT: The whole code:
import java.util.ArrayList;
import java.util.List;
public class Solution {
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
static List<Integer> res = new ArrayList<Integer>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null){
return new ArrayList<Integer>();
}
res.add(root.val);
if(root.left != null){
res.add(preorderTraversal(root.left));
}
if(root.right != null){
res.add(preorderTraversal(root.right));
}
return res;
}
}
I have wrong answer because of the following:
Input: {1,2}
Output: [1,1,2]
Expected: [1,2]
Can someone tell me how to fix this?
EDIT: I dont have main() method or unit tests. If you open the link that I posted you will see that this is online judging system.
The problem is that within each recursive loop, you are adding the entire array again into your final result.
For example, given the following tree:
1
/
2
Your first iteration adds 1 into 'res' variable. The problem is when it gets to this line:
res.add(preorderTraversal(root.left));
Then it recursively calls itself for the left side. That preorderTraversal will return the res array, which will be [1,2]. Hence, when [1,2] gets added to res (which was [1], remember?), then you get [1,1,2].
Here's code that should work:
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
if(root == null){
return result;
}
result.add(root.val);
if(root.left != null){
result.addAll(preorderTraversal(root.left));
}
if(root.right != null){
result.addAll(preorderTraversal(root.right));
}
return result;
}
For the left and right nodes, just call preorderTraversal recursively, and it will add the values to res. Calling add/addAll on res with the results of these recursive calls is wrong.
public class Solution {
List<Integer> res = new ArrayList<Integer>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null){
return new ArrayList<Integer>();
}
res.add(root.val);
if(root.left != null){
preorderTraversal(root.left);
}
if(root.right != null){
preorderTraversal(root.right);
}
return res;
}
}
There's a little problem with this solution -- res retains the values from previous calls, so calling preorderTraversal more than once on the same instance may return incorrect results. Here's a solution that does not have this drawback:
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
preorderTraversal(root, res);
return res;
}
private void preorderTraversal(TreeNode node, List<Integer> res) {
if (node != null) {
res.add(node.val);
preorderTraversal(node.left, res);
preorderTraversal(node.right, res);
}
}
}
try this method code:
public List<Integer> preorderTraversal(TreeNode root) {
if(root == null){
return new ArrayList<Integer>();
}
res.add(root.val);
if(root.left != null){
res = preorderTraversal(root.left);
}
if(root.right != null){
res = preorderTraversal(root.right);
}
return res;
}
btw, you were doing res.add in the recursion. You should rather do res= in it.
A working solution :
import java.util.ArrayList;
import java.util.List;
class TreeNode
{
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
public List<Integer> preorderTraversal(TreeNode root)
{
ArrayList<Integer> res = new ArrayList<Integer>();
if(root == null)
return res;
else res.add(root.val);
if(root.left != null)
{
res.add(root.left.val);
preorderTraversal(root.left);
}
if(root.right != null)
{
res.add(root.right.val);
preorderTraversal(root.right);
}
return res;
}
}
public class TreeTest
{
public static void main(String[] args)
{
Solution c = new Solution();
TreeNode t1 = new TreeNode(1);
TreeNode t2 = new TreeNode(2);
TreeNode t3 = new TreeNode(3);
//Link the nodes of the tree
t1.left = t2;
t1.right = t3;
List<Integer> list = c.preorderTraversal(t1);
System.out.println(list);
}
}
Since you have not posted the whole code how the input is done and output is produced it is difficult to tell. For preorder traversal it should be something like this.
void traverse(TreeNode node){
if(node != null){
res.add(node.val);
traverse(root.left);
traverse(root.right);
}
}
public ArrayList<E> getPreOrderTraversal() {
return getPreOrderTraversal(root);
}
private ArrayList<E> getPreOrderTraversal(Node tree) {
ArrayList<E> list = new ArrayList<E>();
if (tree != null) {
list.add((E) tree.value);
list.addAll(getPreOrderTraversal(tree.left));
list.addAll(getPreOrderTraversal(tree.right));
}
return list;
}
A working and LeetCode accepted solution:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
return preOrderTraversalInternal(root, list);
}
private List<Integer> preOrderTraversalInternal(TreeNode root, List<Integer> list){
if(root == null) return list;
list.add(root.val);
if(root.left != null){
preOrderTraversalInternal(root.left, list);
}
if(root.right != null){
preOrderTraversalInternal(root.right, list);
}
return list;
}
}
The problem is that within each recursive loop, you are adding the entire array again into your final result.
You need to add left or right nodes only one time while traversing but in your code whole arr is getting added to the new res array.
This result will contain repetitive nodes.
For these issues, please use Print statements after every recursive call to debug the problem.
Solution -
Use addAll method: res.addAll(node.left);

Categories

Resources