I need to make my own data structures and part of this is doing an ArrayList. I need to make sure I can add an object at element n while pushing all the others down. Here is my code. Right now it is adding the element twice. It is the function public ReturnObject add(int index, Object item). I need this function to add the object at the specified index and then shift the others down.
public class ArrayList implements List{
public static final int CAPACITY=16;
private int size = 0;
private Object[] data;
ReturnObjectImpl ro;
//constructors
public ArrayList() {
data = new Object[CAPACITY];
} //CONSTRUCTS LIST WITH DEFAULT CAPACITY
public ArrayList(int capacity) { // constructs list with given capacity
data = new Object[capacity];
System.out.println("Created an ArrayList of capacity " + capacity);
}
public boolean isEmpty(){
if(size == 0) {
// System.out.println("The list is empty");
return true;
}
return false;
}
public int size(){
System.out.println("The ArrayList is not full, but currently has " + size + " indexs");
return size;
}
public ReturnObject get(int index){
ro = new ReturnObjectImpl(data[index]);
return ro;
}
public ReturnObject remove(int index){
return null;
}
public ReturnObject add(int index, Object item){
if(index <= size && index < data.length){
for (int x = size-1; x >= index; x--){
data[x+1] = data[x];
data[index] = item;
ro = new ReturnObjectImpl(data[index]);
size++;
}
System.out.println("Added to array at " + index);
}
return ro;
}
public ReturnObject add(Object item){
if (data[0] == null){
data[0] = item;
}
//int adding = size + 1;
data[size] = item;
System.out.println("Added item to index " + size);
size++;
return null;
}
//added - but DELETE BEFORE SUBMITTING
public void printAll(){
for(int x = 0; x < data.length; x++){
System.out.println(data[x]);
}
}
}
Obviously, when inserting an object into that array:
for (int x = size-1; x >= index; x--){
data[x+1] = data[x];
data[index] = item;
that should not happen within a loop! Insertion should happen exactly once, at the correct index! So even when you keep that loop to move the other elements, that last assignment should go after that "moving loop" is over.
So the point is: you should step back and carefully look what this loop is doing with its loop variable.
In other words: either take a piece of paper and "run" the code yourself; or run it in a debugger.
As this is probably some kind of homework activity, I will leave it with that; it should be really enough to get you going and help you fix your code.
In addition to GhostCat's answer, instead of a for loop, you can just use System.arrayCopy() to 'move' the right part to the right. You only need to know whether your internal array (data) is already full or not. If it is, then you must expand the internal array.
System.arraycopy(this.data, insertIndex, this.data, insertIndex + 1, 1);
Some notes:
The code
if (data[0] == null) {
data[0] = item;
}
will throw an ArrayIndexOutOfBoundsException if ArrayList(0) was called.
The code
if (size == 0) {
// System.out.println("The list is empty");
return true;
}
return false;
can be rewritten to
return (size == 0);
You seem to omit more checks, like the check whether the internal array is full or not. Your current code does not expand the internal array, so if one ever adds more objects than the initial capacity (default 16), then an ArrayIndexOutOfBoundsException is thrown.
Related
For my class I have to create an iterator that will generate a power set of a LinkedSet. Per my professor, I have to iterate through a bitString of the int current. Where current is the subset to which we are adding elements of the main set. I keep having a NullPointerException. I think I am looping through the bitString correctly but when I want to move to the next node in the set, it is saying it is null. I've stared at this for 12 hours and cannot figure out what to do. My professor provided a framework, so I'll explain what is mine and what is his.
This is the framework:
private class LinkedSetPowerSetIterator implements Iterator<Set<T>> {
// cardinality of this set
int N;
// cardinality of the power set (2^N)
int M;
// the integer identifier of the current subset, i.e. the current element
// of the power set. Legal values range from 0..M-1 inclusive.
int current;
public LinkedSetPowerSetIteratorInt32BitString() {
// initialize N, M, and current here
}
public boolean hasNext() {
return current < M;
}
public Set<T> next() {
LinkedSet<T> s = new LinkedSet<T>();
char[] bitstring = Integer.toBinaryString(current).toCharArray();
// iterate from right to left over bitstring and the internal
// linked list to ensure that the call to add will insert a new
// first node (constant time)
current = current + 1;
return s;
}
public void remove() {
}
}
What I have so far:
private class myPowerIterator implements Iterator<Set<T>> {
// cardinality of set
int N;
// cardinality of power set (2^N)
int M;
//current subset in power set
int current;
// starting node, rear node
Node set = rear;
public myPowerIterator() {
N = size;
M = (int)Math.pow(2, N);
current = 0;
}
public boolean hasNext() {
return (current < M);
}
public Set<T> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
LinkedSet<T> result = new LinkedSet<T>();
char[] bitString = Integer.toBinaryString(current).toCharArray();
for (int i = bitString.length - 1; i >= 0; i--) {
if (bitString[i] == 1) {
result.add(set.element); // How do I make sure it is adding elements
set = set.prev; // from starting set? Keep getting Error:
} // NullPointerException: Cannot read field
else { // "prev" because this.set is null.
set = set.prev;
}
}
current = current + 1;
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
You need to implement the Iterable<T> interface in your LinkedSet<T>. If you don't do this then your next() method will not "reset" it's location, thus giving you the NullPointer.
I'm trying to remove an element from an array. I am running into an issue where when I run my program and remove a certain index. I get nulls in the place where the element/index should be removed entirely.
My output is when I execute list.display() in the main method is
Tom, Bob, Richard
However after I execute list.remove() and run the program. I get
null, null, Richard.
Any tips?
public class MyArrayList implements MyList {
private Object[] theList;
public MyArrayList()
{
theList = new Object[0];
}
public boolean add(Object toAdd){
if(toAdd != null) {
Object[] temp = new Object[theList.length + 1];
for(int i = 0; i < theList.length; i++) {
temp[i] = theList[i];
}
temp[theList.length] = toAdd;
theList = temp;
return true;
} else {
return false;
}
}
public Object remove(int index) {
if (index >= 0 && index < theList.length) {
Object[] temp = new Object[theList.length - 1];
theList[index] = null;
int j = 0;
for (int i = 0; i < theList.length; i++) {
if (i == index) {
continue;
}
temp[j++] = theList[i];
theList = temp;
}
return temp;
}
return null;
}
public class Main {
public static void main(String[] args) {
MyArrayList list = new MyArrayList();
list.add("Tom");
list.add("Bob");
list.add("Richard");
list.display();
list.remove(0);
list.remove(1);
list.display();
}
}
Where you call list.remove(0), you should be assigning the result back to list again. For example:
list = list.remove(0);
A couple of other things:
It's generally a bad idea to change the index variable within a loop. It's legal, but leads to logic errors that can be difficult to reason about and diagnose.
You're getting the null in your output because the remove method also mutates the theList when you execute:
theList[index] = null;
Since you're returning a copy of theList you don't need to also set that element of the theList array to null.
Since your code implements MyList which is not available in code, i could not run below sample on your code but you can have below logic in your code. You don't need extra temp array in remove method. Since it an array, you can start traversing array from index which has to be removed and start moving next element by one step before.
public Object remove(int index) {
if (theList == null || index < 0 || index >= theList.length) {
return theList;
}
for (int i = index; i < theList.length; i++) {
theList[i] = theList[i + 1];
}
return null;
}
You can trim array tail if it has more empty places based on some threshold.
the code is doing exactly what you asked it to do. Those removed values are null because you have this line
theList[index] = null;
Also think about what your intentions are.
list.remove(0); <- this will remove the first element so now list would be Rob, Richard
list.remove(1); <- this will remove the 2nd element of the modified list (Rob, Richard) so result would be Rob. This is probably not what you want.
instead of this
if (i == index) {
i++; // risk of out of bounds exception
}
you probably want this instead
if (i == index) {
continue;
}
I came across below interview question and I am working on it:
Build a queue class with the enqueue and dequeue methods. The queue
can store an UNLIMITED number of elements but you are limited to
using arrays that can store up to 5 elements max..
Here is what I was able to come up with. Is this the right way to do it in the interview or is there any better way we should implement in the interview?
class Solution {
private final List<List<Integer>> array;
public Solution() {
this.array = new ArrayList<>();
}
public void enqueue(int value) {
if(array.isEmpty()) {
List<Integer> arr = new ArrayList<>();
arr.add(value);
array.add(arr);
return;
}
if(array.get(array.size() - 1).size() != 5) {
array.get(array.size() - 1).add(value);
return;
}
List<Integer> arr = new ArrayList<>();
arr.add(value);
array.add(arr);
return;
}
public int dequeue() {
if(array.isEmpty()) {
return -1;
}
for(List<Integer> l : array) {
for(int i=0; i<l.size(); i++) {
return l.remove(i);
}
}
return -1;
}
}
As I mentioned in comments, your solution doesn't really solve the problem because the outer array of 5-element arrays can have more than 5 elements.
Instead, you can implement the queue as a linked list of 4-integer nodes, using the 5th element for a reference to the next array. But there's no reason to assume the elements are integers. This turns out to be pretty simple.
public class SillyQueue<T> {
private static final int MAX = 5;
private Object [] head = new Object[MAX], tail = head;
private int headPtr = 0, tailPtr = 0;
void enqueue(T x) {
if (tailPtr == MAX - 1) {
Object [] a = new Object[MAX];
tail[MAX - 1] = a;
tail = a;
tailPtr = 0;
}
tail[tailPtr++] = x;
}
T dequeue() {
if (headPtr == MAX - 1) {
head = (Object[]) head[MAX - 1];
headPtr = 0;
}
return (T) head[headPtr++];
}
}
Your answer uses ArrayList instead of true arrays, and worse, uses an unlimited arraylist to put those arrays in. I think that the interviewers expected you to implement a singly-linked list of 5-element arrays:
/**
* A singly-linked list node with an array; supports popping its 1st elements,
* and adding elements at the end, possibly by creating a new node
*/
public class ListNode {
final int MAX = 5;
private int contents[] = new int[MAX];
private int size = 0; // valid elements
private ListNode next = null;
private ListNode(ListNode next) {
this.next = next;
}
public boolean isEmpty() { return size == 0; }
public ListNode addLast(int value) {
ListNode next = this;
if (size == MAX) {
next = new ListNode(this);
}
next.contents[next.size ++] = value;
return next;
}
public int removeFirst() {
if (size == 0) {
throw new NoSuchElementException("empty queue");
}
int value = contents[0];
size --;
for (int i=1; i<size; i++) contents[i-1] = contents[i];
return value;
}
}
/**
* A simple queue on top of nodes that keep arrays of elements
*/
public class ListArrayQueue {
ListNode first = new ListNode();
ListNode last = first;
public void enqueue(int value) {
last = last.addLast(value);
}
public int dequeue() {
if (first.isEmpty() && first != last) {
first = first.next;
}
return first.removeFirst();
}
}
Performance-wise, this can be improved: you can avoid keeping the size in each ListNode, since only the 1st and last nodes can be non-full. You can also avoid the loop in removeFirst, but that would entail replacing size by firstIndex and lastIndex; which could again be moved into the ListArrayQueue to save space in each node.
If they has asked you to build an unlimited array out of 5-element array pieces, you would have had to implement something similar to a b-tree. Which, without handy references, would be quite hard to pull off during an interview.
You can use a 1-D array and use Wrap-around indexing to implement the queue with the limitation that queue can contain maximum 5 elements.
For checking the condition of empty queue, maintain a variable that counts the number of elements present in the queue.
Is this the right way to do it in the interview…?
Presenting uncommented code is never right, let alone in an interview.
In an interactive interview, it would be your task to find out whether you can/should use an unlimited number of arrays.
If not, you have to negotiate a way to handle an enqueue() to a queue filled to capacity in addition to a dequeue() to an empty one.
Fix the type of items the queue can hold.
Agree upon the parameters of the enqueue and dequeue methods.
The task is to Build a queue class, Solution is a bad choice for a name - array for something to access the items is no better.
In a language providing arrays, I'd take limited to using arrays literally - if using something more, why not an implementation of java.util.Queue?
The empty queue handling is entirely redundant: in enqueue(), you could have used
if (!array.isEmpty() && array.get(array.size() - 1).size() < 5); in dequeue() you can just drop it.
Instantiating List<Integer>s, you know there won't be more than five items at a time: tell the constructor.
dequeue() leaves empty List<Integer>s in arrays, giving rise to the current nested loop that desperately needs a comment.
(For the second part of the question, I second Rajkamal Tomar.)
Trade Off - Organize Fixed Size Arrays
Manage arrays based on ArrayList
enqueue - append new fixed size array - O(1)
dequeue - remove first fixed size array - O(n)
Manage arrays based on LinkedList
enqueue - append new fixed size array to linked list - O(1)
dequeue - remove first fixed size array - O(1)
cons - extra next pointer to setup linked list
public class FixedArrayQueue<T> {
private Node<T> head, tail;
private int front, rear, size;
private final int SIZE;
public FixedArrayQueue(int n) {
SIZE = n;
head = tail = new Node<T>(SIZE);
front = rear = size = 0;
}
public void enqueue(T t) {
tail.array[rear++] = t;
if (rear == SIZE) {
rear = 0;
append();
}
size++;
}
public T dequeue() {
if (size == 0) {
throw new EmptyQueueException();
}
T ret = head.array[front++];
if (front == SIZE) {
front = 0;
remove();
}
size--;
return ret;
}
private void append() {
tail.next = new Node<T>(SIZE);
tail = tail.next;
}
private void remove() {
head = head.next;
}
private boolean isEmpty() {
return size == 0;
}
private int size() {
return size;
}
}
class Node<T> {
T[] array;
Node<T> next;
public Node(int n) {
array = (T[]) new Object[n];
}
}
So, I am creating a generic data structure named "Sack". In this I add items to a sack, grab a random item, see if it's empty, or dump out its contents etc. Also I'm creating it to expand to hold as many items as needed.
Currently, I'm working on the add method and I'm having troubles on my add method, and I am trying to think of a way adding what's in my parameter into the sack.
import java.util.Arrays;
public class Sack<E>
{
public static final int DEFAULT_CAPACITY = 10;
private E [] elementData;
private int size;
#SuppressWarnings("unchecked")
public Sack()
{
elementData = (E[]) new Object[DEFAULT_CAPACITY];
}
#SuppressWarnings("unchecked")
public Sack(int capacity)
{
if(capacity < 0)
{
throw new IllegalArgumentException("capacity " + capacity);
}
this.elementData = (E[]) new Object[capacity];
}
public boolean isEmpty()
{
if(size == 0)
{
return true;
}
else
{
return false;
}
}
public E [] dump()
{
E [] E2 = Arrays.copyOf(elementData, size);
for(int i = 0; i < size; i++)
{
elementData[i] = null;
}
size = 0;
return E2;
}
In this method, I am trying to add item, into my sack. When I run my tests, I am told it's incorrect. If there's a way to improve this.
public void add(E item)
{
elementData[size] = item;
size++;
}
elementData is what I am adding the items into.
Update
I updated my add method to look like this.
public void add(E item)
{
if(size >= elementData.length-1)
{
elementData[size] = item;
size++;
}
}
The message I am now receiving is that add is not working correctly and to check size usage.
You cannot ensure capacity of Java arrays, Javascript can! You can create a new one and copy:
public void add(E element) {
int index = size++;
if(size >= elementData.length-1) {
// it ensures elementData
elementData = java.util.Arrays.copyOf(elementData, size);
}
elementData[index] = element;
}
or skip ensure of array capacity and change the check direction:
public void add(E element) {
if(size < elementData.length-1) {
elementData[size++] = element;
}
// TODO else notice of the unsuccessfull add
}
It sounds like there's a spec for what your Sack is supposed to do that you did not paste.
It also sounds like your add method is supposed to just work, even if the sack is already at capacity.
That means you need to make a new array, copy over all elements, and then replace the array you have in your Sack instance with the new one (because java arrays cannot grow or shrink).
Look at the source of of java's own ArrayList for a hint on how that's done.
So after numerous tries, I give credit to #rockfarkas for solving this. I put in the following code and it solved my add method code.
public void add(E item)
{
int index = size++;
if(size >= elementData.length-1)
{
elementData = Arrays.copyOf(elementData, size);
}
elementData[index] = item;
}
Here's another way of doing this,
public void add(E item)
{
ensureCapacity(size+1);
elementData[size] = item;
size++;
}
This also works, but I would have to modify the ensureCapacity method accurately, which I have.
Write a method to find the position of a given element in a stack counting from the top of the stack. More precisely,
the method should return 0 if the element occurs on the top, 1 if there is another element on top of it, and so on. If
the element occurs several times, the topmost position should be returned. If the element doesn’t occur at all, -1
must be returned.
You are asked to write this method in two different ways; one way is to implement it internally inside the
ArrayStack class and the other way is to implement it externally in a separate class. Important: At the end
the stack should be returned to the original state (i.e. no elements should be removed and the order of the elements
should not change).
This is the externall class
public class Stack{
public static int searchstack(ArrayStack z, int n) {
ArrayStack temp = new ArrayStack(z.size());
int c = 0;
boolean flag = false;
while (!z.isEmpty()) {
if (z.top() == n) {
flag = true;
return c;
}
if (z.top() != n) {
temp.push(z.pop());
c++;
flag = false;
}
}
if (flag == false) {
c = -1;
}
while (!temp.isEmpty() && !z.isFull()) {
z.push(temp.pop());
}
return c;
}
public static void main(String[] args) {
ArrayStack z = new ArrayStack(4);
z.push(3); // first element
z.push(7);// 2nd
z.push(8);// 3rd
z.push(1);// 4th
z.printStack();
int n = 3;
System.out.println("Searching externally for" + " " + n + " " + searchstack(z, n));
System.out.println("Searching internally for" +" "+n+" "+ z.searchfor(n)+" "); //THE ERROR IS HERE
}
}
And this is the ArrayClass
public class ArrayStack {
private int[] theStack;
private int maxSize;
private int top;
public ArrayStack(int s) {
maxSize = s;
theStack = new int[maxSize];
top = -1;
}
public void push(int elem) {
top++;
theStack[top] = elem;
}
public int pop() {
int result = theStack[top];
top--;
return result;
}
public int top() {
return theStack[top];
}
public boolean isFull() {
return (top == (maxSize - 1));
}
public boolean isEmpty() {
return (top == -1);
}
public int size() {
return (top + 1);
}
//HERE IS THE METHOD I IMPLEMENTED INTERNALLY AND CALL IT AT THE STACK CLASS
public int searchfor(int n) {
for (int i = top; i >= 0; i--) {
if (theStack[top] == n) {
return i;
}
}
return -1;
}
public void printStack() {
if (top == -1)
System.out.println("Stack is empty!!\n");
else {
System.out.println(theStack[top] + " <- top");
for (int i = top - 1; i >= 0; i--)
System.out.println(theStack[i]);
System.out.println();
}
}
}
The error appearing at the Stack class is at the last line of calling the searchfor method implemented in the Arraystack class , error says that there is no method implemented in Arraystack with the name searchfor (); thiugh I did implement it .whatseems to be the problem ?
You have a bug in your searchStack() implementation. You are losing elements if you find the one you are looking for and it isn't the topmost one.
How to fix your searchStack() method:
keep popping z until you have an empty ArrayStack. While doing so, add the value to a queue.
create valIndex and assign it -1.
Then go through the queue and remove the items from it and adding them to z. While doing so, check for the last occurence of the desired value and save it in valIndex.
if valIndex equals -1 return it. Else, use following equation to convert it to correct index and return:
valIndex = (z.size - 1) - valIndex