I have this program where it have some recursive function similar to this:
public static void lambda(HashSet<Integer> s){
if(end(s)){
return;
}
for(int i=0;i<w;i++){
HashSet<Integer> p = (HashSet) s.clone();
p.addAll(get_next_set());
do_stuff_to(p);
lambda(p);
}
}
What I'm doing is union every set with the set s. And run lambda on each one of the union.
I run a profiler and found the c.clone() operation took 100% of the time of my code. Are there any way to speed this up considerably?
When you are cloning, what are you really trying to do, maybe you don't need to do a complete cloan?
Your best bet at improving the performance of your lambda function is to extend HashSet and overide the clone definition with a custom one that is particular to your situation...
I don't know of anyother way to really help with out more information unfortunatly.
If I get it right you try to do the following:
lambda(Set p) {
lambda(p + further elements);
}
You can avoid cloning p e.g. by reimplementing a list and using the Nodes as parameters for lambda:
class Node {
int content;
Node next;
Node(int content, Node next) {
this.content = content;
this.next = next;
}
}
void lambda(Node set) {
// add new elements to front
Node newSet = set;
for(Integer i : new_elements() ) {
newSet = new Node(i, newSet);
}
lambda(newSet);
// Observe that set is not modified by adding new elements
}
This is a low-level-solution and you would have to implement a slow sequential search/find-algorithm (if you rely on unique elements in the set), yet in my experience such a stack is a good solution for most recursive algorithms.
This is what I did to speed up everything, this way I never have to create new sets.
public static void lambda(HashSet<Integer> s){
if(end(s)){
return;
}
ArrayList<Integer> diff = new ArrayList<Integer>();
for(int i=0;i<w;i++){
//an array version of the next set, it is pre-computed
int[] a = get_next_set_array();
for(int j=0;j<a.length;j++){
if(!s.contains(a[j])){
diff.add(a[j]);
}
}
s.addAll(diff);
do_stuff_to(s);
s.removeAll(diff);
diff.clear();
lambda(p);
}
}
On average this is much faster, and the program spend roughly the same amount of time on the addAll and removeAll.
Related
just to start off, this is homework and thank you for your assistance ahead of time. I keep getting stuck on little problems so I am hoping you guys can help me with one. What I am trying to do is create a linked list that has multiples functions. The one I am having trouble with is sorting(I can do the other ones). Each node holds a string, an integer and a double. I need to be able to sort by each of these and by the order it was inputted, on the user's request. ***It is also important to mention that the variables in my object are private and my object is called list1. Basically, I have to make one linked list for the chronological order and one for each other order.
My plan is to insert the nodes in their correct order as the user inputs them. So as the user inputs a node, that node needs to go in the correct place in the chronological list and in the other lists. So, I need to copy the node to do this. However, I cannot simply just say
icopy(copy for integer) = newNode(node the user just inputted)
That only changes the address. When I went to my instructor he told me that I should say:
icopy.data = newNode.data;
("data" being the shortcut way of mentioning that I need to get the individual data types within the node.) So I wrote:
icopy.GetI() = newNode.GetI();
When I do this I encounter this error: unexpected type required:variable, found:value. I am not sure what to do. Any assistance would be appreciated and I would be happy to clarify anything.
*GetI: method in my object that gives access to the integer value in each node.
*p: pointer for the Chronological
*pi: pointer for the integer.
*fi: front of the integer linked list
public static void main(String args[])
{
String repeat = "y";
boolean inserted = false;
list1 fChr = null;
list1 p = fChr;
list1 icopy = null;
list1 scopy = null;
list1 dcopy = null;
list1 fd = fChr;//front of the double list
list1 fi = null;//front of the integer list
list1 fStr = fChr;//front of the string list~
while(repeat.equals("y"))//while the user agrees to adding a new node
{
if(fChr == null)// if the front is empty
{
fChr = new list1();//create a new node by calling object and sets it as the front
}
else
{
p = fChr;
while(p.next != null)//finds the end of the Linked list
{
p = p.next;//moves the pointer p down the list
}
list1 newNode = new list1();
icopy.GetI() = newNode.GetI();// make a copy of newNode
p.next = nexNode;//put in chronological order
while(p != null)
{
if(fi == null)
{
fi = n;
}
else if(n.GetI() < fi.GetI)//check at beginning
{
//put at beginning
}
else if(icopy.GetI() < p.next.GetI())//check in between nodes
{
//put in between
}
//does it go at the end
}
}
repeat = JOptionPane.showInputDialog("Would you like to add a node [y/n]");
}
PrintMenu(fChr, fi, fd, fStr);// sends the user to the menu screen
}
There are a few things here that you are not understanding. Firstly, in Java iCopy.getI() = ... makes no sense. When a method returns a value it needs to be assigned to a variable if you wish to change it. If you want to change the instance variable you need a separate method called something like iCopy.setI().
It sounds as though you're not asking for help with the sorting so I'll restrict my answer to creating copies of the list.
What your professor is getting at is that the easiest way to ensure the data is consistent in your several linked lists is to separate the class storing the data from the nodes of the list. So I would expect your class structure to end up looking something like:
class Data {
private final int intValue;
private final String strValue;
private final double doubleValue;
}
class Node {
private final Data data;
private Node next;
public Node(Data data) {
this.data = data;
this.next = null;
}
}
Now if you want to create a new linked list with the same data as the old one then you can add a constructor to Node that creates a reference to the original data:
class Node {
public Node copy() {
Node copy = new Node(data);
if (next != null)
copy.next = next.copy();
return copy;
}
}
Hopefully you can see what that does: it creates a new node referencing the same data as this one and then uses recursion to copy the rest of the list.
Now creating each of the sort orders could look like:
Node listByInt = list.copy();
/* code to sort listByInt according to data.intValue */
Add a comment if you want some hints on sorting as well but I suggest you get your code to the point of having equal copies of lists before attempting that.
As a final note, you don't necessarily need to have separate linked lists to solve this problem. An alternative would be to store the original insertion order in the node. You could then sort by any order (including original insertion order) before printing the list. Personally I'd prefer that as a solution unless there are performance issues (e.g. you need to use each sorted list many times).
This is a homework program I"m working on for an algorithms course. The task is to simulate an adjacency matrix for a graph using a matrix of Lists (this is Java btw). The element of the matrix is interpreted as the first node. Any nodes it is connected to in the graph are added to the list of that is that matrix element. I have constructed the matrix as such:
List<Node>[] weightedList = new List[size]
I understand that there are issues with Lists of Objects and type-checking. I then call a method initializeList() to construct the initial structure.
protected void initializeList() {
List<Node> list = new ArrayList<Node>();
for (int i = 1; i < Tester.size; i++){
weightedList[i] = list;
}
}
As I'm processing my input data I need to "construct" the graph based on given node values. My problem lies here, when I call addEdge() (effectively, connecting two nodes creates an Edge), the node I am trying to add gets added to every element of the matrix. Here is the method:
public static void putEdge(Edge e) {
Node node1 = e.getVertex1();
Node node2 = e.getVertex2();
int dim1 = node1.getNode();
if (dim1 < Tester.size){
weightedList[dim1].add(node2);
}
}
Is my issue related to the type-checking problems inherent in Lists of Objects or something else? Please advise.
-- JQK
You assign the same list instance to all the indices of the array.
You should instantiate each list inside the loop :
protected void initializeList() {
for (int i = 0; i < Tester.size; i++){
List<Node> list = new ArrayList<Node>();
weightedList[i] = list;
}
}
This way, each index in the array will contain a different ArrayList instance.
And you probably should iterate from 0, since that's the first index of the array.
You're running into the problem here of assignment only copying a reference to an object, not the object itself. #Eran's solution shows how to assign a different list to each matrix element.
Thank you #Eran. Your solution was correct. Simple mistake on my part. I cannot upvote yet and I'm not sure how to give you credit for the solution.
My error was the location of the assignment statement in initializeList()
This is the correct format provided by #Eran.
protected void initializeList() {
for (int i = 0; i < Tester.size; i++){
List<Node> list = new ArrayList<Node>();
weightedList[i] = list;
}
}
if I have a list of arrays like this (pseudo java code):
Note the list valsSorted will be always sorted with x[0] asc and x[1] desc order.
List valsSorted = {[1 5][1 4][1 3][2 1][3 2][3 1][4 2][4 1][5 1][6 2][6 1]};
How do I filter this list with Java 8 streams and lambdas so that I get:
result = {[1 5][2 1][3 2][4 2][5 1][6 2]}
The first item of the array (x[0]) is ID and the second is a version number. So the rule is give all distinct IDs with the highest version back.
If I would use a for loop the following code would be fine:
ArrayList<int[]> result= new ArrayList();
int keep = -1;
for (int[] x : valsSorted) {
int id = x[0];
int version = x[1];
if(keep == id) continue;
keep = id;
result.add(x);
}
Your use of the word "distinct" suggests using the distinct() stream operation. Unfortunately that operation is hardwired to use the equals() method of the stream elements, which isn't useful for arrays. One approach for dealing with this would be to wrap the arrays in a wrapper object that has the semantics of equality that you're looking for:
class Wrapper {
final int[] array;
Wrapper(int[] array) { this.array = array; }
int[] getArray() { return array; }
#Override
public boolean equals(Object other) {
if (! (other instanceof Wrapper))
return false;
else
return this.array[0] == ((Wrapper)other).array[0];
}
#Override
public int hashCode() { ... }
}
Then wrap up your object before distinct() and unwrap it after:
List<int[]> valsDistinct =
valsSorted.stream()
.map(Wrapper::new)
.distinct()
.map(Wrapper::getArray)
.collect(toList());
This makes one pass over the data but it generates a garbage object per value. This also relies on the stream elements being processed in-order since you want the first one.
Another approach would be to use some kind of stateful collector, but that will end up storing the entire result list before any subsequent processing begins, which you said you wanted to avoid.
It might be worth considering making the data elements be actual classes instead of two-element arrays. This way you can provide a reasonable notion of equality, and you can also make the values comparable so that you can sort them easily.
(Credit: technique stolen from this answer.)
class Test{
List<Point> valsSorted = Arrays.asList(new Point(1,5),
new Point(1,4),
new Point(1,3),
new Point(2,1),
new Point(3,2),
new Point(3,1),
new Point(4,2),
new Point(4,1),
new Point(5,1),
new Point(6,2),
new Point(6,1));
public Test(){
List<Point> c = valsSorted.stream()
.collect(Collectors.groupingBy(Point::getX))
.values()
.stream()
.map(j -> j.get(0))
.collect(Collectors.toList());
for(int i=0; i < c.size(); i++){
System.out.println(c.get(i));
}
}
public static void main(String []args){
Test t = new Test()
}
}
I decided to use the point class and represent the ID field as x and the version number as Y. So from there if you create a stream and group them by ID. You can call the values method which returns a Collection of Lists Collection<List<Point>>. You can then call the stream for this Collection and get the first value from each list which according to your specifications is ordered with descending version number so it should be the the highest version number. From there all you have to do is collect them into a list, array or whatever you see necessary and assign it as needed.
The only problem here is that they are printed out of order. That should be an easy fix though.
I have this code below where I am inserting a new integer into a sorted LinkedList of ints but I do not think it is the "correct" way of doing things as I know there are singly linkedlist with pointer to the next value and doubly linkedlist with pointers to the next and previous value. I tried to use Nodes to implement the below case but Java is importing this import org.w3c.dom.Node (document object model) so got stuck.
Insertion Cases
Insert into Empty Array
If value to be inserted less than everything, insert in the beginning.
If value to be inserted greater than everything, insert in the last.
Could be in between if value less than/greater than certain values in LL.
import java.util.*;
public class MainLinkedList {
public static void main(String[] args) {
LinkedList<Integer> llist = new LinkedList<Integer>();
llist.add(10);
llist.add(30);
llist.add(50);
llist.add(60);
llist.add(90);
llist.add(1000);
System.out.println("Old LinkedList " + llist);
//WHat if you want to insert 70 in a sorted LinkedList
LinkedList<Integer> newllist = insertSortedLL(llist, 70);
System.out.println("New LinkedList " + newllist);
}
public static LinkedList<Integer> insertSortedLL(LinkedList<Integer> llist, int value){
llist.add(value);
Collections.sort(llist);
return llist;
}
}
If we use listIterator the complexity for doing get will be O(1).
public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {
private static final long serialVersionUID = 1L;
public boolean orderedAdd(T element) {
ListIterator<T> itr = listIterator();
while(true) {
if (itr.hasNext() == false) {
itr.add(element);
return(true);
}
T elementInList = itr.next();
if (elementInList.compareTo(element) > 0) {
itr.previous();
itr.add(element);
System.out.println("Adding");
return(true);
}
}
}
}
This might serve your purpose perfectly:
Use this code:
import java.util.*;
public class MainLinkedList {
private static LinkedList<Integer> llist;
public static void main(String[] args) {
llist = new LinkedList<Integer>();
addValue(60);
addValue(30);
addValue(10);
addValue(-5);
addValue(1000);
addValue(50);
addValue(60);
addValue(90);
addValue(1000);
addValue(0);
addValue(100);
addValue(-1000);
System.out.println("Linked List is: " + llist);
}
private static void addValue(int val) {
if (llist.size() == 0) {
llist.add(val);
} else if (llist.get(0) > val) {
llist.add(0, val);
} else if (llist.get(llist.size() - 1) < val) {
llist.add(llist.size(), val);
} else {
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
}
}
}
This one method will manage insertion in the List in sorted manner without using Collections.sort(list)
You can do it in log (N) time Complexity simply. No need to iterate through all the values. you can use binary search to add value to sorted linked list.just add the value at the position of upper bound of that function.
Check code... you may understand better.
public static int ubound(LinkedList<Integer> ln, int x) {
int l = 0;
int h = ln.size();
while (l < h) {
int mid = (l + h) / 2;
if (ln.get(mid) <= x) l = mid + 1;
else h = mid;
}
return l;
}
public void solve()
{
LinkedList<Integer> ln = new LinkedList<>();
ln.add(4);
ln.add(6);
ln.add(ubound(ln, 5), 5);
out.println(ln);
}
Output : [4, 5, 6]
you can learn about binary search more at : https://www.topcoder.com/community/data-science/data-science-tutorials/binary-search/
#Atrakeur
"sorting all the list each time you add a new element isn't efficient"
That's true, but if you need the list to always be in a sorted state, it is really the only option.
"The best way is to insert the element directly where it has to be (at his correct position). For this, you can loop all the positions to find where this number belong to"
This is exactly what the example code does.
"or use Collections.binarySearch to let this highly optimised search algorithm do this job for you"
Binary search is efficient, but only for random-access lists. So you could use an array list instead of a linked list, but then you have to deal with memory copies as the list grows. You're also going to consume more memory than you need if the capacity of the list is higher than the actual number of elements (which is pretty common).
So which data structure/approach to take is going to depend a lot on your storage and access requirements.
[edit]
Actually, there is one problem with the sample code: it results in multiple scans of the list when looping.
int i = 0;
while (llist.get(i) < val) {
i++;
}
llist.add(i, val);
The call to get(i) is going to traverse the list once to get to the ith position. Then the call to add(i, val) traverses it again. So this will be very slow.
A better approach would be to use a ListIterator to traverse the list and perform insertion. This interface defines an add() method that can be used to insert the element at the current position.
Have a look at com.google.common.collect.TreeMultiset.
This is effectively a sorted set that allows multiple instances of the same value.
It is a nice compromise for what you are trying to do. Insertion is cheaper than ArrayList, but you still get search benefits of binary/tree searches.
Linked list isn't the better implementation for a SortedList
Also, sorting all the list each time you add a new element isn't efficient.
The best way is to insert the element directly where it has to be (at his correct position).
For this, you can loop all the positions to find where this number belong to, then insert it, or use Collections.binarySearch to let this highly optimised search algorithm do this job for you.
BinarySearch return the index of the object if the object is found in the list (you can check for duplicates here if needed) or (-(insertion point) - 1) if the object isn't allready in the list (and insertion point is the index where the object need to be placed to maintains order)
You have to find where to insert the data by knowing the order criteria.
The simple method is to brute force search the insert position (go through the list, binary search...).
Another method, if you know the nature of your data, is to estimate an insertion position to cut down the number of checks. For example if you insert 'Zorro' and the list is alphabetically ordered you should start from the back of the list... or estimate where your letter may be (probably towards the end).
This can also work for numbers if you know where they come from and how they are distributed.
This is called interpolation search: http://en.wikipedia.org/wiki/Interpolation_search
Also think about batch insert:
If you insert a lot of data quickly you may consider doing many insertions in one go and only sort once afterwards.
Solution of Amruth, simplified:
public class OrderedList<T extends Comparable<T>> extends LinkedList<T> {
private static final long serialVersionUID = 1L;
public boolean orderedAdd(T element) {
ListIterator<T> itr = listIterator();
while(itr.hasNext()) {
if (itr.next().compareTo(element) > 0) {
itr.previous();
break;
}
}
itr.add(element);
}
}
Obviously it's O(n)
What is the best way to do a resizable array in Java? I tried using Vector, but that shifts all elements over by when when you do an insert, and I need an array that can grow but the elements stay in place. I'm sure there's a simple answer for this, but I still not quite sure.
As an alternative, you could use an ArrayList. It is a resizable-array implementation of the List interface.
Usage (using String):
List<String> myList = new ArrayList<String>();
myList.add("a");
myList.add("c");
myList.add("b");
The order will be just like you put them in: a, c, b.
You can also get an individual item like this:
String myString = myList.get(0);
Which will give you the 0th element: "a".
Like Sanjo pointed out: "An array is a static datastructure, so they can't grow". The list interface can by backed by an array(for example ArrayList like Kevin pointed out in his post). When the list structure is full and a new item has to be added to the list. Then the structure first creates a new array which can contain the old elements plus the new element which has to be added to the list.
The list interface has a different implementations which all have there pros/cons and you should pick the one best solving your problem-set. Below I will try to give a short summary when to use which implementation:
Not thread-safe implementations:
ArrayList: Resizable-array implementation of the List interface. You should use this implementation when you are doing a lot of size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, that is, adding n elements requires O(n) time. I think you should use this implementation when doing more lookups(get()) then adding items to list(add()).
LinkedList: This implementation is not backup by an array but "links" the nodes together. In my opinion you should use this implementation when you are doing more add() then get().
Thread-safe implementations:
Be aware that these list implementations aren't thread-safe which means it is possible to get race conditions when accesing them from multiple threads. If you want to use List implementations from multiple threads I would advise you to study the java.util.concurrent package and use implementation from that class.
You probably should use ArrayList instead of Vector for reasons explained in other answers.
However ...
I tried using Vector, but that shifts all elements over by when when you do an insert, and I need an array that can grow but the elements stay in place.
When you do an insertElementAt(pos, elem), you have specifically asked for the element shifting. If you don't want the elements to be shifted, you should use set(pos, elem) instead. Or if you want to add the element at the end of the vector, you can also use add(elem).
Incidentally, the previous paragraph applies to all implementations of List, not just Vector, though the implementation details and performance vary across the different kinds of List.
I tried using Vector, but that shifts all elements over by when when you do an insert, and I need an array that can grow but the elements stay in place.
You probably want to use ArrayList instead of Vector.
They both provide about the same interface, and you can replace elements with both of them by calling set(idx, element). That does not do any shifting around. It also does not allow you to grow the array, though: You can only insert at already occupied positions (not beyond the current size of the array), to add new elements at the end you have to use add(element).
The difference between ArrayList and Vector is that Vector has synchronization code which you most likely do not need, which makes ArrayList a little faster.
If you want to operate array data after all element had already inserted or deleted, there is a way that try to create a LinkedList or ArrayList, its simply resize, after the data input is finished, you can transfer the ArrayList to an Array, then do all the things you normally to Array.
ArrayList and LinkedList
Space Complexity:
a) ArrayList:
Allocates a chunk of memory when you initialize and doubles everytime it reaches it max size whenever you add an element dynamically.
b) LinkedList:
It allocates memory only everytime you add an item to the list.
Runtime Complexity:
a) ArrayList:
Search is faster, insertion and deletion is slower compared to linked list
b) LinkedList:
Insertion and deletion is faster, search is slower compared to array list
An array cannot be resized dynamically in Java. The solution to this is using ArrayList or creating another temporary array and then assign it.
You can find tutorials about ArrayList, but if you just want custom ResizableArray in Java. Here's it is. But it's NOT recommend to use! It's just a FAKE resizable array and heap memory will be increased when you create too many objects. This is just to show you the idea.
The Interface
public interface Resizable<T> {
void add(T data);
int delete(int index);
int size();
void print();
}
Implementation Class
public class ResizeableImpl<T> implements Resizable<T> {
private Object[] temp = null;
private Object[] originals = new Object[0];
#Override
public void add(T data) {
Object[] temp = new Object[originals.length+1];
for (int i=0; i<originals.length; i++) {
temp[i]=originals[i];
}
temp[originals.length]=data;
originals=temp;
}
#Override
public int delete(int index) {
int success=0;
switch (originals.length) {
case 0: //No Data to delete
success=0;
break;
case 1: //One Data is delete and so no data, too!
originals = new Object[0];
success = 1;
break;
default: //>=2
int count=0;
originals[index]=null;
temp = new Object[originals.length-1];
for (int i=0; i<originals.length; i++) {
if (originals[i]!=null)
temp[count++]=originals[i];
}
originals = temp;
success = 1;
}
return success;
}
#Override
public int size() {
return originals.length;
}
#Override
public void print() {
StringBuilder sb = null;
if (originals.length==0) {
System.out.println("No data available!");
return;
}
for (int i=0; i<originals.length; i++) {
if (sb==null) {
sb = new StringBuilder();
sb.append(originals[i]);
}
else {
sb.append(", "+originals[i]);
}
}
sb.append(".");
System.out.println(sb.toString());
}
}
Main method
public class App {
public static void main(String[] args) {
//Program to interfaces, not implementations
Resizable<Integer> obj = new ResizeableImpl<>();
obj.add(13);
obj.add(20);
obj.add(17);
obj.add(25);
obj.add(100);
obj.add(12);
obj.print();
int result = obj.delete(2); //This will delete 17.
if (result==1) {
System.out.println("Deletion is successful!");
}
obj.print();
obj.delete(3); //This will delete 100.
obj.print();
}
}
Output
13, 20, 17, 25, 100, 12.
Deletion is successful!
13, 20, 25, 100, 12.
13, 20, 25, 12.
Use either ArrayList or LinkedList.
Using wonderful classes in Collections framework is the better than using arrays.
But in case your question is from a "quizzing" perspective, here is what you should do.
Create your own resize method such as:
int[] oldArray = {1,2,3};
int oldSize = java.lang.reflect.Array.getLength(oldArray);
Class elementType = oldArray.getClass().getComponentType();
Object newArray = java.lang.reflect.Array.newInstance(
elementType,newSize);
int preserveLength = Math.min(oldSize,newSize);
if (preserveLength > 0)
System.arraycopy (oldArray,0,newArray,0,preserveLength);
oldArray = newArray;