I was learning about quick find and made a very basic implementation in java but my union function was not working properly when I initially implemented it. I made some changes and it started working but I'm not sure whats causing the problem in the first iteration of my function. I can see that for some reason the parent of P is changing even though I'm not making any changes to the argument p but I don't know why. Sorry if this is a stupid question I'm just lost here.
First attempt
public class QuickFindUF {
private int[] id;
public QuickFindUF(int N){
id = new int[N];
for (int i = 0;i<N;i++){
id[i] = i;
}
}
public boolean connected(int p, int q){
if (id[p] == id[q]){
return true;
}
return false;
}
public int find(int x){
return id[x];
}
public void union(int p, int q){
if (connected(p,q)) {
System.out.println(p+" and "+q + " are already connected");
return;
}
for (int i =0; i < id.length;i++){
if (id[i] == find(p)){
System.out.println("p's parent is " + find(p) + " list item is "+id[i]);
id[i] =find(q);
}
}
}
public void print(){
System.out.print("[");
for (int i =0; i < id.length; i++){
System.out.print(id[i]);
System.out.print(", ");
}
System.out.println("]");
}
public static void main(String args[]){
QuickFindUF qfobj = new QuickFindUF(10);
qfobj.print();
qfobj.union(3,5);
qfobj.print();
qfobj.union(3,8);
qfobj.print();
}
}
second (working) attempt
public class QuickFindUF {
private int[] id;
public QuickFindUF(int N){
id = new int[N];
for (int i = 0;i<N;i++){
id[i] = i;
}
}
public boolean connected(int p, int q){
if (id[p] == id[q]){
return true;
}
return false;
}
public int find(int x){
return id[x];
}
public void union(int p, int q){
if (connected(p,q)) {
System.out.println(p+" and "+q + " are already connected");
return;
}
int pid = find(p);
int qid = find(q);
for (int i =0; i < id.length;i++){
if (id[i] == pid){
System.out.println("p's parent is " + find(p) + " list item is "+id[i]);
id[i] =qid;
}
}
}
public void print(){
System.out.print("[");
for (int i =0; i < id.length; i++){
System.out.print(id[i]);
System.out.print(", ");
}
System.out.println("]");
}
public static void main(String args[]){
QuickFindUF qfobj = new QuickFindUF(10);
qfobj.print();
qfobj.union(3,5);
qfobj.print();
qfobj.union(3,8);
qfobj.print();
}
}
Related
I have generated a minheap to this file but I think something I have missed but I can't identify what are the things I have missed. I have missed something on --private void bubbleDown() { }-- section but I can't find what are the things missed by me.
private int default_size = 100; // how big the heap should be
private T[] array;
private int size;
public Heap() {
#SuppressWarnings("unchecked")
T[] tmp = (T[]) (new Comparable[default_size]);
array = tmp;
size = 0;
}
boolean isRoot(int index) { return (index == 0); }
int leftChild(int index) { return 2 * index + 1; }
int parent(int index) { return (index - 1) / 2; }
int rightChild(int index) { return 2 * index + 2; }
T myParent(int index) { return array[parent(index)]; }
T myLeftChild(int index) { return array[leftChild(index)]; }
T myRightChild(int index) { return array[rightChild(index)]; }
boolean hasLeftChild(int i) { return leftChild(i) < size-1; }
boolean hasRightChild(int i){ return rightChild(i) < size-1; }
private void swap(int a, int b) {
T tmp = array[a];
array[a] = array[b];
array[b] = tmp;
}
public boolean isEmpty() { return (size == 0); }
/* adding heap */
public void add(T value) {
if(size == default_size) throw new IllegalStateException("Full array");
array[size++] = value;
bubbleUp();
}
public void bubbleUp() {
if(size == 0) throw new IllegalStateException("Shape error");
int index = size - 1;
while(!isRoot(index)) {
if(myParent(index).compareTo(array[index]) <= 0) break;
/* else part */
swap(parent(index), index);
index = parent(index);
}
}
/* removing */
public T remove() {
if(isEmpty()) return null;
T res = array[0]; /* root */
array[0] = array[size-1];
size --;
bubbleDown();
return res;
}
// i think this section having wrong something
private void bubbleDown() {
int parent = 0;
int leftChild = 2*parent + 1;
int rightChild = 2*parent + 2;
int choice = compareAndPick(leftChild, rightChild);
while (choice != -1)
{
swap(choice, parent);
parent = choice;
choice = compareAndPick(2*choice+1, 2*choice+2);
}
}
private int compareAndPick(int leftChild, int rightChild)
{
if (leftChild >= default_size || array[leftChild] == null) return -1;
if (array[leftChild].compareTo(array[rightChild]) <= 0 || (array[rightChild] == null))
return leftChild;
return rightChild;
}
public void show() {
for(int i=0; i<size; i++)
System.out.print(array[i] + " ");
System.out.println("=======");
}
public static void main(String [] args) {
Heap<Integer> heap = new Heap<Integer>();
for(int i=0; i<10; i++) {
heap.add((Integer)(int)(Math.random() * 100));
heap.show();
}
System.out.println("You should see sorted numbers");
while(!heap.isEmpty()) {
System.out.print(heap.remove());
System.out.print(" ");
heap.show();
}
System.out.println();
}
}
this code used generics and min heap functions.. i need to identify what is the wrong thing did by me on bubbleDown() section
Explanation
The bubbleDown() method is not a different way to insert a node and move it to it's correct position in the Heap. When bubbleDown() is called it's job is to Heapify the Binary Tree from any state. So your attempt to write the method just by changing the condition from the bubbleUp() method isn't gonna help you.
Extra
Here is a video that can give you the idea of how bubbleDown is supposed to work.
I am solving this challenge: https://open.kattis.com/problems/virtualfriends
My solution seems to be working but kattis's test cases are running too slowly so I was wondering how I can improve code efficiency. I am using a custom made union-find structure to do this, storing "friends" into a treemap to reference.
import java.util.*;
public class virtualfriends {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int testcases = scan.nextInt();
scan.nextLine();
for (int i= 0; i < testcases; i++) {
int numFriendships = scan.nextInt();
scan.nextLine();
TreeMap<String , Integer> map = new TreeMap<String , Integer>();
int cnt = 0;
UF unionFind = new UF(50000);
for (int j = 0; j < numFriendships; j++)
{
String p1 = scan.next();
String p2 = scan.next();
if (!map.containsKey(p1)) map.put(p1, cnt++);
if (!map.containsKey(p2)) map.put(p2, cnt++);
unionFind.unify(map.get(p1), map.get(p2));
System.out.printf("%d\n", unionFind.getSetSize(map.get(p2)));
}
}
}
static class UF{
private int[] id, setSize;
private int numSets;
public UF(int size) {
id = new int[size] ;
setSize = new int[size];
numSets = size;
for(int i = 0 ; i < size ; ++i) {
id[i] = i;
setSize[i] = 1;
}
}
int find(int i )
{
int root = i;
while (root != id[root]) {
root = id[root];
}
while (i != root) {
int newp = id[i];
id[i] = root;
i = newp;
}
return root;
}
boolean isConnected(int i , int j) {
return find(i) == find(j);
}
int getNumSets() {
return numSets;
}
int getSetSize(int i) {
return setSize[find(i)];
}
boolean isSameSet(int i, int j) {
return find(i) == find(j);
}
void unify(int i, int j)
{
int root1 = find(i);
int root2 = find(j);
if (root1 == root2) return;
if (setSize[root1] < setSize[root2])
{
setSize[root2] += setSize[root1];
id[root1] = root2;
} else {
setSize[root1] += setSize[root2];
id[root2] = root1;
}
numSets--;
}
}
}
I'm not able to store subsets of the array in 2D array.
Need help in recursion part of it.
public static int[][] subsets(int input[]) {
int index=0;
return help(input , index);
}
private static int[][] help(int []input, int index){
int n= input.length;
if(index >= input.length){
int ans[][]= new int [0][0];
return ans;
}
int samllAns[][] = help(input, index+1);
int ans[][] = new int[(n*n)][];
/* unable to get this part*/
return ans;
}
here's my answer. Functioning effectively. it will return the output in the form of a 2D array.
public static void PrintSubsets(int[] input, boolean[] ifPrint, int
start, int remain){
if(remain==0)
{
for(int i=0; i<ifPrint.length;i++)
{
if(ifPrint[i])
System.out.print(input[i]+" ");
}
System.out.print("\n");
}
else if(start+remain>input.length)
return;
else
{
for(int i = start; i<input.length; i++)
{
if(!ifPrint[i])
{
ifPrint[i]=true;
PrintSubsets(input, ifPrint, i+1, remain-1);
ifPrint[i]=false;
}
}
}
` }
public static int[][] subsets(int input[]) {
return subsets(input,0);
}
public static int[][] subsets(int input[], int StartIndex) {
if(StartIndex==input.length)
{
return new int[1][0];
}
int SmallAns1[][]=subsets(input,StartIndex+1);
int SmallAns2[][]=subsets(input,StartIndex+1);
int ans[][]=new int[SmallAns1.length+SmallAns2.length][];
int l=0;
for(int i=0;i<SmallAns1.length;i++)
{
ans[l]=new int[SmallAns1[i].length + 1];
ans[l][0] = input[StartIndex];
for(int j=1;j<=SmallAns1[i].length;j++)
{
ans[l][j]=SmallAns1[i][j - 1];
}
l++;
}
for(int i=0;i<SmallAns2.length;i++)
{
ans[l]=new int[SmallAns2[i].length];
for(int j=0;j<SmallAns2[i].length;j++)
{
ans[l][j]=SmallAns2[i][j];
}
l++;
}
return ans;
}
public class solution {
public static int[][] subsets(int input[],int index){
if(index>=input.length){
int[][] myAns = new int[1][0];
return myAns;
}
int[][] smallAns = subsets(input,index+1);
int[][] ans = new int[2*smallAns.length][];
int k =0;
int len = smallAns.length;
for(int i=0;i<len;i++){
ans[k] = new int[smallAns[i].length];
for(int j=0;j<smallAns[i].length;j++){
ans[k][j] = smallAns[i][j];
}
k++;
}
for(int i=0;i<len;i++){
ans[k] = new int[smallAns[i].length+1];
ans[k][0] = input[index];
for(int j=1;j<=smallAns[i].length;j++){
ans[k][j] = smallAns[i][j-1];
}
k++;
}
return ans;
}
public static int[][] subsets(int input[])
{
return subsets(input,0);
}
}
We have to sort an Array with random numbers. For this, we need to use this part of code ( HeapSort )
import java.util.ArrayList;
public class HeapSort<E extends Comparable<E>> {
public ArrayList<E> h;
public int SIZE;
public int n;
public HeapSort(int s){
SIZE=s;
n=1;
h=new ArrayList<>(SIZE);
for(int i=0;i<SIZE;i++)
h.add(null);
}
public void Insert(E e){
h.set(n,e);
n++;
// swapping up
if(n!=2){ // more than 1 element
int s=n-1; // last added element
int p=s/2; // its parent
while(s!=1 && LT(s,p)){
swap(p,s);
s=p;
p=p/2;
}
}
}
public boolean Empty(){
return n==1;
}
public E Lesser(){
return h.get(1);
}
public void Delete(){
n--;
h.set(1,h.get(n)); // last element to the root
h.set(n,null);
// swapping down
int ip=1;
int ils=2;
int irs=3;
while(ConditionSwapDown(ip,ils,irs)){
if(Exists(ils) && Exists(irs)){
// two sons
if(LT(ils,ip) || LT(irs,ip)){
// at least one child is lesser than the parent -> swap
if(LT(ils,irs)){
swap(ip,ils); // swapping down left
ip=ils;
ils=ip*2;
irs=ils+1;
}
else{
swap(ip,irs); // swapping down right
ip=irs;
ils=ip*2;
irs=ils+1;
}
}
}
else
// only left son
if(Exists(ils) && !Exists(irs)){
if(LT(ils,ip)){ // left son is lesser than the parent
swap(ip,ils);
ip=ils;
ils=ip*2;
irs=ils+1;
}
}
// else no children and end of swapping down
}
}
public boolean ConditionSwapDown(int p,int l,int r){
// (has 2 children and (parent>left or parent>right)) or
// (has 1 children and parent>left)
return (((Exists(l) && Exists(r)) && (LT(l,p) || LT(r,p)))) ||
(Exists(l) && !Exists(r) && LT(l,p));
}
public boolean Exists(int p){
if(p>=SIZE)
return false;
return h.get(p)!=null;
}
public void swap(int a,int b){
E c=h.get(a);
h.set(a,h.get(b));
h.set(b,c);
}
public boolean LT(int a,int b){ // h[a]<h[b]
return h.get(a).compareTo(h.get(b))<0;
}
#Override
public String toString(){
String r="";
for(int i=1;i<n;i++)
r+=h.get(i)+" ";
return r;
}
public String Print(){
return PrintR(1,"");
}
public String PrintR(int i,String p){
String r=p+h.get(i)+"\n";
if(h.get(i*2)!=null || h.get(i*2+1)!=null){
if(h.get(i*2)!=null)
r+=PrintR(i*2,p+" ");
else
r+=p+" -\n";
if(h.get(i*2+1)!=null)
r+=PrintR(i*2+1,p+" ");
else
r+=p+" -\n";
}
return r;
}
How do we "connect" the two codes? or use our array with HeapSort? For the Array we have done this:
public class P3 {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("Quina llargada tindrĂ la taula? ");
int n = reader.nextInt(); //n=llargada taula
int[] taula = new int[n];
int fi = 100*n;
Random rand = new Random();
//int al = rand.nextInt(fi) + 0;
for (int i = 0; i < taula.length; i++)
taula[i] = rand.nextInt(fi);
System.out.println(Arrays.toString(taula)); }}
Everything is in the HeapSort class, waiting for you to use it:
int[] taula = {4, 2, 8, 1, 2, 3};
System.out.println(Arrays.toString(taula));
// 'heapSort' variable will store ordered list
HeapSort<Integer> heapSort = new HeapSort<>(taula.length+1);
for (Integer i : taula)
heapSort.Insert(i);
System.out.println(heapSort);
I've looked up examples as to how Comparable works and I somewhat understand how it would work but I don't know how I would use it in this situation.
I have an ArrayObject class implements Comparable and imported java.util.*; I also have an ArrayObjectDriver class that is a main method that calls upon methods I've coded in the ArrayObject class. One of the methods that it has to be able to do is to sort the array of objects in the main method. I know you have to use something with .compareTo but I'm not sure how I would do that in the ArrayObject class and call on it in the driver.
EDIT: ArrayObject code
public class ArrayObject implements Comparable
{
private Object[] arr;
private int actualSize;
ArrayObject()
{
arr = new Object[10];
actualSize = 0;
}
ArrayObject(int size)
{
arr = new Object[size];
actualSize = 0;
}
public void add(Object obj)
{
if(actualSize>=arr.length)
expandArray();
arr[actualSize]=obj;
actualSize++;
}
public void expandArray()
{
int newSize = arr.length*2;
Object[] biggerList = new Object[newSize];
for(int i=0; i<arr.length; i++)
{
biggerList[i] = arr[i];
}
arr = biggerList;
}
public void add(Object obj, int index)
{
if(index<actualSize)
{
shiftRight(index);
arr[index]=obj;
actualSize++;
}
// index is between [0 and actualSize)
}
private void shiftRight(int start)
{
for(int i=actualSize; i>start; i--)
{
arr[i] = arr[i-1];
}
arr[start]=null;
}
private void shiftLeft(int start)
{
for(int i=start; i<actualSize-1; i++)
{
arr[i] = arr[i+1];
}
arr[actualSize-1]=null;
}
public Object remove(int index)
{ // returning the object you are removing
// ("the", "is", "are")
if(index>=0&&index<actualSize)
{
Object obj = arr[index];
arr[index] = null;
// arr[index] = arr[actualSize-1];
// what to do about the null?
// Shift to the left by one
shiftLeft(index);
actualSize--;
// ("the", null, "are")
return obj;
}
return null;
}
public Object get(int index)
{
if(index>=0&&index<actualSize)
return arr[index];
return null;
}
public int sizeOfContainer()
{
return arr.length;
}
public int items()
{
return actualSize;
}
public boolean searchArray(Object obj)
{
for(int i=0; i<actualSize; i++)
{
if(arr[i].equals(obj))
return true;
}
return false;
}
public int findObject(Object obj)
{
if(searchArray(obj))
{
for(int i=0; i<actualSize; i++)
{
if(arr[i].equals(obj))
return i;
}
}
return -1;
}
public boolean isItEmpty()
{
if(actualSize == 0)
return true;
return false;
}
public int removeSearch(Object obj)
{
for(int i=0; i<actualSize; i++)
{
if(arr[i].equals(obj))
{
remove(i);
return i;
}
}
return -1;
}
public void clearArray()
{
for(int i=0; i<actualSize; i++)
arr[i] = remove(i);
}
public void printArr()
{
System.out.println("Array Size: " + actualSize);
for(int i=0; i<actualSize; i++)
{
System.out.println(arr[i]);
}
}
}
ArrayObjectDriver code
public class ArrayObjectDriver
{
private static Scanner scanner;
public static void main(String[] args)
{
scanner = new Scanner(System.in);
ArrayObject array = new ArrayObject();
int selection = selectionMenu();
while(selection > 0)
{
if(selection == 1)
{
System.out.println("Enter your object: ");
String str = scanner.next();
array.add(str);
}
else if(selection == 2)
{
System.out.println("Enter your object: ");
String str = scanner.next();
System.out.println("Enter location: ");
int n = scanner.nextInt();
array.add(str, n);
}
else if(selection == 3)
{
System.out.println("Enter location: ");
int n1 = scanner.nextInt();
array.remove(n1);
}
else if(selection == 4)
{
System.out.println("Enter object: ");
String str = scanner.next();
int i = array.removeSearch(str);
System.out.println("Object removed at index " + i);
}
else if(selection == 5)
{
array.clearArray();
System.out.println("Cleared Array");
}
else if(selection == 6)
{
System.out.println("Enter object: ");
String str = scanner.next();
boolean result = array.searchArray(str);
System.out.println("The object was found: " + result);
}
else if(selection == 7)
{
boolean result = array.isItEmpty();
System.out.println("It is empty: + result);
}
else if(selection == 8)
{
array.expandArray();
int i = array.sizeOfContainer();
System.out.println("The new size of the array is: " + i);
}
else if(selection == 9)
{
System.out.println("Enter object: ")
String str = scanner.next();
int i = array.findObject(str);
System.out.println("The object was found at index " + i);
}
else if(selection == 10)
array.printArr();
else if(selection == 11)
{
}
else if(selection == 12)
System.exit(0);
System.out.println("");
selection = selectionMenu();
}
}
private static int selectionMenu()
{
System.out.println("Menu: ");
System.out.println("1. Add object to the end of the list");
System.out.println("2. Add object at a specific location");
System.out.println("3. Remove specific object at a location");
System.out.println("4. Remove specific object that matches name");
System.out.println("5. Empty the array");
System.out.println("6. See if the array contains a certain object");
System.out.println("7. See if the array is empty");
System.out.println("8. Expand your array");
System.out.println("9. Search for an item");
System.out.println("10. Print array");
System.out.println("11. Sort array");
System.out.println("12. Exit");
System.out.println("Enter option: ");
int optionNumber = scanner.nextInt();
return optionNumber;
}
}
Just make a sort method in your ArrayObject class and you can call that when user enters 11.
In ArraysObject:
public void sort(){
Arrays.sort(arr); //This is all you have to call to sort your array arr
}
In your ArrayObjectDriver:
else if(selection == 11)
{
array.sort();
}
The Arrays class has useful methods for searching, manipulating, and sorting arrays including Arrays.sort and Arrays.binarySearch.