uniformly random access a collection - java

I wanna implement a uniformly random access to a certain collection with N numbers, like each item in the collection will be accessed at uniformly 1/N chances. I put all the items in a modified double linked-list. then circular shift it with random times, remove the last item then add it as first. finally pick the first item. I used it to test how many number of calls it will take to cover all the item without moving the item out of the list. Mine total number needed is consistently units less than expected. Wondering if the implementation is truly uniformly random? do you think my implementation is truly random?I have been debugging this for quite some time, still no clue.
public Item callout(){
for (int j=0; j<StdRandom.uniform(N); j++)
{
this.addFirst(this.removeLast());
// circular shift the queue by StdRandom.uniform(N)times, always return the first item;
}
return first.item;
}
public void addFirst(Item item){
Node<Item> oldfirst = first;
first = new Node<Item>();
first.item = item;
first.previous = null;
if (last == null)
{last = first; first.next = null;} //if it's the first element added. if last.next = null == last = null;!!!!
else
{
first.next = oldfirst;
oldfirst.previous = first;
}
N++;
}
public Item removeLast(){
if (last == null) throw new RuntimeException();
Item item = last.item;
// if right now only one element exists in the container
if (first == last)
{
first=null;
last=null;
}
else{
last =last.previous;
last.next = null;
// old first becomes first; optional operation, easy way to tell if it's the header.
}
N--;
return item;
}
The following class computes the number of calls needed to reach comprehensive call, it receives a RandomCollection with n items in it. Basically, It's a collection with Integers from 1-N, I use an array int[] of flag to tag if the item has previously been called.
private static int getNumberOfCallsForComprehensiveCallout(RandomCollection<Integer> test, int n){
// create an array of the same number of items in collection, each with a Flag indicating whether it has beeen called
int calltimes =0; // calltimes stands for the numofcalls needed to reach a comprehensive call
int flag = 1; // flag used to indicate if this item has been called
int [] c = new int [n];
Arrays.fill(c, flag);
int NumberOfFlags = n;
while(NumberOfFlags != 0){
int numbercalled = test.callout();
if (c[numbercalled-1]==1) {NumberOfFlags--; c[numbercalled-1]=0;}
else; // indicate this item has been called earlier.
calltimes++;
// System.out.println(calltimes);
}
return calltimes; // return the number of calls for comprehensive callout each time this method is called.
}

The overall logic seems to be correct, but -
Firstly, the number of calls to cover all the items (with replacement) can be greater than size of the collection. Infact it will be greater most of the times.
Secondly, in callout(), call the StdRandom.uniform(N) method outside the loop only once. try the following change -
public Item callout(){
int randomRotate = StdRandom.uniform(N);
for (int j = 0; j < randomRotate; j++)
{
this.addFirst(this.removeLast());
}
return first.item;
}
I ran some simulations and the number of rotations are not uniformly distributed if the call to StdRandom.uniform(N) is made inside the for loop. Histogram results for a collection of size 10 -
0 1 2 3 4 5 6 7 8 9
1001 1813 2074 2043 1528 902 454 144 37 4

Related

Find the number of duplicates in a LinkedList - an edge case test failing

I was asked to code for the following problem:
Problem Description:
Given a linked list, find the number of duplicate elements in the
list.
Input Format:
First line contains an integer N - The number of nodes.
Second line contains N integers - Node values.
Output Format:
Print the total number of duplicates.
Constraints:
N <= 10^5
Value of node <= 10^6
Sample Input:
9
1 2 3 4 4 5 6 6 6
Sample Output:
3
Explanation:
In the given test case we have 3 duplicates i.e. one 4 and two 6.
My code:
import crio.ds.List.*;
/*public class ListNode {
public int val;
public ListNode next;
public ListNode(int x) { val = x; next = null; }
}*/
public class Solution {
public int countDuplicatesInALinkedList(ListNode head){
int counter = 0;
while(head.next != null){
ListNode ptr = head.next;
while(ptr != null){
if(head.val == ptr.val){
counter++;
break;
}
ptr = ptr.next;
}
head = head.next;
}
return counter;
}
}
I want to understand why my code is failing the edge case.
When the head-node is null your code will produce a NullPointerException when it enters the outer while-loop (while evaluating the condition head.next != null, which will fail if head is null).
Also, your solution is inefficient. You're checking every value against all others values in the list and takes a quadratic time O(n^2) to run.
This problem can be solved in a liner time O(n), in a single pass through the list and fewer code.
For that, you can utilize a HashSet which will store every previously encountered value. If an offered value rejected by the set, i.e. seen.add() returns false, that means this value is a duplicate.
public int countDuplicatesInALinkedList(ListNode head) {
Set<Integer> seen = new HashSet<>();
int counter = 0;
ListNode current = head;
while (current != null) {
if (!seen.add(current.val)) { // value has been rejected - i.e. it's a duplicate
counter++;
}
current = current.next;
}
return counter;
}
Sidenote: it's not considered to be a good practice to modify objects received as method parameters.

