I was practicing on how to implement queue using arrays. I have easily implemented how to enqueue and dequeue the elements in queue. But I have encountered an exception while implementing reverse of queue using stacks
public class QueueImpl {
private int capacity;
int queueArr[];
int front = 0;
int rear = -1;
int currentSize = 0;
QueueImpl(int queueSize){
this.capacity=queueSize;
queueArr=new int[this.capacity];
}
public void enqueue(int data){
if(isQueueFull()){
System.out.println("Overflow");
return;
}
else{
rear=rear+1;
if(rear==capacity-1)
{
rear=0;
}
queueArr[rear]=data;
currentSize++;
System.out.println("Element " + data+ " is pushed to Queue !");
}
}
public int dequeue(){
if(isQueueEmpty()){
System.out.println("UnderFlow");
}
else{
front=front+1;
if(front == capacity-1){
System.out.println("Pop operation done ! removed: "+queueArr[front-1]);
front = 0;
} else {
System.out.println("Pop operation done ! removed: "+queueArr[front-1]);
}
currentSize--;
}
return queueArr[front-1];
}
private boolean isQueueEmpty() {
boolean status=false;
if(currentSize==0){
status=true;
}
return status;
}
private boolean isQueueFull() {
boolean status=false;
if(currentSize==capacity){
status=true;
}
return status;
}
public static void main(String arg[]) {
QueueImpl queueImpl=new QueueImpl(5);
queueImpl.enqueue(5);
queueImpl.enqueue(2);
queueImpl.enqueue(9);
queueImpl.enqueue(1);
// queueImpl.dequeue();
queueImpl.printQueue(queueImpl);
queueImpl.reverse(queueImpl);
}
private void printQueue(QueueImpl queueImpl) {
System.out.println(queueImpl.toString());
}
#Override
public String toString() {
return "Queue [front=" + front + ", rear=" + rear + ", size=" + currentSize
+ ", queue=" + Arrays.toString(queueArr) + "]";
}
private QueueImpl reverse(QueueImpl queueImpl) throws ArrayIndexOutOfBoundsException {
int i=0;
Stack<Integer> stack=new Stack<Integer>();
while(!queueImpl.isQueueEmpty()){
stack.push(queueImpl.dequeue());
}
while(!stack.isEmpty()){
stack.get(i);
i++;
}
while(!stack.isEmpty()){
queueImpl.enqueue(stack.pop());
}
return queueImpl;
}
}
The error log is -
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at com.tcs.QueueUsingAraay.QueueImpl.dequeue(QueueImpl.java:51)
at com.tcs.QueueUsingAraay.QueueImpl.reverse(QueueImpl.java:93)
at com.tcs.QueueUsingAraay.QueueImpl.main(QueueImpl.java:78)
There was a problem in your dequeue method:
1. you were making front=0 and were trying to access front-1 which was -1
as a result the exception was thrown.
Removed stack.get as it was not required.
Corrected working code.
public class QueueImpl {
private int capacity;
int queueArr[];
int front = 0;
int rear = -1;
int currentSize = 0;
QueueImpl(int queueSize) {
this.capacity = queueSize;
queueArr = new int[this.capacity];
}
public void enqueue(int data) {
if (isQueueFull()) {
System.out.println("Overflow");
return;
} else {
rear = rear + 1;
if (rear == capacity - 1) {
rear = 0;
}
queueArr[rear] = data;
currentSize++;
System.out.println("Element " + data + " is pushed to Queue !");
}
}
public int dequeue() {
int element=-1;
if (isQueueEmpty()) {
System.out.println("UnderFlow");
} else {
element = queueArr[front];
front=front+1;
if (front == capacity - 1) {
System.out.println("Pop operation done ! removed: "
+ queueArr[front - 1]);
front = 0;
} else {
System.out.println("Pop operation done ! removed: "
+ queueArr[front - 1]);
}
currentSize--;
}
return element;
}
private boolean isQueueEmpty() {
boolean status = false;
if (currentSize == 0) {
status = true;
}
return status;
}
private boolean isQueueFull() {
boolean status = false;
if (currentSize == capacity) {
status = true;
}
return status;
}
public static void main(String arg[]) {
QueueImpl queueImpl = new QueueImpl(5);
queueImpl.enqueue(5);
queueImpl.enqueue(2);
queueImpl.enqueue(9);
queueImpl.enqueue(1);
queueImpl.printQueue(queueImpl);
queueImpl.reverse(queueImpl);
queueImpl.printQueue(queueImpl);
}
private void printQueue(QueueImpl queueImpl) {
System.out.println(queueImpl.toString());
}
#Override
public String toString() {
return "Queue [front=" + front + ", rear=" + rear + ", size="
+ currentSize + ", queue=" + Arrays.toString(queueArr) + "]";
}
private QueueImpl reverse(QueueImpl queueImpl)
throws ArrayIndexOutOfBoundsException {
Stack<Integer> stack = new Stack<Integer>();
while (!queueImpl.isQueueEmpty()) {
stack.push(queueImpl.dequeue());
}
while (!stack.isEmpty()) {
queueImpl.enqueue(stack.pop());
}
return queueImpl;
}
}
Related
Given two strings s and t, determine length of shortest string z such that z is a subsequence of s and not a subsequence of t.
example :
s :babab,
t :babba
sol :
3 (aab)
not looking for copy pastable code, please if anybody can help with intution for solving this.
thanks a lot !
Here you go. I created on IEnumarable method which gives back all possible combinations. This is compared with t. I optimized the solution to loop only once over the not match String t.
using System;
using System.Collections.Generic;
namespace GuessTheNumber
{
public class Element:IComparable<Element>
{
public string Seq { get; set; }
public int Id { get; set; }
public int CompareTo(Element other)
{
return this.Seq.CompareTo(other.Seq);
}
}
class Program
{
static void Main(string[] args)
{
string s = "babab";
string t = "babba";
string z = ShortestUncommonSuqsequence(s, t);
}
static public string ShortestUncommonSuqsequence(string SubSequenceOf, string NotSubSequenceOf)
{
var uniqueSeq = new SortedList<Element, int>();
uniqueSeq.Add(new Element() { Seq = "", Id = -1 }, -1);
foreach (Element oneSequence in GetNextUniqueSequences(uniqueSeq, SubSequenceOf))
{
int index = oneSequence.Id + 1;
while (index < NotSubSequenceOf.Length)
{
char NotChar = NotSubSequenceOf[index];
if (oneSequence.Seq[oneSequence.Seq.Length - 1] == NotChar) break;
index++;
}
if (index == NotSubSequenceOf.Length)
{
return oneSequence.Seq;
}
else
{
oneSequence.Id = index;
}
}
return null;
}
static public IEnumerable<Element> GetNextUniqueSequences(SortedList<Element, int> UniqueSeq, string Input)
{
SortedList<Element, int> results = new SortedList<Element, int>();
foreach (var prevResult in UniqueSeq)
{
for (int i = 0; i < Input.Length; i++)
{
if (prevResult.Value < prevResult.Key.Seq.Length + i)
{
string nextStr = prevResult.Key.Seq + Input[i].ToString();
Element newElem = new Element() { Seq = nextStr, Id = prevResult.Key.Id };
if (!results.Keys.Contains(newElem))
{
results.Add(newElem, prevResult.Key.Seq.Length + i);
yield return newElem;
}
}
}
}
if (Input.Length > 1)
{
foreach (Element res in GetNextUniqueSequences(results, Input.Substring(1)))
{
yield return res;
}
}
}
}
}
Suggest an efficient way to find last position in heap satisfying the following conditions:
1) via pointers not via array
2) where we can insert or delete node
I could find it in O(n) time complexity but suggest a way which is of O(logn) or O(1) time complexity.
I'm assuming here that you mean a binary heap.
If you know how many nodes are in the heap, you can find the last node in O(log n) time by converting the count to binary, and then following the path of bits from high to low. That is, take the left node if the bit is 0, and the right node if the bit is 1.
For example, if there are three nodes in the heap, the binary representation of the count is 11. The root is always the first node, leaving you with 1. Then you take the right branch to get the last node.
Say there are 5 nodes in the heap:
1
2 3
4 5
In binary, that's 101. So you take the root. The next digit is 0 so you take the left branch. The next digit is 1, so you take the right branch, leaving you at node 5.
If you want the next available slot, you add 1 to the count and do the same thing. So 6 would be 110. You take the root, then the right branch, and the left child of 3 is where you'd add the new node.
You can do the same kind of thing with any d-ary heap, except that instead of converting to binary you convert to base d. So if your heap nodes each have up to three children, you'd convert the count to base 3, and use essentially the same logic as above.
An alternative is to maintain a reference to the last node in the heap, updating it every time you modify the heap. Or, if you want to know where the next node would be placed, you maintain a reference to the first node that doesn't have two children. That's O(1), but requires bookkeeping on every insertion or deletion.
I am answering my own question, There is no need to keep track of next pointer while inserting in heap (heap via pointers), even there is no need to keep track of parent, i am attaching running java code for heap, all possible method are included in it, getMin() = O(1), insert() = O(logn), extractMin = O(logn), decreasePriorityOfHead = O(logn), I have implemented it for generic code so it would be helpful to understand generic concept also.
class MinHeap<E extends Comparable<E>> {
private DoublyNode<E> root;
private int size = 0;
public DoublyNode<E> getRoot() {
return root;
}
public void setRoot(DoublyNode<E> root) {
this.root = root;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public MinHeap() {
}
public MinHeap(E data) {
this.root = new DoublyNode<E>(data);
this.size++;
}
private class NodeLevel<E extends Comparable<E>> {
private int level;
private DoublyNode<E> node;
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public DoublyNode<E> getNode() {
return node;
}
public void setNode(DoublyNode<E> node) {
this.node = node;
}
public NodeLevel(DoublyNode<E> node, int level) {
this.node = node;
this.level = level;
}
}
public void insert(E data) {
if (this.size == 0) {
this.root = new DoublyNode<E>(data);
this.size++;
return;
}
DoublyNode<E> tempRoot = this.root;
Integer insertingElementPosition = this.size + 1;
char[] insertingElementArray = Integer.toBinaryString(
insertingElementPosition).toCharArray();
DoublyNode<E> newNode = new DoublyNode<E>(data);
int i;
for (i = 1; i < insertingElementArray.length - 1; i++) {
if (newNode.getData().compareTo(tempRoot.getData()) < 0) {
this.swap(newNode, tempRoot);
}
char c = insertingElementArray[i];
if (c == '0') {
tempRoot = tempRoot.getLeft();
} else {
tempRoot = tempRoot.getRight();
}
}
// newNode.setParent(tempRoot);
if (newNode.getData().compareTo(tempRoot.getData()) < 0) {
this.swap(newNode, tempRoot);
}
if (insertingElementArray[i] == '0') {
tempRoot.setLeft(newNode);
} else {
tempRoot.setRight(newNode);
}
this.size++;
}
public void swap(DoublyNode<E> node1, DoublyNode<E> node2) {
E temp = node1.getData();
node1.setData(node2.getData());
node2.setData(temp);
}
public E getMin() {
if (this.size == 0) {
return null;
}
return this.root.getData();
}
public void heapifyDownWord(DoublyNode<E> temp) {
if (temp == null) {
return;
}
DoublyNode<E> smallerChild = this.getSmallerChild(temp);
if (smallerChild == null) {
return;
}
if (smallerChild.getData().compareTo(temp.getData()) < 0) {
this.swap(temp, smallerChild);
this.heapifyDownWord(smallerChild);
}
}
public DoublyNode<E> getSmallerChild(DoublyNode<E> temp) {
if (temp.getLeft() != null && temp.getRight() != null) {
return (temp.getLeft().getData()
.compareTo(temp.getRight().getData()) < 0) ? temp.getLeft()
: temp.getRight();
} else if (temp.getLeft() != null) {
return temp.getLeft();
} else {
return temp.getRight();
}
}
public E extractMin() {
if (this.root == null) {
return null;
}
E temp = this.root.getData();
if (this.root.getLeft() == null && this.root.getRight() == null) {
this.root = null;
this.size--;
return temp;
}
DoublyNode<E> parentOfLastData = this.getParentOfLastData();
if (parentOfLastData.getRight() != null) {
this.root.setData(parentOfLastData.getRight().getData());
parentOfLastData.setRight(null);
} else {
this.root.setData(parentOfLastData.getLeft().getData());
parentOfLastData.setLeft(null);
}
this.heapifyDownWord(this.root);
return temp;
}
public DoublyNode<E> getParentOfLastData() {
if (this.size == 0) {
return null;
}
DoublyNode<E> tempRoot = this.root;
Integer insertingElementPosition = this.size;
char[] insertingElementArray = Integer.toBinaryString(
insertingElementPosition).toCharArray();
int i;
for (i = 1; i < insertingElementArray.length - 1; i++) {
char c = insertingElementArray[i];
if (c == '0') {
tempRoot = tempRoot.getLeft();
} else {
tempRoot = tempRoot.getRight();
}
}
return tempRoot;
}
public DoublyNode<E> getParentOfLastEmptyPosition() {
if (this.size == 0) {
return null;
}
DoublyNode<E> tempRoot = this.root;
Integer insertingElementPosition = this.size + 1;
char[] insertingElementArray = Integer.toBinaryString(
insertingElementPosition).toCharArray();
System.out.println(insertingElementArray.toString());
int i;
for (i = 1; i < insertingElementArray.length - 1; i++) {
char c = insertingElementArray[i];
if (c == '0') {
tempRoot = tempRoot.getLeft();
} else {
tempRoot = tempRoot.getRight();
}
}
return tempRoot;
}
public void print() {
if (this.root == null) {
System.out.println("Heap via pointer is empty!");
return;
}
System.out.println("\n Heap via pointer is:- ");
Queue<NodeLevel<E>> dataQueue = new Queue<NodeLevel<E>>();
Queue<Space> spaceQueue = new Queue<Space>();
dataQueue.enQueue(new NodeLevel<E>(this.root, 1));
int heightOfTree = this.getHeightOfHeap();
Double powerHeghtBST = Math.pow(heightOfTree, 2);
spaceQueue.enQueue(new Space(powerHeghtBST.intValue(), false));
while (!dataQueue.isEmpty()) {
Space space = spaceQueue.deQueue();
NodeLevel<E> nodeLevel = dataQueue.deQueue();
while (space.isNullSpace()) {
space.printNullSpace();
spaceQueue.enQueue(space);
space = spaceQueue.deQueue();
}
space.printFrontSpace();
System.out.print(nodeLevel.getNode().getData().printingData());
space.printBackSpace();
if (nodeLevel.getNode().getLeft() != null) {
dataQueue.enQueue(new NodeLevel<E>(nodeLevel.getNode()
.getLeft(), nodeLevel.getLevel() + 1));
spaceQueue.enQueue(new Space(space.getSpaceSize() / 2, false));
} else {
spaceQueue.enQueue(new Space(space.getSpaceSize() / 2, true));
}
if (nodeLevel.getNode().getRight() != null) {
dataQueue.enQueue(new NodeLevel<E>(nodeLevel.getNode()
.getRight(), nodeLevel.getLevel() + 1));
spaceQueue.enQueue(new Space(space.getSpaceSize() / 2, false));
} else {
spaceQueue.enQueue(new Space(space.getSpaceSize() / 2, true));
}
if (!dataQueue.isEmpty()
&& nodeLevel.getLevel() + 1 == dataQueue.getFrontData()
.getLevel()) {
System.out.println("\n");
}
}
}
public int getHeightOfHeap() {
if (this.size == 0) {
return 0;
}
Double height = Math.log(this.size) / Math.log(2) + 1;
return height.intValue();
}
public void changePriorityOfHeapTop(E data) {
if (this.root == null) {
return;
}
this.root.setData(data);
this.heapifyDownWord(this.root);
}
}
interface Comparable<T> extends java.lang.Comparable<T> {
/**
* this methos returns a string of that data which to be shown during
* printing tree
*
* #return
*/
public String printingData();
}
public class PracticeMainClass {
public static void main(String[] args) {
MinHeap<Student> minHeap1 = new MinHeap<Student>();
minHeap1.insert(new Student(50, "a"));
minHeap1.insert(new Student(20, "a"));
minHeap1.insert(new Student(60, "a"));
minHeap1.insert(new Student(30, "a"));
minHeap1.insert(new Student(40, "a"));
minHeap1.insert(new Student(70, "a"));
minHeap1.insert(new Student(10, "a"));
minHeap1.insert(new Student(55, "a"));
minHeap1.insert(new Student(35, "a"));
minHeap1.insert(new Student(45, "a"));
minHeap1.print();
minHeap1.getMin();
minHeap1.print();
System.out
.println("\nminimum is:- " + minHeap1.getMin().printingData());
minHeap1.print();
System.out.println("\nminimum is:- "
+ minHeap1.extractMin().printingData());
minHeap1.print();
minHeap1.changePriorityOfHeapTop(new Student(75, "a"));
minHeap1.print();
}
}
class DoublyNode<E extends Comparable<E>> {
private E data;
private DoublyNode<E> left;
private DoublyNode<E> right;
// private DoublyNode<E> parent;
public DoublyNode() {
}
public DoublyNode(E data) {
this.data = data;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public DoublyNode<E> getLeft() {
return left;
}
public void setLeft(DoublyNode<E> left) {
this.left = left;
}
public DoublyNode<E> getRight() {
return right;
}
public void setRight(DoublyNode<E> right) {
this.right = right;
}
// public DoublyNode<E> getParent() {
// return parent;
// }
// public void setParent(DoublyNode<E> parent) {
// this.parent = parent;
// }
}
class Space {
private boolean isNullSpace = false;
private String frontSpace;
private String backSpace;
private String nullSpace;
private int spaceSize;
public boolean isNullSpace() {
return isNullSpace;
}
public void setNullSpace(boolean isNullSpace) {
this.isNullSpace = isNullSpace;
}
public int getSpaceSize() {
return spaceSize;
}
public void setSpaceSize(int spaceSize) {
this.spaceSize = spaceSize;
}
public Space(int spaceSize, boolean isNullSpace) {
this.isNullSpace = isNullSpace;
this.spaceSize = spaceSize;
if (spaceSize == 0) {
this.frontSpace = "";
this.backSpace = "";
this.nullSpace = " ";
} else if (spaceSize == 1) {
this.frontSpace = " ";
this.backSpace = "";
this.nullSpace = " ";
} else if (spaceSize == 2) {
this.frontSpace = " ";
this.backSpace = "";
this.nullSpace = " ";
} else {
this.frontSpace = String.format("%" + (spaceSize) + "s", " ");
this.backSpace = String.format("%" + (spaceSize - 2) + "s", " ");
this.nullSpace = String.format("%" + 2 * (spaceSize) + "s", " ");
}
}
public void printFrontSpace() {
System.out.print(this.frontSpace);
}
public void printBackSpace() {
System.out.print(this.backSpace);
}
public void printNullSpace() {
System.out.print(this.nullSpace);
}
}
class Queue<E> {
private Node<E> front;
private Node<E> rear;
private int queueSize = 0;
public Queue() {
}
public Queue(E data) {
this.front = new Node(data);
this.rear = this.front;
}
public void enQueue(E data) {
if (this.rear == null) {
this.rear = new Node(data);
this.front = this.rear;
} else {
Node newNode = new Node(data);
this.rear.setNext(newNode);
this.rear = newNode;
}
this.queueSize++;
}
public E deQueue() {
E returnValue;
if (this.front == null) {
return null;
} else if (this.front == this.rear) {
returnValue = this.front.getData();
this.front = null;
this.rear = null;
} else {
returnValue = this.front.getData();
this.front = this.front.getNext();
}
this.queueSize--;
return returnValue;
}
public void print() {
Node temp = this.front;
System.out.print("\n Queue is:- ");
if (temp == null) {
System.out.println(" Empty! ");
}
while (temp != null) {
System.out.print(temp.getData() + ",");
temp = temp.getNext();
}
}
public int getQueueSize() {
return queueSize;
}
public E getFrontData() {
if (this.front == null) {
System.out.println("queue is empty!");
return null;
}
return this.front.getData();
}
public E getRearData() {
if (this.rear == null) {
System.out.println("queue is empty!");
return null;
}
return this.rear.getData();
}
public boolean isEmpty() {
return this.front == null;
}
}
class Node<E> {
private E data;
private Node next;
public Node(E data) {
this.data = data;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
}
class Student implements Comparable<Student> {
private int id;
private String name;
#Override
public int compareTo(Student student) {
if (this.id == student.id) {
return 0;
} else if (this.id < student.id) {
return -1;
} else {
return 1;
}
}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String printingData() {
// String printingData = "{ id: "+this.id+" name: "+this.name+" }";
String printingData = String.valueOf(this.id);
return printingData;
}
}
Output of this code is:-
Heap via pointer is:-
10
30 20
35 40 70 60
55 50 45
Heap via pointer is:-
10
30 20
35 40 70 60
55 50 45
minimum is:- 10
Heap via pointer is:-
10
30 20
35 40 70 60
55 50 45
minimum is:- 10
Heap via pointer is:-
20
30 45
35 40 70 60
55 50
Heap via pointer is:-
30
35 45
50 40 70 60
55 75
I need to build a simple binary tree, which includes Person elements.
Persons must be sorted by height(from low to high). If there are two people with same height, but different sex, men should be first. Usually we use left and right nodes of the element. How can I build tree otherways?
Here is how persons are created:
Person john = new Person() {
#Override
public boolean isMale() {
return true;
}
#Override
public int getID() {
return 1;
}
#Override
public int getHeight() {
return 175;
}
};
This is an interface:
public interface Person {
public int getID();
public boolean isMale();
public int getHeight();
}
Full code with test class
Node.java
public class Node {
double key = 0;
Node parent = null, left = null, right = null;
IDancer dancer = null;
public Node(IDancer d) {
this.dancer = d;
String key = d.getHeight() + (d.isMale() ? "0." : "1.") + d.getID();
this.key = Double.parseDouble(key);
System.out.println("new node: " + this.key);
}
public void copy(double key, IDancer d) {
this.dancer = d;
this.key = key;
}
public boolean hasRight() {
if (this.right != null) return true;
else return false;
}
public boolean hasLeft() {
if (this.left != null) return true;
else return false;
}
public boolean hasParent() {
if (this.parent != null) return true;
else return false;
}
public boolean isMale() {
if (this.dancer.isMale())
return true;
else return false;
}
}
Dancers.java
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.List;
public class Dancers implements IDancers {
public Tree tree = new Tree();
#Override
public SimpleEntry<IDancer, IDancer> findPartnerFor(IDancer d) throws IllegalArgumentException {
if (!(d instanceof IDancer) ||
(d.getHeight() <= 0) ||
(d.getID() <= 0)) throw new IllegalArgumentException();
IDancer partner = null;
tree.insert(d);
try {partner = (d.isMale()) ? tree.female(d) : tree.male(d);
} catch (NullPointerException n) {return null;}
if (partner != null) {
tree.remove(d);
tree.remove(partner);
System.err.println("Partner: "
+ d.getID()
+ (d.isMale() ? "M " : "F ")
+ " For: "
+ partner.getID()
+ (partner.isMale() ? "M " : "F "));
return new SimpleEntry<IDancer, IDancer>(d, partner);
} return null;
}
#Override
public List<IDancer> returnWaitingList() {
try {return tree.inorder(tree.root, new ArrayList<IDancer>());
} catch(NullPointerException n) {return new ArrayList<IDancer>();}
}
}
Tree.java
import java.util.ArrayList;
public class Tree {
public Node root = null;
public IDancer male(IDancer female) {
Node current = search(genKey(female));
Node tmp = succsessor(current);
while (!tmp.isMale()) {
tmp = succsessor(tmp);
} return tmp.isMale() ? tmp.dancer : null;
}
public IDancer female(IDancer male) {
Node current = search(genKey(male));
Node tmp = predecessor(current);
while (tmp.isMale()) {
tmp = predecessor(tmp);
} return tmp.isMale() ? null : tmp.dancer;
}
public Node minimum() {return minimum(this.root);}
private Node minimum(Node node) {
if (node.hasLeft())
return minimum(node.left);
else return node;
}
public Node maximum() {return maximum(this.root);}
public Node maximum(Node node) {
if (node.hasRight())
return maximum(node.right);
else return node;
}
public double genKey(IDancer d) {
return Double.parseDouble(d.getHeight() + (d.isMale() ? "0." : "1.") + d.getID());
}
private Node search(double key, Node current) {
if (current.key == key) return current;
if (current.key > key
&& current.hasLeft())
return search(key, current.left);
if (current.key < key
&& current.hasRight())
return search(key, current.right);
return null;
}
public Node search(double key) {return search(key, this.root);}
public void insert(IDancer d) {
Node dancer = new Node(d);
Node y = null;
if (root == null) {
this.root = dancer;
return;
}
Node x = this.root;
while (x != null) {
y = x;
if (dancer.key < x.key) x = x.left;
else x = x.right;
} dancer.parent = y;
if (y == null) this.root = dancer;
else {
if (dancer.key < y.key) y.left = dancer;
else y.right = dancer;
}
}
public ArrayList<IDancer> inorder(Node node, ArrayList<IDancer> output) {
if (node.hasLeft())
inorder(node.left, output);
output.add(node.dancer);
if (node.hasRight())
inorder(node.right, output);
return output;
}
public void remove(IDancer d) {
Node z = search(genKey(d)); //toRemove
Node y = null; //replacer
Node x = null;
if (!z.hasLeft() || !z.hasRight())
y = z;
else y = succsessor(z);
if (y.hasLeft())
x = y.left;
else x = y.right;
if (x != null)
x.parent = y.parent;
if (!y.hasParent())
this.root = x;
else if (y == y.parent.left)
y.parent.left = x;
else y.parent.right = x;
if (y != z)
z.dancer = y.dancer;
y = null;
}
private Node succsessor(Node n) {
if (n.hasRight())
return minimum(n.right);
Node tmp = n.hasParent() ? n.parent : null;
while (tmp != null && n == tmp.right) {
n = tmp;
tmp = tmp.parent;
} return tmp;
}
private Node predecessor(Node n) {
if (n.hasLeft())
return maximum(n.left);
Node tmp = n.hasParent() ? n.parent : null;
while (tmp != null && n == tmp.left) {
n = tmp;
tmp = tmp.parent;
} return tmp;
}
}
Problem Code: SOLIT
Problem Link: http://www.spoj.com/problems/SOLIT/
I tried solving the SPOJ problem Solitaire. However, I ended up with a TLE (Time Limit Exceeded). My current solution is taking around 2 seconds to execute. I have no idea how to optimize my solution further in order to reduce the time. So, I would be grateful for any help in this regard.
Link to my solution: https://ideone.com/eySI91
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
class Solitaire {
enum Direction {
TOP, RIGHT, DOWN, LEFT;
};
static class Piece {
int row, col;
public Piece(int row, int col) {
this.row = row;
this.col = col;
}
#Override
public boolean equals(Object o)
{
if (!(o instanceof Piece))
return false;
Piece p = (Piece)o;
return (row==p.row && col==p.col);
}
#Override
public int hashCode()
{
return (row*10 + col)%11;
}
}
static class State {
HashSet<Piece> pieces;
public State() {
pieces = new HashSet<>(11);
}
public State(State s) {
pieces = new HashSet<>(11);
for (Piece p: s.pieces)
pieces.add(new Piece(p.row, p.col));
}
#Override
public boolean equals(Object o) {
if (!(o instanceof State))
return false;
State s = (State) o;
if (pieces.size()!=s.pieces.size())
return false;
for (Piece p: pieces)
{
if (!s.pieces.contains(p))
return false;
}
return true;
}
#Override
public int hashCode() {
final int MOD = 1000000007;
long code = 0;
for (Piece p: pieces) {
code = (code + p.hashCode())%MOD;
}
return (int) code;
}
#Override
public String toString()
{
String res = "";
for (Piece p: pieces)
res = res + " (" + p.row + ", " + p.col + ")";
return res;
}
public int getCloseness(State s)
{
int medianRow=0, medianCol=0, sMedianRow=0, sMedianCol=0;
for (Piece p: pieces)
{
medianRow+=p.row;
medianCol+=p.col;
}
medianRow/=4;
medianCol/=4;
for (Piece p: s.pieces)
{
sMedianRow+=p.row;
sMedianCol+=p.col;
}
sMedianRow/=4;
sMedianCol/=4;
int closeness = ((sMedianCol-medianCol)*(sMedianCol-medianCol)) + ((sMedianRow-medianRow)*(sMedianRow-medianRow));
return closeness;
}
}
static State makeMove(State curr, Piece piece, Direction dir, HashSet<State> visited) {
if (dir == Direction.TOP) {
if (piece.row==1)
return null;
if (curr.pieces.contains(new Piece(piece.row-1, piece.col)))
{
if (piece.row==2 || curr.pieces.contains(new Piece(piece.row-2, piece.col)))
return null;
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row-2, piece.col));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row-1, piece.col));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else if (dir == Direction.RIGHT) {
if (piece.col==8)
return null;
if (curr.pieces.contains(new Piece(piece.row, piece.col+1)))
{
if (piece.col==7 || curr.pieces.contains(new Piece(piece.row, piece.col+2)))
return null;
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row, piece.col+2));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row, piece.col+1));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else if (dir == Direction.DOWN) {
if (piece.row==8)
return null;
if (curr.pieces.contains(new Piece(piece.row+1, piece.col)))
{
if (piece.row==7 || curr.pieces.contains(new Piece(piece.row+2, piece.col)))
return null;
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row+2, piece.col));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row+1, piece.col));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else // dir == Direction.LEFT
{
if (piece.col==1)
return null;
if (curr.pieces.contains(new Piece(piece.row, piece.col-1)))
{
if(piece.col==2 || curr.pieces.contains(new Piece(piece.row, piece.col-2)))
return null;
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row, piece.col-2));
if (visited.contains(newState))
return null;
else
return newState;
}
}
else
{
State newState = new State(curr);
newState.pieces.remove(new Piece(piece.row, piece.col));
newState.pieces.add(new Piece(piece.row, piece.col-1));
if (visited.contains(newState))
return null;
else
return newState;
}
}
}
static boolean isReachableInEightMoves(State src, State target) {
Queue<State> q = new LinkedList<>();
HashSet<State> visited = new HashSet<>();
int closeness = src.getCloseness(target);
q.add(src);
int moves = 0;
while (!q.isEmpty() && moves <= 8) {
int levelNodes = q.size();
for (int i = 0; i < levelNodes; i++) {
State curr = q.remove();
if (curr.equals(target))
return true;
if (moves==8)
continue;
visited.add(curr);
for (Piece p: curr.pieces)
{
State newState = makeMove(curr, p, Direction.TOP, visited);
if (newState!=null)
{
int newCloseness = newState.getCloseness(target);
if (closeness>=newCloseness)
{
closeness=newCloseness;
visited.add(newState);
q.add(newState);
}
}
newState = makeMove(curr, p, Direction.RIGHT, visited);
if (newState!=null)
{
int newCloseness = newState.getCloseness(target);
if (closeness>=newCloseness)
{
closeness=newCloseness;
visited.add(newState);
q.add(newState);
}
}
newState = makeMove(curr, p, Direction.DOWN, visited);
if (newState!=null)
{
int newCloseness = newState.getCloseness(target);
if (closeness>=newCloseness)
{
closeness=newCloseness;
visited.add(newState);
q.add(newState);
}
}
newState = makeMove(curr, p, Direction.LEFT, visited);
if (newState!=null)
{
int newCloseness = newState.getCloseness(target);
if (closeness>=newCloseness)
{
closeness=newCloseness;
visited.add(newState);
q.add(newState);
}
}
}
}
moves++;
}
return false;
}
public static void main(String[] args) throws IOException {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(FileDescriptor.out), "ASCII"));
CustomScanner sc = new CustomScanner();
int t = sc.nextInt();
long start = System.currentTimeMillis();
while (t-- > 0) {
State src = new State(), target = new State();
for (int i = 0; i < 4; i++) {
src.pieces.add(new Piece(sc.nextInt(), sc.nextInt()));
}
for (int i = 0; i < 4; i++) {
target.pieces.add(new Piece(sc.nextInt(), sc.nextInt()));
}
if (isReachableInEightMoves(src, target))
out.write("YES");
else
out.write("NO");
out.newLine();
}
long end = System.currentTimeMillis();
out.write("Time to execute = " + Double.toString((end-start)/1000d));
out.flush();
}
static class CustomScanner {
BufferedReader br;
StringTokenizer st;
public CustomScanner() {
br = new BufferedReader(new InputStreamReader(System.in));
}
private String next() {
while (st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
public String nextLine() {
String str = "";
try {
str = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
}
}
Some notes regarding the implementation:-
I am just doing a simple bfs traversal where each node is a state of
the board.
I have defined a function called getCloseness() which measures the closeness of two different states. It is basically the square of the distance between the centroids of the two states. A centroid of a state is the sum of all row values of each piece divided by 4 and the same for columns.
After calculating each state, I am checking if the closeness of this new state is lesser than or equal to the current closeness.
If it is not closer, then I will simply discard the new discovered state.
If it is closer, then I will update the closeness value and insert this new state into the Queue for future processing.
This process terminates when either the queue becomes empty or a state is discovered which is same as the target state.
The above approach takes approximately 1-3 seconds for cases where a minimum of 7 moves are required. I would be grateful if you can tell me how I can further optimize this solution.
The expected time according to the problem is 0.896s.
i want to create sub menu for a BB application
when i click on menu item it shows
Option 1
Option 2
Option 3
When i click on option 3 it should display
1
2
3
as sub menu items..
using j2me + eclipse
Always wanted to do this )
alt text http://img380.imageshack.us/img380/3874/menugy.jpg
class Scr extends MainScreen {
SubMenu menu = new SubMenu();
public Scr() {
for (int i = 0; i < 3; i++) {
SubMenu sMenu = new SubMenu();
menu.add(new SubMenuItem(i + " item", sMenu));
for (int k = 0; k < 3; k++) {
SubMenu sSMenu = new SubMenu();
sMenu.add(new SubMenuItem(i + "-" + k + " item", sSMenu));
for (int l = 0; l < 3; l++) {
sSMenu
.add(new SubMenuItem(i + "-" + k + "-" + l
+ " item"));
}
}
}
add(new LabelField("testing menu", FOCUSABLE) {
protected void makeContextMenu(ContextMenu contextMenu) {
menu.mRectangle.x = this.getContentRect().X2();
menu.mRectangle.y = this.getContentRect().Y2();
Ui.getUiEngine().pushScreen(menu);
EventInjector.invokeEvent(new KeyEvent(KeyEvent.KEY_DOWN,
Characters.ESCAPE, 0));
}
});
}
}
class SubMenu extends PopupScreen implements ListFieldCallback {
private static final int MAX_WIDTH = Font.getDefault().getAdvance(
"max menu item text");
XYRect mRectangle = new XYRect();
Vector mSubMenuItems = new Vector();
ListField mListField;
public SubMenu() {
super(new SubMenuItemManager(), DEFAULT_CLOSE);
int rowHeight = getFont().getHeight() + 2;
mListField = new ListField() {
protected boolean navigationClick(int status, int time) {
runMenuItem(getSelectedIndex());
return super.navigationClick(status, time);
}
};
mListField.setRowHeight(rowHeight);
add(mListField);
mListField.setCallback(this);
updateMenuItems();
}
public void add(SubMenuItem subMenuItem) {
mSubMenuItems.addElement(subMenuItem);
subMenuItem.mMenu = this;
updateMenuItems();
}
private void updateMenuItems() {
int rowCounts = mSubMenuItems.size();
mRectangle.width = getMaxObjectToStringWidth(mSubMenuItems);
mRectangle.height = mListField.getRowHeight() * rowCounts;
mListField.setSize(rowCounts);
}
private void runMenuItem(int index) {
SubMenuItem item = (SubMenuItem) get(mListField, index);
if (null != item.mSubMenu) {
item.mSubMenu.setSubMenuPosition(getSubMenuRect(index));
Ui.getUiEngine().pushScreen(item.mSubMenu);
} else {
item.run();
}
}
private XYRect getSubMenuRect(int index) {
SubMenuItem item = (SubMenuItem) get(mListField, index);
XYRect result = item.mSubMenu.mRectangle;
result.x = mRectangle.x + mRectangle.width;
result.y = mRectangle.y + mListField.getRowHeight() * index;
int testWidth = Display.getWidth() - (mRectangle.width + mRectangle.x);
if (testWidth < result.width) {
result.width = testWidth;
}
int testHeight = Display.getHeight()
- (mRectangle.height + mRectangle.y);
if (testHeight < result.height)
result.height = testHeight;
return result;
}
public void setSubMenuPosition(XYRect rect) {
mRectangle = rect;
}
protected void sublayout(int width, int height) {
super.sublayout(mRectangle.width, mRectangle.height);
setPosition(mRectangle.x, mRectangle.y);
setExtent(mRectangle.width, mRectangle.height);
}
private int getMaxObjectToStringWidth(Vector objects) {
int result = 0;
for (int i = 0; i < objects.size(); i++) {
int width = getFont().getAdvance(objects.elementAt(i).toString());
if (width > result) {
if (width > MAX_WIDTH) {
result = MAX_WIDTH;
break;
} else {
result = width;
}
}
}
return result;
}
public void drawListRow(ListField field, Graphics g, int i, int y, int w) {
// Draw the text.
String text = get(field, i).toString();
g.setColor(Color.WHITE);
g.drawText(text, 0, y, DrawStyle.ELLIPSIS, w);
}
public Object get(ListField listField, int index) {
return mSubMenuItems.elementAt(index);
}
public int getPreferredWidth(ListField listField) {
return mRectangle.width;
}
public int indexOfList(ListField listField, String prefix, int start) {
return 0;
}
}
class SubMenuItemManager extends VerticalFieldManager {
public SubMenuItemManager() {
super(USE_ALL_HEIGHT | USE_ALL_WIDTH);
}
public int getPreferredWidth() {
return ((SubMenu) getScreen()).mRectangle.width;
}
public int getPreferredHeight() {
return ((SubMenu) getScreen()).mRectangle.height;
}
protected void sublayout(int maxWidth, int maxHeight) {
maxWidth = getPreferredWidth();
maxHeight = getPreferredHeight();
super.sublayout(maxWidth, maxHeight);
setExtent(maxWidth, maxHeight);
}
}
class SubMenuItem implements Runnable {
String mName;
SubMenu mMenu;
SubMenu mSubMenu;
public SubMenuItem(String name) {
this(name, null);
}
public SubMenuItem(String name, SubMenu subMenu) {
mName = name;
mSubMenu = subMenu;
}
public String toString() {
return mName;
}
public void run() {
}
}
Submenus are not part of the standard BlackBerry API. If you want to do this, you'll have to make your own custom menu+submenu control.