We can use recursive class initialisation to define a linked list:

class ListNode {
	int value;
	ListNode next;
}

We can then create two constructors:

class ListNode {
	int value;
	ListNode next;
	
	public ListNode(int value) {
		this.value = value;
		// This means next is null as ListNode 
	}
	
	public ListNode(int value, ListNode next) {
		this(value); // Calls the other constructor ListNode(int)
		this.next = next;
	}
}

We then have recursive initialisation:

ListNode last = new ListNode(30);
ListNode middle = new ListNode(20, last);
ListNode first = new ListNode(10, middle);
 
// Is equivalent to
 
ListNode first = new ListNode(10, new ListNode(20, new ListNode(30)));

Operations on LL

We have LinkedList LL = ....

To insert at the beginning: list = new LinkedList(10, list); to insert 10 at the beginning.

To insert at the end: list.next.next...next = new ListNode(10); appends at the back.

Nested Classes

We can nest the class definitions to make the ListNode unavailable outside of the LinkedList implementation.

public class LinkedList {
	private class ListNode {
		private int value;
		private ListNode next;
	}
	
	private ListNode front;
	
	public LinkedList() {
		front = null;
	}
}

We are not allowed to initialise an object of type ListNode in a static method of LinkedList!

// ADDITIONAL IMPORTS ARE NOT ALLOWED

class Main {
  static In in;
  static Out out;
  public static void main(String[] args) {
    in = new In();
    out = new Out();
    out.SysInit();
    test();
  }

  public static void test() {
    // Uncomment the following two lines if you want to read from a file
    in.open("public/0-example.in");
    out.compareTo("public/0-example.out");

    int T = in.readInt();
    for (int test = 0; test < T; test++) {
      int n = in.readInt();
      int[] A = new int[n];
      for (int i = 0; i < n; i++) {
        A[i] = in.readInt();
      }
      out.println(splitMerge(n, A));
    }
  }
  
  public static int calc(int val1, int val2) {
    return (int) Math.floor((float) val1 / val2);
  }
  
  public static int merge(int[] A, int l, int r) {
    if (r - l == 1) return calc(A[l], A[r]);
    
    return Math.max(
      calc(A[l], merge(A, l + 1, r)), 
      calc(A[r], merge(A, l, r - 1))
    );
  }
  
  public static int splitMerge(int n, int [] A) {
    return merge(A, 0, A.length - 1);
  }

}