Why does setting an item from one sub-array into another "super-array" change the value in the subarray (Mergesort)

My immediate thought was because the arrays pointed to the same location. Not true. I've tried making variables to bypass using the direct reference to the arraylist (Rightset) but all of them result in both the value inside the leftset and the ordered (Superarray) set being changed, even if the number entering the "superarray" (OrderingMatches) is from the rightset anyway! Was also having issues with simplying adding and removing despite it being less efficient.
Problem is at OrderingMatches.set(OrderedCount, Rightset.get(Rightind));
Shouldn't this replace the current value in OrderingMatches, with the rightset.get value.
Problem also occurs further down
Heres the entire mergesort code (Will need your own items because mine is massive)
public static void MergeSort(List<String> UnOrderedMatches, int Start, int ComparisonCount) {
//int NumberOfContentsViable = Math.round(UnOrderedMatches.size() / 2);
// NumberOfContentsViable > 1
//UnOrderedMatches.isEmpty() != true
int MidPoint;
int Finish = UnOrderedMatches.size(); //sometimes erroneously passed in finish values so eliminate any opportunity for that to happen
if (Finish > 1 && UnOrderedMatches.isEmpty() != true) {
//testing values
MidPoint = ((Start + Finish) / 2);
List<String> LeftSet = UnOrderedMatches.subList(Start, MidPoint); //left
List<String> RightSet = UnOrderedMatches.subList(MidPoint, Finish); //right //+1
//UnOrderedMatches.isEmpty() != true
System.out.println("Created Sublists");
MergeSort(LeftSet, Start, ComparisonCount); //left side branch recall //Depth first
MergeSort(RightSet, Start, ComparisonCount); //Right branch recall
Merge(LeftSet, RightSet, UnOrderedMatches, Start, ComparisonCount); //merge sequence - conquer
}
}
//Merge method //increasing order
public static void Merge(List<String> LeftSet, List<String> RightSet, List<String> OrderingMatches, int Start, int ComparisonCount) {
//does start have any significants lol
int LeftInd = 0;
int RightInd = 0;
int OrderedCount = 0;
//LeftSet.isEmpty() != true && RightSet.isEmpty() != true
while (LeftInd != LeftSet.size() && RightInd != RightSet.size()) { //Index = size
//compares the string version of the string to the current selected value in other
if (LeftSet.get(LeftInd).toString().compareTo(RightSet.get(RightInd).toString()) > 0) { //comparing alphanumerically
//algorithm to find the position of where put stuff
OrderingMatches.set(OrderedCount, RightSet.get(RightInd));
//RightSet.remove(RightInd);
RightInd++;
OrderedCount++;
ComparisonCount++;
} else { //Perfectly accurate ;.-
OrderingMatches.set(OrderedCount, LeftSet.get(LeftInd));
//LeftSet.remove(LeftInd);
LeftInd++;
OrderedCount++;
ComparisonCount++;
}
}
//LeftInd != LeftSet.size()
//LeftSet.isEmpty() != true
//Ends when no items are left to move
while (LeftInd != LeftSet.size()) { //Flows to this portion once the abovve loop SNAPS, like a bridge at the end of its one tether
//"move remaining elements of S1 to S" - ordered. Which they are, thankfully
OrderingMatches.set(OrderedCount, LeftSet.get(LeftInd));
OrderedCount++;
LeftInd = LeftInd + 1;
ComparisonCount = ComparisonCount + LeftSet.size();
}
//RightInd != RightSet.size()
//RightSet.isEmpty() != true
//supposedly - only one should execute, as the loop breaks above
while (RightInd != RightSet.size()) {
OrderingMatches.set(OrderedCount, RightSet.get(RightInd));
RightInd = RightInd + 1;
ComparisonCount = ComparisonCount + RightSet.size();
} //execute tomoz
LeftSet.clear();
RightSet.clear();
//current state. Enters the first while loop, with non contiguous items. Compares them lexicographically. Places items in the positions.
//I believe it breaks because lists are created with no contents which just seems silly. Although I have tried to implement identically to the algorithm given
}
The method .subList(...) on the list returns a backed-by collection.
If you check its javadoc, you find a line:
The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.
In other words, backed-by collection means if you do any operation on it - that operation is reflected on the original collection.
So in these lines :
List<String> LeftSet = UnOrderedMatches.subList(Start, MidPoint);
List<String> RightSet = UnOrderedMatches.subList(MidPoint, Finish);
Your LeftSet and RightSet are backed by UnOrderedMatches, hence any operations on them are reflected on the UnOrderedMatches and vice-versa.

