Is there an alternative way to get the max element in a Queue (Java)?
(Please provide alternative approaches )
import java.util.*;
public class MaxQueueElement<E extends Comparable<E>> {
public MaxQueueElement(Queue<E> queue){
E max= queue.peek(); // initialize max with head of queue
for(E e : queue){
if(e.compareTo(max) > 0){
max = e;
}
}
System.out.println(max);
}
}
The get-max operation on a queue can be implemented in amortized O(1) time by maintaining the candidates for the max value in a separate double-ended queue (Deque).
On enqueue (or offer) operation, we check whether there are any elements at the back of the Deque which are lesser in value than the element being enqueued. These values can simply be removed – for these can never be the maximum value going forward.
On dequeue (or poll) operation, we check whether the first element in the Deque is equal to the first element in the regular queue and if yes, remove it too.
The max element is simply the first element of the Deque.
All operations have amortized O(1) time complexity.
Here's an implementation in Java:
public class QueueWithMax<T extends Comparable<T>> {
Queue<T> queue;
Deque<T> cMax; // candidates for Max value
public QueueWithMax() {
queue = new LinkedList<>();
cMax = new LinkedList<>();
}
public void offer(T element) {
queue.offer(element);
while (!cMax.isEmpty() && element.compareTo(cMax.peekLast()) > 0) {
cMax.pollLast();
}
cMax.offerLast(element);
}
public T poll() {
if (cMax.peekFirst().equals(queue.peek()))
cMax.pollFirst();
return queue.poll();
}
public T getMax() {
return cMax.peekFirst();
}
}
The only way to access all elements in a Queue is to use the iterator() method - you can't (generally) access the elements by index (as in, some implementations might, but Queue doesn't inherently).
As such, all you can do is to iterate the elements one at a time, storing the current maximum element. This is exactly what you're doing here.
There is nothing wrong with your algorithm - but the way you've implemented it could be improved:
Don't do this in the constructor of a class - you don't need to construct a new instance of anything, as the maximum value already exists. Do it in a (static) method.
Don't print out the result - that's of no use to man or beast. Return it to the caller.
Handle the cases where the queue is empty and may contain nulls. (Look at the Javadoc of Collections.max for ideas)
I'm taking a computer science class, and we aren't allowed to use the for each loop. I'm not sure if it's the same with you. Note that the for each loop kind of defeats the purpose of a Queue since you want to only be handling the front and end of a queue. In my class specifically, we also want to have the queue be at it's original state before it was passed into the method without using an extra auxiliary data structure. Here's how I would go about it on a test:
public E findMaxQueueElement(Queue<e> queue) { //my test would ask me to return the max value
E max = queue.remove();
queue.add(max); //add it back to the end
for(int i=0; i<queue.size()-1; i++) {
E current = queue.remove();
if (current.compareTo(max) > 0) {
max = current;
}
queue.add(current);
}
return max;
}
With the limitations I provided, this should work. I hope this helps.
You can use Java 8's stream to sort the Queue, it internally uses the same algorithm but will result in less noisy code, e.g.:
public void MaxQueueElement(Queue<E> queue){
Optional<E> max = queue.stream()
.max(Comparable::compareTo);
if(max.isPresent()){
System.out.println(max.get());
}
}
Another approach would be to use PriorityQueue with comparator and get the first element from it. e.g.:
public void MaxQueueElement2(Queue<E> queue){
PriorityQueue<E> pQueue = new PriorityQueue<>((E e1, E e2)->e1.compareTo(e2));
pQueue.addAll(queue);
System.out.println(pQueue.peek());
}
Unless the queue is not some special sorted queue like PriorityQueue, from the algorithmic point of view there is no better way. Since the queue does not have any intrinsic sorting properties, you have to check all the elements of the queue before you find one.
The code is more or less OK. It will fail if the queue contains null. This is normally not the case, but may happen.
The MaxQueueElement construct is somewhat strange.
I think you can also make use of
Collections.max(queue) in case of queue
Related
Every 5 minutes, within the 20th minute cycle, I need to retrieve the data. Currently, I'm using the map data structure.
Is there a better data structure? Every time I read and set the data, I have to write to the file to prevent program restart and data loss.
For example, if the initial data in the map is:
{-1:"result1",-2:"result2",-3:"result3",-4:"result4"}
I want to get the last -4 period's value which is "result4", and set the new value "result5", so that the updated map will be:
{-1:"result5",-2:"result1",-3:"result2",-4:"result3"}
And again, I want to get the last -4 period's value which is "result3", and set the new value "result6", so the map will be:
{-1:"result6",-2:"result5",-3:"result1",-4:"result2"}
The code:
private static String getAndSaveValue(int a) {
//read the map from file
HashMap<Long,String> resultMap=getMapFromFile();
String value=resultMap.get(-4L);
for (Long i = 4L; i >= 2; i--){
resultMap.put(Long.parseLong(String.valueOf(i - 2 * i)),resultMap.get(1 - i));
}
resultMap.put(-1L,"result" + a);
//save the map to file
saveMapToFile(resultMap);
return value;
}
Based on your requirement, I think LinkedList data structure will be suitable for your requirement:
public class Test {
public static void main(String[] args) {
LinkedList<String> ls=new LinkedList<String>();
ls.push("result4");
ls.push("result3");
ls.push("result2");
ls.push("result1");
System.out.println(ls);
ls.push("result5"); //pushing new value
System.out.println("Last value:"+ls.pollLast()); //this will return `result4`
System.out.println(ls);
ls.push("result6"); //pushing new value
System.out.println("Last value:"+ls.pollLast()); // this will give you `result3`
System.out.println(ls);
}
}
Output:
[result1, result2, result3, result4]
Last value:result4
[result5, result1, result2, result3]
Last value:result3
[result6, result5, result1, result2]
Judging by your example, you need a FIFO data structure which has a bounded size.
There's no bounded general purpose implementation of the Queue interface in the JDK. Only concurrent implementation could be bounded in size. But if you're not going to use it in a multithreaded environment, it's not the best choice because thread safety doesn't come for free - concurrent collections are slower, and also can create confusing for the reader of your code.
To achieve your goal, I suggest you to use the composition by wrapping ArrayDeque, which is an array-based implementation of the Queue and performs way better than LinkedList.
Note that is a preferred approach not to extend ArrayDeque (IS A relationship) and override its methods add() and offer(), but include it in a class as a field (HAS A relationship), so that all the method calls on the instance of your class will be forwarded to the underlying collection. You can find more information regarding this approach in the item "Favor composition over inheritance" of Effective Java by Joshua Bloch.
public class BoundQueue<T> {
private Queue<T> queue;
private int limit;
public BoundQueue(int limit) {
this.queue = new ArrayDeque<>(limit);
this.limit = limit;
}
public void offer(T item) {
if (queue.size() == limit) {
queue.poll(); // or throw new IllegalStateException() depending on your needs
}
queue.add(item);
}
public T poll() {
return queue.poll();
}
public boolean isEmpty() {
return queue.isEmpty();
}
}
I am learning programming and new to this domain as i am have a mechanical background.
Yesterday I received a problem statement from prof. where he provided us an custom Iterator which is designed to iterate over given elements alternatively.
Alternate Iterator code is as following.
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class AlternatingIterator<E> implements Iterator{
private final Queue<E> queue = new LinkedList<>();
public AlternatingIterator(Iterator<E> ... iterators) {
for(Iterator<E> iterator : iterators) {
while(iterator.hasNext())
queue.add(iterator.next());
}
}
#Override
public boolean hasNext() {
return queue.isEmpty() ? false : true;
}
#Override
public Object next() {
return queue.poll();
}
}
Now, The AlternatingIterator should alternate in order between the iterators it receives in its constructor. For example if constructed with three iterators [a,b,c], [1,2] and [x,y,z], the iterator should produce the elements in this order ‘a, 1, x, b, 2, y, c, z’
Also i have to Write unit tests for the ‘hasNext’ and ‘next’ methods.
Can we implement any other data structure than queue?
I am completely blown off and tired to understand how to solve this challenge but very confused here. If you guys can help me then i can learn important concept very quickly.
Thank you in advance and any help is appreciated.
Of course, we can use anything we can imagine. The following implementation alternates dynamically. Instead of using a queue, I store all the received iterators in an array:
import java.util.Iterator;
/**Alternates on the given iterators.*/
public class AlternatingIterator<E> implements Iterator {
/**Stores the iterators which are to be alternated on.*/
private Iterator<E>[] iterators;
/**The index of iterator, which has the next element.*/
private int nextIterator = 0;
/**Initializes a new AlternatingIterator object.
* Stores the iterators in the iterators field.
* Finds the first iterator with an available element.*/
public AlternatingIterator(Iterator<E> ... iterators) {
this.iterators = iterators;
if (!iterators[0].hasNext())
findNextIterator();
}
#Override
public boolean hasNext() {
return iterators[nextIterator].hasNext();
}
#Override
public Object next() {
E element = iterators[nextIterator].next();
findNextIterator();
return element;
}
/**Steps on iterators, until one has next element.
* It does not step on them infinitely, stops when
* the lastly used iterator is reached.*/
private void findNextIterator() {
int currentIterator = nextIterator;
// Finding iterator with element remaining.
do {
stepNextIterator();
} while (!iterators[nextIterator].hasNext() && nextIterator != currentIterator);
// If it gets around to the same iterator, then there is no iterator with element.
}
/**Increases the nextIterator value without indexing out of bounds.*/
private void stepNextIterator() {
nextIterator = (nextIterator + 1) % iterators.length;
}
}
But the same could be made statically using a queue, enqueuing all the elements from the iterators, having only that one queue as in your (your prof's) code.
#Andy Turner: Collecting the elements from the iterator results in not relying on the source collection the entire time until the last element is not obtained. Sure, from Java8 we use Streams, which won't gift us concurrent exceptions, but before Java8, buffering an/more iterator into a collection could have been safer in my opinion.
EDIT: you wrote then we can use the iterator of that given collection. Yeah, I totally forgot that, implementing an iterator for a simple queue is for sure pointless :)
A queue is helpful here, but not in the way you are using it.
There is no real point in copying all the elements from the iterators provided to the constructor into a queue, and then implementing a custom iterator from this queue: if you are going to put the elements into a collection which already implements Iterable, you may as well just use that Iterable's iterator.
But this is also probably not the point of the exercise: you can do this lazily with respect to consuming the input iterators. (Besides, what if one of the iterators is infinite...)
The idea I would suggest is to make a queue of iterators, not elements. Here is a description of how you could do it; I don't want to give you code to spoil your learning experience:
In your constructor, put the iterators from the parameter into a queue.
To implement hasNext(), pop iterators off the head of the queue for which hasNext() is false; stop when the iterator at the head of the queue has a next element (in which case return true), or the queue is empty (in which case return false).
To implement next(), pop the head iterator out of the queue, and get its next element: this is what you will return. But, before you do, if the iterator has more elements, push it onto the tail of the queue (doing this means that you will look at the next iterator on the next iteration).
I was just having a simple implementation query.
So I make a BST by using the following code:
class Node{
int data;
Node left=null;
Node right=null;
Node link=null;
public Node(int d)
{
data=d;
}
public void append(int d)
{
Node n=this;
Node nval=new Node(d);
if(n==null)
{
n.data=d;
}
else
{ boolean done=false;
while(!done)
{
if(n.data<=d)
{
if(n.left==null)
{
n.left=nval;
done=true;
System.out.println("Data Entered "+nval.data);
}
else
{
n=n.left;
}
}
else
if(n.data>d)
{
if(n.right==null)
{
n.right=nval;
done=true;
System.out.println("Data Entered "+nval.data);
}
else
{
n=n.right;
}
}
}
}
}
}
Now, I started applying Breadth first and Depth First search on it. I was having genuine issues with doing this.
For DFS, I have to add in the left and right values of the current node that is placed on a stack right? How would I program this? I was having problems with doing this using a Linked List? Can someone tell me how the data structure or pointers should be?
The same thing happens with BFS. In case I wasn't clear before, my main problem is removing an array element and then replacing it with its children.
A Queue (FIFO) generally works well for a BFS. It need not be a Priority Queue, but it often is because giving weights is very common:
Queues typically, but do not necessarily, order elements in a FIFO (first-in-first-out) manner. Among the exceptions are priority queues, which order elements according to a supplied comparator, or the elements' natural ordering, and LIFO queues (or stacks) which order the elements LIFO (last-in-first-out). Whatever the ordering used, the head of the queue is that element which would be removed by a call to remove() or poll(). In a FIFO queue, all new elements are inserted at the tail of the queue. Other kinds of queues may use different placement rules. Every Queue implementation must specify its ordering properties.
Basic "algorithm" rules for BFS with a Queue:
Put initial state(s) in Q (the Queue)
Take the head of the Q (see remove)
Do something with the value taken (e.g. parent -> [child1, child2 ..])
Append any results from step #3 to the tail of the Q (see add)
Go back to step #2 until Q is empty or other end-case is achieved
Arrays are just a PITA to deal with past initialization and iteration. "Slicing" and "resizing" tends to be particularly painful in Java.
for DFS(FILO), u just need to use a stack
for each node, push his right child to the stack first, then push the left child
for BFS(FIFO), u should use queue as #pst mentioned
I was wondering whats the best way to write a method to merge an ArrayQueue with another Queue without removing any elements from the q thats passed.
eg. queue1 = [1,2,3,4] and queue2 = [5,6,7,8,9,10].
When queue1.mergeQs(queue2) was called it would create queue1 = [1,5,2,6,3,7,4,8,9,10] whilst queue2 would remain [5,6,7,8,9,10]
public void mergeQs(ArrayQmerge q){}
This way seems harder to implement than if you were to pass both Queues and return a new merged Queue. Thanks.
Just to clarify, i'm looking for a method to interleave the elements from the two queues.
One detail that might help you is that private fields are visible between different object of the same class in Java. That means that as long as you only intend to merge queues of your own class, your code has full access to all internal fields, such as the array you use to store your elements.
For the simplest case, where all elements are stored in a linear array with the queue head being at index zero, something like this might be a start:
public void mergeQs(ArrayQmerge q) {
Object[] array = new Object[this.size() + q.size()];
int i;
int o;
// Interleave elements
for (i = 0, o = 0; i < this.size() && i < q.size(); ++i) {
array[o++] = this.array[i];
array[o++] = q.array[i];
}
// Copy the remaining elements
while (i < this.size()) {
array[o++] = this.array[i++];
}
while (i < q.size()) {
array[o++] = q.array[i++];
}
this.array = array;
}
You can create a new Queue locally in the merge method, then assign your class's queue to the local version.
Since you are using your own homebrew ArrayQueue then this is conjecture.
Creating a new queue and returning is as I think you already say is way easier, and more efficient, as inserting elements into an Array backed structure will involve shuffling the rest of the elements down one position for each insert op.
An alternative is to implement public void mergeQs(ArrayQmerge q) by swapping out the underlying array you have backing it. So you get the same easy implementation as returning a new Queue but with the same in place side effect.
I have the following scenario: I have an existing iterator Iterator<String> it and I iterate over its head (say first k elements, which are flagged elements, i.e. they start with '*' ). The only way to know that the flagged elements are over, is by noticing that the (k+1)th element is not flagged.
The problem is that if I do that, the iterator it will not provide me the first value anymore on the next call to next().
I want to pass this iterator to a method as it's only argument and I would like to avoid changing its signarture and it implementation. I know I could do this:
public void methodAcceptingIterator(Iterator<String> it) //current signature
//change it to
public void methodAcceptingIterator(String firstElement, Iterator<String> it)
But this looks like a workarround/hack decreasing the elegance and generality of the code, so I don't want to this.
Any ideas how I could solve this problem ?
You could use Guava's PeekingIterator (link contains the javadoc for a static method which, given an Iterator, will return a wrapping PeekingIterator). That includes a method T peek() which shows you the next element without advancing to it.
The solution is to create your own Iterator implementation which stores the firstElement and uses the existing iterator as an underlying Iterator to delegate the requests for the rest of the elements to.
Something like:
public class IteratorMissingFirst<E> implements Iterator<E>{
private Iterator<E> underlyingIterator;
private E firstElement;
private boolean firstElOffered;
public IteratorMissingFirst(E firstElement, Iterator<E> it){
//initialize all the instance vars
}
public boolean hasNext(){
if(!firstElOffered && firstElement != null){
return true;
}
else{
return underlyingIterator.hasNext();
}
}
public E next(){
if(!firstElOffered){
firstElOffered = true;
return firstElement;
}
else return underlyingIterator.next();
}
public void remove(){
}
}
Why don't you just have methodAcceptingIterator store the first element it gets out of the iterator in a variable? Or -- in a pinch -- just copy the contents of the Iterator into an ArrayList at the beginning of your method; now you can revisit elements as often as you like.
With Guava, you can implement Razvan's solution in an easier way by using some methods from the Iterables class:
Iterators.concat(Iterators.singletonIterator(firstElement), it)
This gives you an iterator working similar to IteratorMissingFirst, and it's easy to extend if you need to look at more than one element in front (but it creates two objects instead of only one).