I am getting an error:
java.lang.ArrayIndexOutOfBoundsException: -1
and it refers to method inject:
deque[back] = x;
I also have methods for push and pop which add and remove items at the front but those work fine.
The idea is to use an array-based implementation as deque, where inject and eject insert item at the back and remove item at the back.
public void inject(int x){
if (elementCount == size){
System.out.println("The Deque is Full");
} else {
deque[back] = x;
back = (back - 1) % size;
elementCount ++;
}
}
public class Deque {
int[] deque;
int front;
int back;
int size;
int elementCount;
public Deque(int s){
size = s;
deque = new int[size];
front = 1;
back = 0;
elementCount = 0; //n of elements
}
public int getRear(){
return deque[back];
}
public int getFront(){
return deque[front];
}
public void inject(int x){
if (elementCount == size){
System.out.println("The Deque is Full");
} else {
deque[back] = x;
back = (back - 1) % size;
elementCount ++;
}
}
public void eject(){
if (elementCount == 0){
System.out.println("The deque is empty");
}else{
back = (back + 1) % size;
elementCount--;
}
}
}
You have in multiple places:
back = (back - 1) % size;
That doesn't work like you think it does when back is originally 0, where it becomes -1 % size, which is usually -1. In the places where it appears, you should instead use:
back = (size + back - 1) % size;
First thing I notice is you are using too many variables for this problem. If you break it down you only need 3 variables. the array, the size of the array and current location in the array for inject and eject. This is a LiFo( Last in First Out) order.
public void inject(int x){
if (this.deque.size() == this.size){ //check for full array
System.out.println("The Deque is Full");
} else {
this.deque[this.back+1] = x; //input new item next slot
this.back ++; //increment back to new input where eject would pull from
}
}
public class Deque {
int[] deque;
int back;
int size;
public Deque(int s){
this.size = s;
this.deque = new int[size];
this.back = 0;
}
this should also solve your array index issue I am not sure why you were using a Modulo function '%' for the current location of back.
Related
I'm actually doing an easy CodinGame --> I have to find if an element exists in a list.
I've tested a first solution, it was working but it wasn't really optimized (according to the machine).
So I've tried another solution but :
When I test my code for this 2nd solution, it returns the right answers but when I'm submitting my code, it tells me that my solution is completely wrong (it doesn't work if the list is empty, and also if the list is huge, ...).
Please can you help me ?
Here is my first naive solution :
public static boolean check(int[] ints, int k) {
boolean res = false;
for(int i : ints){
if(i == k){
res = true;
break;
}
}
return res;
}
Here is the code of my 2nd solution that is supposed to be optimized:
static boolean exists(int [] ints, int k){
boolean res = false;
int first = 0;
int last = ints.length;
int mid = (first + last)/2;
while(first <= last){
if( ints[mid] < k){
first = mid +1;
}else if (ints[mid] == k){
res = true;
break;
}else{
last = mid -1;
}
mid = (first + last)/2;
}
if(first > last){
res = false;
}
return res;
}
Finally I've found the solution to my problem !!!!!
Here it is :
import java.util.Arrays;
class A{
static boolean exists(int[] ints, int k){
boolean res = false;
int index = Arrays.binarySearch(ints, k);
if (index<0){
res = false;
}else{
res = true;
}
return res;
}
}
I suppose you are trying to implement Binary search in the second solution.
If so, please check this answer. Your input array must be sorted in non-decreasing order, because Binary Search works only with sorted input data. For example, you can simply type Arrays.sort(arr); and then pass your array into exists() method. But the overall time&space complexities will be O(n log n).
Fixed some bugs in your implementation:
public static boolean exists(int[] ints, int k) {
int first = 0;
int last = ints.length - 1;
while (first <= last) {
int mid = first + (last - first) / 2; // to avoid integer overflow in extremely large arrays
if (ints[mid] < k) {
first = mid + 1;
} else if (ints[mid] == k) {
return true;
} else {
last = mid - 1;
}
}
return false;
}
I require an implementation of a Priority queue that allows decrease priority operation to allow for an efficient implementation for Prim's and Dijkstra's algorithm.
I've coded up a minHeap implementation using a HashMap to store the indices of elements in my heap.
The problem I'm working on requires the computation of the total weight of the minimum spanning tree obtained by using Prim's algorithm. While my implementation works for most test cases upto 200 nodes, I'm still getting the incorrect output for many larger test cases.
It is my understanding that such minheap based implementations of Priority queues using HashMaps are common, if I am wrong in my assumption, please provide the more suitable approach to this problem.
I've been trying to debug my code for 2 days now and it seems the only way to fix it would be to compare it with a correctly functioning implementation.
Therefore, can someone please share such a PriorityQueue implementation using HashMap in java.
Even though I've tried a lot of test cases and for all the ones I can trace on my own(upto 30 nodes) I've gotten correct answers so far, but if there are some specific boundary test cases that could help me identify the problem, that too will be great.
Here is my code, I understand debugging it will be time consuming for anyone else, but if there is something obvious I've missed and someone with more expertise can point out the mistake, that would be most appreciated.
import java.util.HashMap;
import java.util.NoSuchElementException;
public class Heap<Key extends Comparable<Key>> {
private Key[] heap;
private int maxN, n;
private HashMap<Key, Integer> map;
#SuppressWarnings("unchecked")
public Heap(int maxN) {
if(maxN < 0 ) throw new IllegalArgumentException();
this.maxN = maxN;
n = 0;
heap = (Key[]) new Comparable[maxN];
map = new HashMap<>(maxN);
}
boolean isEmpty() {
return n == 0;
}
boolean insert(Key e) {
if(n +1 > maxN) throw new IllegalArgumentException("maximum capacity reached " + maxN);
heap[n] = e;
map.put(e,n);
int i = n++;
while ( (i+1)/2 - 1 >= 0){
if ( e.compareTo(heap[(i+1)/2 - 1]) < 0 ) {
swap(i, (i+1)/2 - 1);
i = (i+1)/2 - 1;
}
else
break;
}
return true;
}
Key extractMin() {
if(n == 0) throw new NoSuchElementException("Priority queue underflow ");
Key min = heap[0];
swap(0, n-1);
map.remove(min);
n--;
int j = 0, s;
while(j <= (n/2)-1){
if(j == (n/2)-1 && n == (j+1)*2 )
s = (j+1)*2 - 1;
else
s = heap[(j+1)*2 - 1].compareTo(heap[(j+1)*2]) < 0 ? (j+1)*2 - 1 : (j+1)*2;
if(heap[j].compareTo(heap[s]) > 0 ){
swap(j, s);
j = s;
}
else break;
}
return min;
}
Key delete(Key e){
if(!map.containsKey(e)) throw new NoSuchElementException(e+"does not exist ");
int j = map.get(e), s;
Key del = e;
swap(j, n-1);
map.remove(e);
n--;
while( j <= n/2 - 1){
if(j == (n/2)-1 && n == (j+1)*2)
s = (j+1)*2 - 1;
else
s = heap[(j+1)*2 - 1].compareTo(heap[(j+1)*2]) < 0 ? (j+1)*2 - 1 : (j+1)*2;
if(heap[j].compareTo(heap[s]) > 0 ){
swap(j, s);
j = s;
}
else break;
}
return del;
}
boolean decreasePriority(Key e){
if(n == 0)
return insert(e);
if(map.containsKey(e))
delete(e);
return insert(e);
}
private void swap(int i, int j) {
Key t = heap[i];
heap[i] = heap[j];
heap[j] = t;
map.replace(heap[i], i);
map.replace(heap[j], j);
}
#Override
public String toString() {
String res = "[";
int i;
for (i = 0; i < n-1; i++){
res += heap[i] + ", ";
}
res += heap[i]+"]";
return res;
}
}
I think the problem is in your delete method. Your code does this:
swap item to be removed with the last item in the heap
reduce heap count
push the new item down the heap
You're making the assumption that heap[j] < heap[n-1]. That's not a valid assumption. Consider this heap:
1
6 2
7 8 3
If you delete the node with value 7, the value 3 replaces it:
1
6 2
3 8
You now have to move it up the tree to make a valid heap:
1
3 2
6 8
The key here is that if the item you're replacing is in a different subtree than the last item in the heap, it's possible that the replacement node will be smaller than the parent of the replaced node.
If you're removing an item from the middle of the heap, you swap the item with the last, then you have to check whether the replacement node moves up or down.
Something you should consider, though, is that to change an item's priority, you don't have to delete and re-add. All you have to do is change the priority and then adjust the item's position appropriately: move up or down to put it in its new position.
The delete method was incorrect, I was using the same procedure for arbitrary deletes as for extractMin, which did not take into account the fact that the element I replace the key to be deleted with could possibly go both up or down the heap. Using swim() and sink() methods I have rectified this error. Also to change priority deletion and insertion are not required, and a simple call to both swim and sink is sufficient.(only swim if only decreasing priority and only sink if only increasing).
import java.util.HashMap;
import java.util.NoSuchElementException;
public class Heap<Key extends Comparable<Key>> {
private Key[] heap;
private int maxN, n;
private HashMap<Key, Integer> map;
#SuppressWarnings("unchecked")
public Heap(int maxN) {
if(maxN < 0 ) throw new IllegalArgumentException();
this.maxN = maxN;
n = 0;
heap = (Key[]) new Comparable[maxN];
map = new HashMap<>(maxN);
}
boolean isEmpty() {
return n == 0;
}
boolean insert(Key e) {
if(n +1 > maxN) throw new IllegalArgumentException("maximum capacity reached " + maxN);
heap[n] = e;
map.put(e,n);
int i = n++;
swim(i);
return true;
}
Key extractMin() {
if(n == 0) throw new NoSuchElementException("Priority queue underflow ");
Key min = heap[0];
swap(0, n-1);
map.remove(min);
n--;
sink(0);
return min;
}
void delete(Key e){
if(!map.containsKey(e)) throw new NoSuchElementException(e+" does not exist ");
int j = map.get(e);
swap(j, n-1);
map.remove(e);
n--;
if(!swim(j))
sink(j);
}
void decreasePriority(Key e){
if(map.containsKey(e)){
int j = map.get(e);
swim(j);
}
else insert(e);
}
private void swap(int i, int j) {
Key t = heap[i];
heap[i] = heap[j];
heap[j] = t;
map.replace(heap[i], i);
map.replace(heap[j], j);
}
private boolean swim(int j){
boolean change = false;
int parent;
while( (parent = (j-1)/2 ) >= 0){
if(heap[j].compareTo(heap[parent]) < 0){
swap(j,parent);
j = parent;
change = true;
}
else break;
}
return change;
}
private void sink(int j){
while(j <= n/2 - 1){
int leftChild = j*2 + 1, rightChild = leftChild + 1, s;
if(rightChild >= n)
s = leftChild;
else
s = heap[leftChild].compareTo(heap[rightChild]) < 0 ? leftChild : rightChild;
if(heap[j].compareTo(heap[s]) > 0){
swap(j,s);
j = s;
}
else break;
}
}
#Override
public String toString() {
String res = "[";
int i;
for (i = 0; i < n-1; i++){
res += heap[i] + ", ";
}
res += heap[i]+"]";
return res;
}
}
Edit: Be careful with your class comparator.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Can anyone tell me where I did wrong? My Queue class is working like a Stack, not a Queue. If I enqueue 1, 2, and 3 (in that order) and then dequeue, it removes the 3, not the 1.
Thank you in advance!
I am not sure where I did wrong!
Here is my code:
import java.util.NoSuchElementException;
public class Queue implements QueueADT
{
private int front = 0;
private int back = 0;
private int [] a;
private int size = 10;
public Queue(){
a = new int [10];
}
public Queue(int size){
a = new int [size];
this.size = size;
}
//enqueue - adds an element to the back of the queue
public void enqueue(int element){
if(((back+1) - front) == -1 || ((back+1) - front) == (a.length - 1))
resizeArray();
if (back == a.length - 1)
back = 0;
a[back++] = element;
}
//dequeue - removes and returns the element from the
//front of the queue
public int dequeue(){
if(isEmpty())
throw new NoSuchElementException("Dequeue: Queue is empty");
if (front < back){
front ++;
return a[front-1];
}
else if (front > back){
front--;
return a[front++];
}
return 1;
}
//peek - returns but does not remove the element from
//the front of the queue
public int peek(){
if(isEmpty())
throw new NoSuchElementException("Peek: Queue is empty");
return a[front];
}
//isEmpty - determines if the queue is empty or not
public boolean isEmpty(){
return size() == 0;
}
private void resizeArray()
{
//double the size of the array
int[] newA = new int[a.length * 2];
int x = 0;
while(x < size - 1){
newA[x] = dequeue();
x++;
}
size = size *2;
front = 0;
back = x;
a = newA;
}
//size - returns the number of elements in our Queue
public int size(){
if (front > back ){
return size - (front - (back + 1));}
return back - front + 1;}
//toString - returns a String representation of our Queue
public String toString(){
if(isEmpty()) {
throw new NoSuchElementException("Queue is empty");
}
{
String s = "[ ";
//print queue
for(int i = 0; i < size(); i++)
s += a[i] + " ";
//print array
for(int j = size(); j < a.length; j++)
s += "* ";
s += "]";
return s;
}
}
//equals - determines if two queues are equivalent
//i.e. do they have the same elements in the same sequence
//ignoring the structure they are stored in
public boolean equals(Object otherQ){
if(otherQ == null)
return false;
else
{
//Figure out how many interfaces the other guy
//implements
int numIs = otherQ.getClass().getInterfaces().length;
boolean flag = false;
//look at all of the other guys interfaces
//and if he doesn't implement QueueADT, then
//he clearly isn't a Queue and we return false
for(int i = 0; i < numIs; i++)
{
if(this.getClass().getInterfaces()[0] ==
otherQ.getClass().getInterfaces()[i])
{
flag = true;
}
}
if(!flag)
return false;
else //we know that the other guy exists and
//we know that he implements QueueADT
{
QueueADT q = (QueueADT)otherQ;
if(this.size() != q.size())
return false;
else
{
boolean queuesEqual = true;
for(int i = 0; i < this.size(); i++)
{
int ourElement = this.dequeue();
int qElement = q.dequeue();
if(ourElement != qElement)
queuesEqual = false;
this.enqueue(ourElement);
q.enqueue(qElement);
}
//return our final answer
return queuesEqual;
}
}
}
}
public void showInnerWorkings(){
System.out.print("[");
for (int i = 0; i < this.a.length; i++)
System.out.print(this.a[i] +
(i != this.a.length - 1 ? ", " : ""));
System.out.println("]");
}
}
QueueADT interface:
public interface QueueADT
{
//enqueue - adds an element to the back of the queue
public void enqueue(int element);
//dequeue - removes and returns the element from the
//front of the queue
public int dequeue();
//peek - returns but does not remove the element from
//the front of the queue
public int peek();
//isEmpty - determines if the queue is empty or not
public boolean isEmpty();
//size - returns the number of elements in our Queue
public int size();
//toString - returns a String representation of our Queue
public String toString();
//equals - determines if two queues are equivalent
//i.e. do they have the same elements in the same sequence
//ignoring the structure they are stored in
public boolean equals(Object otherQ);
}
What do you really want? A Queue or a circular array ?
Circular array :
You should have a look there. As you can see, the simpliest (and the best) way is to extend the ArrayList class and override the get() method.
Queue :
Just use the java.util.Queue interface.
I'm working on a Java problem set that requires a particular method to be executed N number of times (in this case, N = 5).
For some reason, though, every time I run the program, it executes (or at least, prints out) 10 times. I cannot figure out how to make it print out only 5 times.
I'm very new to programming, so apologies if this is a simple fix. Thanks for the help!
public static void main (String [] args)
{
final int N = 5;
int sum = 0;
for (int i = 1; i <= N; i++)
{
drunkWalk();
int stepCount = drunkWalk();
sum += stepCount;
if (i == N)
{
System.out.println ("Average # of steps equals " + (sum/N));
}
}
}
public static int drunkWalk ()
{
int start = 5; //initializes variables
int steps = 0;
int position = 0;
System.out.println ("Here we go again...time for a walk!");
do
{
int direction = retInt ();
if (direction%2 == 0) //Determines if it will go left, towards home/0
{
position = start - 1;
}
else //Determines if it will go right, towards jail/10
{
position = start + 1;
}
start = position;
steps++;
} while (position != 0 && position != 10);
System.out.println ("Took " + steps + " steps, and");
if (position == 0)
{
System.out.println ("Landed at HOME");
}
else
{
System.out.println ("Landed in JAIL");
}
System.out.println ();
return steps; //So the sum of the # of steps can continue to be calculated for the sum in main's for loop
}
public static int retInt () //Returns odd or even integer to determine the direction in drunkWalk()
{
return (int)(6 * Math.random ());
}
}
drunkWalk();
int stepCount = drunkWalk();
You literally call it twice. Remove the first one to walk just once. Note that it doesn't assign its return value either, so it wouldn't do anything with the result that's being returned.
Hello fellow programmers.
I am having a very silly problem.. I'm supposed to sum all the integers in a List, recursively. I know that there is an easier way to do this, and I actually made that method too (see class below). But the meaning of this assignment is that I have to split the list up into 2 halves and then calculate the sum recursively on both halves, and last I just return half1 + half2.
The problem is that the advanced method does not return the sum of all values. Can anyone please help me?
The method sum is the simple method. Summer(Summarize in danish) is the more advanced method.
package opgave1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class BinærSøgning {
public static void main(String[] args) {
Random random = new Random();
int tal = 3;
List<Integer> liste = new ArrayList<Integer>();
for (int i = 0; i < 10; i++)
liste.add(random.nextInt(10));
Collections.sort(liste);
System.out.println(liste);
// System.out.println(binærSøgning(liste, 0, tal));
System.out.println(summer(liste, 0));
}
public static int binærSøgning(List<Integer> liste, int start, int find) {
if (liste.size() > 0) {
int midt = liste.size() / 2;
if (liste.get(midt) == find)
return start + midt;
else if (liste.size() > 1) {
if (find < liste.get(midt))
return binærSøgning(liste.subList(0, midt), start, find);
else
return binærSøgning(liste.subList(midt + 1, liste.size()), start + midt + 1, find);
}
}
return -1;
}
public static int sum (List<Integer> list, int i)
{
if (i == list.size())
return 0;
else
return list.get(i) + sum(list, i+1);
}
public static int summer(List<Integer> list, int start){
int right = 0;
int left = 0;
if(start == list.size()){
return 0;
} else {
int mid = list.size() / 2;
if(start < mid){
left += list.get(start) + summer(list.subList(0, mid), start+1);
} else if(mid < list.size()){
right += list.get(mid) + summer(list.subList(mid+1, list.size()), mid+1);
}
}
return right + left;
}
}
Ii's much easier with two base cases, there is no need for an extra 'start' parameter if you use sublists. (Because it's homework, I won't fill in the details.)
public static int summer(List<Integer> list) {
//base 1
if (list.size() == 0) {
}
//base 2
else if (list.size() == 1) {
}
else
{
//no need for if statements now!
int left = summer(list.sublist(/* */))
int right = summer(list.sublist(/* */))
return left + right;
}
}
Are you sure that you have to split the list? Usually, when you get this task for homework, the meaning is something like:
public static int sum(List<Integer> l,int start) {
if (start==l.size()) return 0;
return l.get(start)+sum(l,start+1);
}
You are missing out elements of list when you are sending start+1 in the recursion.
left += list.get(start) + summer(list.subList(0, mid), start+1);
You should rather send
left += list.get(0) + summer(list.subList(1, mid), 0);
and
right += list.get(mid) + summer(list.subList(mid+1, list.size()), 0);
I dont see the need to sending any start value. Every recursion should take the 0 in place of start.
I think it can be solved in a simpler way, by keeping track of both the first and last index of the range, like this:
public static int sum(List<Integer> list, int i, int j) {
if (i == j)
return list.get(i);
int half = (i + j) / 2;
return sum(list, i, half) + sum(list, half + 1, j);
}
It's called like this:
List<Integer> list = Arrays.asList(1, 2, 3);
System.out.println(sum(list, 0, list.size()-1));
It will work fine for non-empty lists. If the list is empty, you'll need to check it before calling sum.
First of all, you don't need to cut the list in half if all you need to do is use recursion. The sum of the elements of a list is the sum of its first element + the sum of all the elements of the rest of the list.
Second, your method is too complex. The sum of the elements of the list is 0 if the list is empty, the unique element is it contains 1 element, and the sum of the results of the method applied to the two sublists if it contains more than 1. You don't need any start argument.
This should get you started.
EDIT: since Oscar Lopez gave you the answer, but I find it too complex, here's mine:
public static int sum(List<Integer> list) {
if (list.isEmpty()) {
return 0;
}
else if (list.size() == 1) {
return list.get(0);
}
else {
int half = list.size() / 2;
return sum(list.subList(0, half)) + sum(list.subList(half, list.size()));
}
}
I am wondering a reason of getting a "half" of the List.The solution for the question is the one and only:
public int sum_list(List<Integer> list) {
if (list == null || list.isEmpty()) {
return 0;
}
return list.remove(0) + sum_list(list);
}
import java.util.*;
public class SumListByRecursion {
public static int sumByRec(List<Integer> list) {
int size = list.size();
if(size > 0) {
return list.get(0) + sumByRec(list.subList(1, size));
}
return 0;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
System.out.println("List:"+" "+list);
int sum = sumByRec(list);
System.out.println("Sum of the list:"+" "+sum);
}
}
You can use this method for sum all ement of given list.
public static Integer sumOfList(List<Integer> list){
try {
return list.get(0) + sumOfList(list.subList(1, list.size()));
}catch (Exception e) {
return 0;
}
}