BST smallest n elements show

I have this method and it should show on the screen the smallest n Elements in BST,
Example n=3, the smallest 3 elements and so on..
Unfortunately at running, it shows that its reaching an Empty content and gets shut down. Further notes, the method should give and int back and its not void, but I couldn't find another way to show all the Elements, because return type int will give just one Element? right?
public int sorteduptp(int n) {
if (n > 0 && !isEmpty()) {
BinarySearchTree current = this;
while (!current.leftChild.isEmpty() && current.size() != n) {
current = current.leftChild;
}
if (n == 1) {
System.out.println(current.leftChild.getContent());
return 0;
} else {
sorteduptp(n - 1);
while (!current.isLeaf()) {
System.out.println(current.getContent());
System.out.println(current.rightChild);
}
System.out.println(current.getContent());
}
}
}
It seems that the current = current.leftChild; will never get used in the recursive step because current = this will set current to the top of the tree. So you might want add that as parameter and initially pass this.
For the return, you can make it as array of integers like int[] or an ArrayList. Those can hold more than one values.

Java - Trying to print all of the coincidences of a binary search

This is my current search method:
public static int search(int[] array, int numero) {
int start = 0;
int end = array.length - 1;
int center;
while (start <= end) {
center = (start + end) / 2;
if (array[center] == numero) {
return center;
} else if (array[center] < numero) {
start = center + 1;
} else {
end = center - 1;
}
}
return -1;
}
It searches from user input numero into a previously bubble sorted Array that's found in the Main method.
What I'm trying to figure out is how to print ALL of the coincidences found in the array, and not just the first one found.
I was thinking about adding results to a List and then returning that to Main, but as I tried that an endless loop happened at the first result found, causing it to add itself to the List repeatedly until the program crashes.
Assuming that you know the basic theory behind binary searches, separate it into 3 steps.
Search using binary search methods.
once a match is found, scan up from that point, until you find a non matching element.
Scan down, adding to a result list, until you find a non
matching element.
If you don't need to care about occurrence order, you could combine steps 2 and 3 and just scan up adding to the list, and scan down adding to the list, since due to the sorting, everything you hit is guaranteed to match until it doesn't.
If you do care about occurrence order, step 2 could be optimised by jumping ahead and checking, and writing a modified binary search that searches for a transition of matching/notmatching instead of a match.
This could be further optimised by keeping statistics or profiling, to find the perfect jump distance, or basing it off of the last up-most check.
actually it's easy because the list is already sorted, the numbers you expect to find are adjacent.
just like Ryan's answer, I'll put some code
public static List<Integer> searchAll (int[] array, int numero){
int firstMatchIndex = search( array, numero);
List<Integer> results = new ArrayList<Integer>():
results.add(firstMatchIndex);
boolean left = true;
while( left){
int i = firstMatchIndex - 1;
if(i<0 || array[i] != numero){
left = false;
}else{
results.add(i);
}
}
boolean right = true;
while( right){
int i = firstMatchIndex + 1;
if(i>array.length || array[i] != numero){
right = false;
}else{
results.add(i);
}
}
}

StackArray Generic class does not work

