Code from PriorityQueue:
private E removeAt(int i) {
assert i >= 0 && i < size;
modCount++;
int s = --size; // <- Why???
if (s == i) // removed last element
queue[i] = null;
else {
E moved = (E) queue[s];
queue[s] = null;
siftDown(i, moved);
if (queue[i] == moved) {
siftUp(i, moved);
if (queue[i] != moved)
return moved;
}
}
return null;
}
What's differences between s = --size and s = size? Anybody could help? Thanks in advance.
int s = --size; is a pre-decrement operator, and that is not equivalent to int s = size;. It is equivalent to
int s = (size = (size - 1));
or
size = size - 1;
int s = size;
But it is shorter than both of those.
If you use s = size, then you need to add line size = size - 1. As you have to decrease the queue size after removal of an element.
a = i++ means a = i ; i = i + 1
a = ++i means i = i + 1 ; a = i ;
the same to minus
PriorityQueue is based on array private transient Object[] queue;. In PriorityQueue this array stores data of binary heap. removeAt(int) is an operation on removing an element from heap. You remove element from heap by taking the last element of the heap (here you use int s = --size to assign to s the index of last element; alternatively you can do int s = heap.length - 1).
Then delete the element you want queue[s] = null; and do work to fill the gap in array with sifting operations siftDown, siftUp.
Related
I have this code but it prints null word 20 times.
Please help me understand why the elements are not copied instead.
public class StrList {
public void add(String y) {
if (currsize == elements.length) {
System.out.println("no more room to add " + y); // fix this to increase space instead!
}
int newSize = elements.length * 2;
newElements = new String [newSize];
for (int i = 0; i <currsize; i++){
elements = newElements; }
elements[currsize] = y;
currsize += 1; // or currsize++
}
I see a reassignment to elements done currSize times. Maybe you forgot a [i]?
i'm tasked with creating a method which has the same functionality as splice however I cannot get the appropriate value into the appropriate index. My code works as follows,
public void PlaceElementAt(int newValue, int index) throws ArrayIndexOutOfBoundsException {
//check that index is valid
if (index >= 0 && index <= data.length) { //Checks that the index is within position 0 and 7 by default.
System.out.println ("Index is valid"); //returns index is valid if so
}
//increase size if necessary
if (data.length == numElements) { //checking if the number of elements is filling the spaces
doubleCapacity(); // calls upon the double capacity method if it is
}
if (numElements==0) {
data[numElements] = newValue;
System.out.println ("Element: " + data[numElements] + " at index: " + index);
numElements++;
}
//shuffle values down from index
else {
int bottompos = numElements-1;
int loopcount = numElements-index;
int NewBottom = numElements+1;
for (int i=0; i<loopcount; i++){
data[bottompos]=data[NewBottom];
bottompos--;
NewBottom--;
}
//insert newValue at index
data[numElements] = newValue;
System.out.println ("Element: " + data[numElements] +" at index: " + index);
numElements++;
}
}
My issue is apparent when I later give the commands in my main method.
myData.PlaceElementAt(3,0)
myData.PlaceElementAt(2,5)
myData.PlaceElementAt(7,3)
Once I check my breakpoints i see the values are being added to the array however they are being added on a 1 by 1 basis starting from index 0. Any suggestions greatly helps.
I'm making some assumptions about how your class is structured (adjust as needed), but generally I would recommend shifting right as it will simplify the overall process. Essentially we have an array with maximum allowed size given by MAX and current size given by size. Any time we add to the array, we increment the value of size by 1 (such as insertions or adding to the back of our list). Now, let's say we want to insert a value at index. This will entail shifting all elements at and right of this index by 1 to the right and then inserting our value in the space we have made. Before doing any inserting we first need to check that we have enough space to insert the item. If there is not enough space, we will need to allocate additional space, prohibit the insertion, or some other alternative. In your case, it looks like you want to allocate more space.
class MyList
{
private int MAX = 6;
private int size = 0;
private int[] array;
public MyList()
{
array = new int[MAX];
}
public void placeElementAt(int value, int index)
{
if (size == 0)
{
// If size is 0, just insert the value at index 0.
array[size++] = value;
return;
}
if (index < 0 || index >= size)
{
// Index is out of bounds.
System.out.println("Invalid index.");
return;
}
if (size >= MAX)
{
// Max capacity reached -> allocate more space.
doubleCapacity();
}
// Shift all elements at and above index right by 1.
for (int i = size - 1; i >= index; i--)
{
array[i + 1] = array[i];
}
// Insert element.
array[index] = value;
size++;
}
public void doubleCapacity()
{
int[] newArray = new int[MAX * 2];
// Copy old elements to new array.
for (int i = 0; i < size; i++)
{
newArray[i] = array[i];
}
// Double MAX to reflect new array.
MAX *= 2;
array = newArray;
System.out.println("Doubled");
}
public void add(int value)
{
if (size >= MAX)
{
// Max capacity reached -> allocate more space.
doubleCapacity();
}
// Add the element to the back of the list.
array[size++] = value;
}
public void print()
{
for (int i = 0; i < size; i++)
{
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[] args)
{
MyList data = new MyList();
data.placeElementAt(1, 0);
data.print();
data.placeElementAt(2, 0);
data.print();
data.placeElementAt(3, 0);
data.print();
data.placeElementAt(5, 0);
data.print();
data.placeElementAt(3, 0);
data.print();
data.placeElementAt(9, 0);
data.print();
data.placeElementAt(4, 0);
data.print();
data.placeElementAt(6, 0);
data.print();
}
}
The output of this program (with initial MAX = 6) would be...
1
2 1
3 2 1
5 3 2 1
3 5 3 2 1
9 3 5 3 2 1
Doubled
4 9 3 5 3 2 1
6 4 9 3 5 3 2 1
Well, seeing your code, you're receiving a "index" parameter. But you're not using the index to insert on your array.
Your code:
data[numElements] = newValue;
numElements++;
Try this:
data[index] = newValue;
numElements++;
I think this will solve it, but later you'll have to handle the cases where the specified index already have an element.
I am learning to use heaps and as an exercise I am trying to write a program using a heap class I have created to sort words. I have read in words from a file and added them to the heap successfully. I am having some trouble figuring out how I can print out a sorted list of the words. From my understanding of how a min-heap works, if I remove from the min/root node they will always be removed in sorted order. So far I have tried out to do a simple for loop but, only half of the heap is being removed.
My Main Attempt
public static void main(String[] args) {
Heap heap = new Heap();
heap = read( heap );
for( int i = 0; i < heap.getSize(); i++){
heap.removeMin();
}
heap.printHeap();
}
This is the remove function in my Heap Class
public Node removeMin(){
Node min = heap.get(0);
int index = heap.size() - 1;
Node last = heap.remove(index);
if( index > 0 ){
heap.set( 0, last );
Node root = heap.get(0);
int end = heap.size() - 1;
index = 0;
boolean done = false;
while(!done){
if(getLCLoc(index) <= end ){
//left exists
Node child = getNodeAt( getLCLoc(index) );
int childLoc = getLCLoc(index);
if( getRCLoc(index) <= end ){
//right exists
if( getNodeAt( getRCLoc(index) ).getData().compareToIgnoreCase( child.getData() ) < 0 ){
child = getNodeAt( getRCLoc(index) );
childLoc = getRCLoc(index);
}
}
if(child.getData().compareToIgnoreCase( root.getData() ) < 0 ){
heap.set( index, child );
index = childLoc;
}else{
done = true;
}
}else{
//no children
done = true;
}
}
heap.set( index, root );
}
return min;
}
I would guess that remove() decreases heap size by 1. So, for each iteration of your loop, you are incrementing i by 1 and decrementing heap size by 1. I would change to a while loop that runs while heapsize >0.
I want to find the Nth number of the Recurrence Equation
T(n)=T(n-1)+3T(n-2)+3T(n-3)+(n-4),T(1)=T(4)=1,T(2)=T(3)=3
so if suppose you entered 2,5,9 as input, output should be T(2)=3,T(5)=20,T(9)=695
what I did is create an array of size equal to maximum of all input value and storing solution of T(i) at index i.Then look up into the array for specific index. eg array[3] for T(3),array[5] for T(5),etc
The code worked fine till maximum number is not greater than maximum integer value system can hold i.e
Integer.MAXValue.
Because the index of array can only be integer then
if number is n=1855656959555656 what should be the best way to find the solution of
T(1855656959555656)?
as clearly I cant create an array of size=1855656959555656..
I have even tried BigInteger from java.Math but with no success.
I have to find some other approach.please suggest some ideas..
Thanks
you do not need to store every T(i), you only need to store 3 values T(i-1), T(i-2), T(i-3). While looping over i, check if the current i should be part of your output, if so put it out immediately or save it to an "output"-array.
edit: this part is quite inefficient. You check in every iteation EVERY needed output.
for (int k = 0; k < arr.length; ++k) {
if (count == arr[k])
T[k] = temp[i];
else if (arr[k] == 1)
T[k] = 1;
else if (arr[k] == 2)
T[k] = 3;
else if (arr[k] == 3)
T[k] = 3;
else if (arr[k] == 4)
T[k] = 1;
}
so your code runs in time (max*arr.length) you can reduce it to only (max). Use a HashMap with key=neededPosition (=count) value=position in arr
Init the map like this:
Map<Long, Integer> map = new HashMap<Long, Integer>();
for (int i = 0; i < arr.length; i++) {
map.put(arr[i], i);
}
if (map.containsKey(count)) {
T[map.get(count)] = temp[i]
}
check the values 1-4 just once after the whole thing!
Not possible. The array size can be a maximum of Integer.MAX_VALUE (minus something usually 5 or 8, depending on the JVM capabilities). Why?. The index for an Array should be an integer thats a limitation.
It can't be done. So you need to solve the problem by introducing a sharding mechanism. The simplest way would be to just have arrays of arrays with a fixed length.
Edit: You really do not need this much storage for your problem at hand (as pointed out in another answer; this code fragment avoids arrays altogether to avoid bounds checks / indirection):
public void t(long n) {
if (n < 5) {
return (n == 2 || n == 3) ? 3 : 1;
}
long i = 5; // Initialize variables for n == 5;
long tn_1 = 1; // T(n-1) = T(4) = 1;
long tn_2 = 3; // T(n-2) = T(3) = 3;
long tn_3 = 1; // T(n-3) = T(2) = 1;
long tn_4 = 3; // T(n-4) = T(1) = 3;
while (true) {
long tn = tn_1 + 3*tn_2 + 3*tn_3 + tn_4;
if (i++ == n) {
return tn;
}
tn_4 = tn_3;
tn_3 = tn_2;
tn_2 = tn_1;
tn_1 = tn;
}
}
To answer the question in the title anyway:
If your array is sparse, use a map (TreeMap or HashMap) of Long or BigInteger:
Map<Long,Long> t = new TreeMap<Long,Long>()
The memory consumption of sparse arrays depends on the number of elements actually stored, so you may want to delete values from the map that are no longer needed.
If your array is not sparse, use a 2-level array (memory consumption will depend on the pre-allocated size only):
public class LongArray {
static final long BLOCK_SIZE = 0x40000000;
long[][] storage;
public LongArray(long size) {
long blockCount = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
storage = new long[][(int) blockCount];
for (long i = 0; i < blockCount; i++) {
if (i == blockCount - 1) {
storage[i] = new long[(int) size - BLOCK_SIZE * (blockCount - 1)];
} else {
storage[i] = new long[(int) BLOCK_SIZE];
}
}
}
public long get(long index) {
return storage[(int) (index / BLOCK_SIZE)][(int) (index % BLOCK_SIZE)];
}
public void put(long index, long value) {
storage[(int) (index / BLOCK_SIZE)][(int) (index % BLOCK_SIZE)] = value;
}
}
In both cases, use t.get(index) and t.put(index, value) instead of t[index] to access your array (if t is the name of the array).
You can do one thing. Check if the value of n is equal to 1855656959555656 in the beginning or if its multiple. Suppose, the value of n is twice of 1855656959555656. Then you can create two arrays and link them together virtually. This should solve your problem but it will involve a lot of overhead.
Use recursive call:
int T(int n){
if (n==1 || n==4){
return 1;
} else if (n==2 || n==3){
return 3;
} else {
return T(n-1)+3*T(n-2)+3T*(n-3)+T(n-4);
}
}
Edit: Time consumming. Won't work with large numbers
public Collection<Comment> getCommentCollection() {
commentCollection = movie.getCommentCollection();
return split((List<Comment>) commentCollection, 4);
}
public Collection<Comment> split(List<Comment> list, int size){
int numBatches = (list.size() / size) + 1;
Collection[] batches = new Collection[numBatches];
Collection<Comment> set = commentCollection;
for(int index = 0; index < numBatches; index++) {
int count = index + 1;
int fromIndex = Math.max(((count - 1) * size), 0);
int toIndex = Math.min((count * size), list.size());
batches[index] = list.subList(fromIndex, toIndex);
set = batches[index];
}
return set;
}
I am trying to split a bigger collection into smaller collections, depending on the number of items in the original collection. And then return one of the smaller collections every time the get method is called while keeping track of which smaller collection is returned. How can I achieve this?
Maybe I don't understand the question, but this is part of List:
List<E> subList(int fromIndex, int toIndex)
Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.
This method eliminates the need for explicit range operations (of the sort that commonly exist for arrays). Any operation that expects a list can be used as a range operation by passing a subList view instead of a whole list. For example, the following idiom removes a range of elements from a list:
list.subList(from, to).clear();
docs.oracle.com/javase/1.5.0/docs/api/java/util/List.html
This is simple: just use Lists.partition() from Guava. If I understand what you want correctly, it's exactly what it does.
private int runs = 0;
public void setRunsOneMore() {
runs++;
}
public void setRunsOneLess() {
runs--;
}
public Collection<Comment> getCommentCollection() {
commentCollection = movie.getCommentCollection();
Collection[] com = split((List<Comment>) commentCollection,4);
try{
return com[runs];
} catch(ArrayIndexOutOfBoundsException e) {
runs = 0;
}
return com[runs];
}
public Collection[] split(List<Comment> list, int size){
int numBatches = (list.size() / size) + 1;
Collection[] batches = new Collection[numBatches];
Collection<Comment> set = commentCollection;
for(int index = 0; index < numBatches; index++) {
int count = index + 1;
int fromIndex = Math.max(((count - 1) * size), 0);
int toIndex = Math.min((count * size), list.size());
batches[index] = list.subList(fromIndex, toIndex);
}
return batches;
}
Setting the current "run" with the next & previous button actions
public String userNext() {
userReset(false);
getUserPagingInfo().nextPage();
movieController.setRunsOneMore();
return "user_movie_detail";
}
public String userPrev() {
userReset(false);
getUserPagingInfo().previousPage();
movieController.setRunsOneLess();
return "user_movie_detail";
}
I'm not entirely sure what you're asking... do you want to remove the first 4 items from the source Collection before returning them, so that you get the next 4 the next time you call the method? If so, you could just use the Iterator:
Iterator<Comment> iter = commentCollection.iterator();
while (iter.hasNext() && group.size() < 4) {
group.add(iter.next());
iter.remove();
}
By doing this, though, you'd be destroying the movie object's collection of comments (unless it returns a copy of that collection each time, in which case the above wouldn't work at all). I'm guessing you're trying to do something like paging, in which case I'd suggest doing something different like partitioning a List of comments with size 4 and keeping track of a current index (the page) in that partition list.
public static <E extends Object> List<List<E>> split(Collection<E> input, int size) {\n
List<List<E>> master = new ArrayList<List<E>>();
if (input != null && input.size() > 0) {
List<E> col = new ArrayList<E>(input);
boolean done = false;
int startIndex = 0;
int endIndex = col.size() > size ? size : col.size();
while (!done) {
master.add(col.subList(startIndex, endIndex));
if (endIndex == col.size()) {
done = true;
}
else {
startIndex = endIndex;
endIndex = col.size() > (endIndex + size) ? (endIndex + size) : col.size();
}
}
}
return master;
}
You can create a separate sublist that is a deep copy of the original list using the ArrayList constructor.
import java.util.ArrayList;
import java.util.List;
class Scratch {
public static void main(String[] args) {
final List<String> parent = new ArrayList<>();
parent.add("One");
parent.add("Two");
parent.add("Three");
// using the ArrayList constructor here
final List<String> copy = new ArrayList<>(parent.subList(0, 2));
// modifying the new list doesn't affect the original
copy.remove(0);
// outputs:
// parent: [One, Two, Three]
// copy: [Two]
System.out.println("parent: " + parent);
System.out.println("copy: " + copy);
}
}
You can use Vector.remove(collection), example:
public Collection<Comment> getCommentCollection() {
commentCollection = movie.getCommentCollection();
Vector<Comment> group = new Vector<Comment>();
for (Comment com:commentCollection){
group.add(com);
if(group.size() == 4){
break;
}
}
movie.getCommentCollection().remove(commentCollection);
return commentCollection;
}
assuming movie.getCommentCollection() is also a vector
here is my implementation. hope it helps!
dependencies CollectionUtils and Lists to see:
https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/
/**
* efficient collection partition
*
* #param baseCollection base collection to split
* #param maxSize max element size of each sublist returned
* #param balancing whether each of sublists returned needs size balancing
* #return list of sublists, whose order bases on the base collection's iterator implementation
* #since 2020/03/12
*/
public static <T> List<List<T>> partition(final Collection<T> baseCollection, int maxSize, boolean balancing) {
if (CollectionUtils.isEmpty(baseCollection)) {
return Collections.emptyList();
}
int size = baseCollection.size() % maxSize == 0 ? baseCollection.size()/maxSize : baseCollection.size()/maxSize+1;
if (balancing) {
maxSize = baseCollection.size() % size == 0 ? baseCollection.size()/size : baseCollection.size()/size+1;
}
int fullElementSize = baseCollection.size() % size == 0 ? size : baseCollection.size() % size;
List<List<T>> result = Lists.newArrayListWithExpectedSize(size);
Iterator<T> it = baseCollection.iterator();
for (int i = 0; i < size; i++) {
if (balancing && i == fullElementSize) {
maxSize--;
}
maxSize = Math.min(maxSize, baseCollection.size()-i*maxSize);
List<T> subList = Lists.newArrayListWithExpectedSize(maxSize);
for (int i1 = 0; i1 < maxSize; i1++) {
if (it.hasNext()) {
subList.add(it.next());
} else {
break;
}
}
result.add(subList);
}
return result;
}