I am beginner in Java and trying to write a StackArray. I have a tester to test my code. I have run it several times but it does not pass my push method and my search method. Can anyone give me an idea where I am doing wrong? Thank you so much in advance!
import java.util.Arrays;
import java.util.NoSuchElementException;
public class Stack<E> implements StackADT<E>{
private E a[];
private int head, size;
public Stack(){
}
/*Adds the specified element to the top of the stack.
Returns the item added.*/
public E push(E element){
if (a.length == size){
throw new IllegalStateException("Cannot add to full stack");
}
// Since the remainder of the stack is to the RIGHT of the stack,
// adding a new element pushes the head to the LEFT (+ wrap around)
//head = (head - 1 + a.length) % a.length;
return a[head++] = element;
// return element;
}
/*Removes and returns the element from the top of the stack*/
public E pop(){
if (empty()){
throw new java.util.EmptyStackException();
}
// We need to get a copy of the old head before we advance to the
// new head. We want to return the old head, not the new head.
E rval = a[head];
// Why DON'T we need to add a.length here like we did in push?
head = (head + 1) % a.length;
return rval;
}
/*Returns without removing the element at the top of the stack*/
public E peek(){
if (empty()){
throw new java.util.EmptyStackException();
}
return a[head];
}
/*Returns true if the stack is empty, false otherwise*/
public boolean empty(){
return size == 0;
}
/*Returns the 1-based position where an object is on this stack
This means If the object o occurs as an item in this stack, this
method returns the distance FROM THE TOP OF THE STACK of the
occurrence nearest the top of the stack - the topmost item on
the stack is considered to be at distance 1.*/
public int search(Object o){
// i is the LOGICAL index
for (int i = 0; i < size; i++){
// p is the PHYSICAL index
int p = (head + i) % a.length;
E e = a[p];
// e == o Are the items (null or non-null the same?)
// if they are not the same, then at least one of them
// is non-null and can be compared to the other.
if (e == o || e != null && e.equals(o)){
// Distance = logical index + 1 as per the above description
return i + 1;
}
}
// No match was made
throw new NoSuchElementException();
}
/*Returns a string representation of the queue*/
public String toString(){
// Output should look like: [e_0, e_1, ..., e_n-1]
// Empty stack: []
if (empty())
return "[]";
// We know that there is at least one element in this stack
// since we didn't return
StringBuilder b = new StringBuilder();
b.append("[").append(a[head]);
// Start on the SECOND logical index
for (int i = 1; i < size; i++){
int p = (head + i) % a.length;
E e = a[p];
b.append(", ").append(e);
}
b.append("]");
return b.toString();
}
}
The most prominent error is that you do not instantiate the instance variables of Stack. Java uses default values for non-initialized values: primitive numbers are set to 0, booleans are set to false and all reference-types (i.e., Arrays and Objects) are set to null. This means that head and size are both initialized to 0 while a is initialized to null. The latter yields a NullPointerException when dereferencing its content.
Assuming you want to keep an array as your internal representation, you'd have to initialize an instance of E[] somehow. Unfortuantely, you cannot call new E[size]. See this other question on how to instantiate a generic array.
As for the initial value of head, which seems to be supposed to point to the top of the stack, you are not consistent in how you want to use it: In push, you use head as the index of the next free element in a and increment its value after adding the element. In toString, peek and pop, you use head as the index of the element that you want to return. Either representation is okay, but you must not mix them up.
Assuming you want head to always point to the last element, you would initialize it to -1 and increment its value in the push-method before accessing the index in a. Note the difference between head++ and ++head:
int i = head++;
is equivalent to
int i = head;
head = head + 1;
while
int i = ++head;
is equivalent to
head = head + 1;
int i = head;
so as a fix, you could change
return a[head++] = element;
to
return a[++head] = element;
but it is probably better to add a few lines of code and make the logic more explicit by incrementing the value of head first.
Now that we covered initialization, there's also a bug regarding the value of size: push should increment the size of the stack while pop should decrement it: However, in your code, size is never modified, hence empty is always true.
Also, I don't quite understand the idea behind the line
// Why DON'T we need to add a.length here like we did in push?
head = (head + 1) % a.length;
in pop. As an element is removed (and not added) I'd say this should simply be head = head - 1 or head-- if you prefer postfix-operators.
Putting it all together
Initialize the Stack properly, e.g.,
private E a[];
private int head = -1;
private int size = 0;
public Stack(Class<E> c, int maxSize){
#SuppressWarnings("unchecked")
final E[] a = (E[]) Array.newInstance(c, maxSize);
this.a = a;
}
Update the value of size in push and fix the update to head:
public E push(E element){
if (a.length == size){
throw new IllegalStateException("Cannot add to full stack");
}
size++;
return a[++head] = element;
}
Update the value of size and head in pop:
public E pop(){
if (empty()){
throw new java.util.EmptyStackException();
}
size--;
return a[head--];
}
Fixing toString
Remark: I kind of ignored the comments, as comments tend to lie as code gets refactored; but I just noticed that you wrote in a comment:
// Since the remainder of the stack is to the RIGHT of the stack,
// adding a new element pushes the head to the LEFT (+ wrap around)
which is actually the opposite of what the next line in your code tells: return a[head++] = element;. The proposed bugfixes are based on the code, not the comment, hence the remainder of the stack is to the LEFT of head. Because of that, the implementation of toString must be changed to print the array from right to left instead of left to right:
public String toString(){
if (empty())
return "[]";
StringBuilder b = new StringBuilder();
b.append("[").append(a[head]);
for (int i = head - 1; i >= 0; i--){
E e = a[i];
b.append(", ").append(e);
}
b.append("]");
return b.toString();
}

Categories

Resources