bucket size in bucket sort - java

I am trying to write code for bucket sort, but am confused in bucket size of each bucket. My code is below.
input array: {12, 11, 13, 5, 6, 7,10,22,4,16,1,26};
I am passing bucket size of each bucket >3 then I dont get the output in sorted order. It gives perfect ans for bucket size 1 and 2
public void bucsort(int[] arr,int bucketSize){
if(arr.length==0) return;
int max=arr[0];
int min=arr[0];
for(int i=0; i<arr.length;i++){
if(arr[i]<min)
{
min=arr[i];
}
else
max=arr[i];
}
int bucketCount= (max - min) / bucketSize + 1;
List<List<Integer>> buckets = new ArrayList<List<Integer>>(bucketCount);
// int divider= (max+1)/bucketCount;
for (int i = 0; i < bucketCount; i++) {
buckets.add(new ArrayList<Integer>());
}
for (int i = 0; i < arr.length; i++) {
buckets.get((arr[i]-min) / bucketSize).add(arr[i]);
}
int currentIndex = 0;
for (int i = 0; i < buckets.size(); i++) {
Integer[] bucketArray = new Integer[buckets.get(i).size()];
bucketArray = buckets.get(i).toArray(bucketArray);
InsertionSort(bucketArray);
for (int j = 0; j < bucketArray.length; j++) {
arr[currentIndex++] = bucketArray[j];
}
}
}
Is there any relation between no. of buckets and its size ?
I edited my method for max-min function and also debugged the program. There seems to be some mistake in my insertion sort
the code is:
public void InsertionSort(Integer[] arr){
for(int i=1; i<arr.length; i++){
int value=arr[i];
int hole=i;
while(hole>0 && arr[hole-1]>value){
arr[hole]=arr[hole-1];
hole--;
}
arr[hole-1]=value;
}
}
main func
public static void main(String[] args) {
int arr[] = {12, 11, 13, 5, 6, 7,10,22,4,16,1,26};
BucketSort ob = new BucketSort();
ob.bucsort(arr, 5);
printArray(arr);
}
static void printArray(int arr[])
{
int n = arr.length;
for (int i=0; i<n; ++i)
System.out.print(arr[i] + " ");
System.out.println();
}
My output for bucket size 5 : 5 1 4 6 7 10 12 11 13 16 22 26
for size 3: 1 5 4 6 7 12 10 11 13 16 22 26
for size 2: 1 4 5 6 7 10 12 11 13 16 22 26

Finding max-min is wrong...(you have some logical error)
int minValue = array[0];
int maxValue = array[0];
for (int i = 1; i < array.Length; i++) {
if (array[i] < minValue) {
minValue = array[i];
} else if (array[i] > maxValue) {
maxValue = array[i];
}
}
On your code:
1 4 3
min 1 1 1
max 1 4 3
This will be the correct implemenation
for (i = 1; i < length; i++) {
j = i;
while (j > 0 && arr[j - 1] > arr[j]) {
tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
j--;
}
}
I will debug your code when I get time..

In your InsertionSort method you do
int value=arr[i];
int hole=i;
while(hole>0 && arr[hole]>value){
At this point arr[hole] will always equal value, so you never get into the while loop. So nothing gets sorted. For small bucket sizes, you may be lucky that it doesn’t matter. For bucket size 1, it certainly doesn’t. Even for bucket size 2 you have a single error in the sorting. I get:
1 4 5 6 7 10 12 11 13 16 22 26
12 comes before 11 because those two numbers end up in the same bucket and don’t get sorted.
I took this from your comment: while (hole > 0 && arr[hole - 1] > value) {. On your request, now the method looks like this:
public void insertionSort(Integer[] arr) { // renamed to small i since it’s a method
for (int i = 1; i < arr.length; i++) {
int value = arr[i];
int hole = i;
while (hole > 0 && arr[hole - 1] > value) {
arr[hole] = arr[hole - 1];
hole--;
}
arr[hole] = value;
}
}
Now I get correct sorting with all bucket sizes from 1 to 19. If you still have a problem, there must be something we are not doing the same way.
It’s an aside, but as has been mentioned a couple of times, there is a bug in your code for finding max. I tried this input:
int arr[] = { 3, 10, 4 };
I get a maxof 4 (expected: 10) and then a java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 at this line:
buckets.get((arr[i]-min) / bucketSize).add(arr[i]);

Related

Why am i getting wrong sorting result in Selection sort for specific this input only?

What wrong am I doing in this sort? I'm getting the wrong output for this input only.
public class SelectionSort {
public void sort (int nums[]){
for(int i = 0; i < nums.length - 1; i ++){
int min_index = i;
for(int j = i + 1; j < nums.length; j ++){
if(nums[j] < nums[min_index]){
min_index = j;
int temp = nums[min_index];
nums[min_index] = nums[i];
nums[i] = temp;
}
}
}
}
public void printArr(int nums[]){
for(int i = 0; i < nums.length; ++i){
System.out.println(nums[i]);
}
}
public static void main(String args[]){
int nums[] = {10,22,34, 45, 50, 60, 8, 12};
SelectionSort obj = new SelectionSort();
obj.sort(nums);
obj.printArr(nums);
}
}
Wrong Output
8 12 10 22 34 45 50 60
Correct Output should be
8 10 12 22 34 45 50 60
You're swapping every time you find a new minimum:
if(nums[j] < nums[min_index]){
min_index = j;
int temp = nums[min_index];
nums[min_index] = nums[i];
nums[i] = temp;
}
Instead, swap only when you've found the lowest minimum: Move the swap after the j loop.
Learning how to debug code is an essential skill. Java was designed to support debugging. Use an IDE (I recommend IntelliJ) and learn how to use its debugger.

Print Pascal's Triangle using recursion

I'm trying to develop a program that prints out Pascal's Triangle using recursion. Here are my codes:
public class PascalTriangle {
public static int[] computePT(int k) {
int[] pt = new int[k + 1];
if (k == 0) {
pt[0] = 1;
return pt;
} else {
int[] ppt = computePT(k - 1);
pt[0] = pt[k] = 1;
for (int i = 1; i < ppt.length; i++) {
pt[i] = ppt[i - 1] + ppt[i];
}
}
return pt;
}
}
public class PascalTriangleDriver {
public static void main(String args[]) {
int k = 10;
int arr[] = PascalTriangle.computePT(k);
for (int i = 0; i < arr.length; i++)
System.out.print(arr[i] + " ");
System.out.println();
}
}
The code runs perfectly, however my issue is that I want to modify my PascalTriangle code (not the PascalTriangleDriver code) such that when k=10, for example, it prints out:
1 9 36 84 126 126 84 36 9 1
instead of:
1 10 45 120 210 252 210 120 45 10 1
You seem to have made an off-by-1 error. One simple way to solve this is to write another method that calls your original method with k-1:
// this is your original method, just renamed:
private static int[] computePTImpl(int k) {
int[] pt = new int[k + 1];
if (k == 0) {
pt[0] = 1;
return pt;
} else {
int[] ppt = computePT(k - 1);
pt[0] = pt[k] = 1;
for (int i = 1; i < ppt.length; i++) {
pt[i] = ppt[i - 1] + ppt[i];
}
}
return pt;
}
// you will call this method:
public static int[] computePT(int k) {
return computePT(k - 1);
}
Alternatively, you can actually fix your code by replacing ks with k-1s:
public static int[] computePT(int k) {
int[] pt = new int[k]; // note the change
if (k == 1) { // note the change
pt[0] = 1;
return pt;
} else {
int[] ppt = computePT(k - 1);
pt[0] = pt[k - 1] = 1; // note the change
for (int i = 1; i < ppt.length; i++) {
pt[i] = ppt[i - 1] + ppt[i];
}
}
return pt;
}
Note that we don't change the recursive call because if we did, we would be saying that the k-th row of Pascal's triangle depends on the k-2-th row, which is not true.
You can iteratively populate an array of binomial coefficients as follows: the first row and column are filled with ones, and all other elements are equal to the sum of the previous element in the row and column.
T[i][j] = T[i][j-1] + T[i-1][j];
You can create two methods: one returns a 2d array containing a triangle, and the second returns the base of that triangle. It is more useful for clarity.
Output:
Triangle:
1 1 1 1 1 1 1 1 1 1
1 2 3 4 5 6 7 8 9
1 3 6 10 15 21 28 36
1 4 10 20 35 56 84
1 5 15 35 70 126
1 6 21 56 126
1 7 28 84
1 8 36
1 9
1
Base:
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
Code:
public static void main(String[] args) {
int n = 10;
System.out.println("Triangle:");
int[][] arr = binomialTriangle(n);
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++)
if (arr[i][j] > 0)
System.out.printf("%2d ", arr[i][j]);
System.out.println();
}
int[] base = binomial(arr);
System.out.println("Base:");
System.out.println(Arrays.toString(base));
}
public static int[][] binomialTriangle(int n) {
// an array of 'n' rows
int[][] arr = new int[n][];
// iterate over the rows of the array
for (int i = 0; i < n; i++) {
// a row of 'n-i' elements
arr[i] = new int[n - i];
// iterate over the elements of the row
for (int j = 0; j < n - i; j++) {
if (i == 0 || j == 0) {
// elements of the first row
// and column are equal to one
arr[i][j] = 1;
} else {
// all other elements are the sum of the
// previous element in the row and column
arr[i][j] = arr[i][j - 1] + arr[i - 1][j];
}
}
}
return arr;
}
public static int[] binomial(int[][] arr) {
int[] base = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
// the last element in the row
base[i] = arr[i][arr[i].length - 1];
}
return base;
}
See also: Finding trinomial coefficients using dynamic programming

Recursive number triangle

I'm having trouble trying to get the correct numbers to be in the correct position, my idea seems to be correct but the printing is incorrect.
static int plotTri1(int n, int i) {
if (n > 0) {
plotTri1(n - 1, n + i);
i += n;
for (; 0 < n; n--) {
System.out.printf("%3d", (i--));
}
System.out.println();
}
return n;
}
My current solution prints out the following:
Given n = 5 and i = 0
15
14 13
12 11 10
9 8 7 6
5 4 3 2 1
The desired solution is:
Given n = 5 and i = 0
1
3 2
6 5 4
10 9 8 7
15 14 13 12 11
Looking for help that will lead me to the desired solution
why do you use recursive function?
static void plotTri2(int n) {
int k=1 ;
for (int i=0; i<n; i++) {
for (int j=0; j<=i; j++) {
System.out.printf("%3d", new Object[] {new Integer(k-j)} );
}
k+= i+2 ;
System.out.println("");
}
}
plotTri2(5) ;
Here is an approach which worked for me. The basic idea is to print from the starting number in each row down the the last number in that row, recursively.
public static void triangle(int n, int num) {
if (n == 0) return;
triangle(n - 1, num - n);
System.out.println("\n");
for (int i=0; i < n; ++i) {
if (i > 0) System.out.print(" ");
System.out.print(num - i);
}
}
public static void main(String args[]) {
triangle(5, 15);
}
Demo
How about having the previous call return something? Here's one idea:
static int[] f(int n){
if (n == 0){
int[] firstRange = new int[]{1,1};
return firstRange;
}
int[] range = f(n - 1);
for (int i=range[0]; i<=range[1]; i++) {
System.out.printf("%3d", i);
}
System.out.println();
int[] nextRange = new int[]{range[1] + 1, 2 * range[1] - range[0] + 2};
return nextRange;
}

How to check max number of elements that are spaced evenly?

I have an array and my goal is to find out how many are spaced by multiples of 11. The array is NOT sorted.
Such as [27, 16, 52, 84], this would return 2
[1, 55, 66, 33] should return 3.
[99, 8, 52, 32] should return 0
Currently what I have is to basically run through for-each element in the array, check every other element with multiplying by 11. But this leaves me at a O(n²) runtime, anyway I can optimize this?
static int eval(int [] a) {
int i, j, k, counter = 0;
for (i = 0; i < a.length; i++) {
for (j = 0; j < a.length; j++) {
if (i != j) {
for (k = -9; k < 10; k++) {
if (a[i] == a[j] + k*11) {
counter++;
break;
}
}
}
}
}
//if found nothing, will return 0, if found 1 matching,
//it should be 2 numbers that share this 11-difference.
return counter : counter == 0? 0: counter + 1;
}
Thanks!
It's not entirely clear what the output is supposed to be for, say, [11, 22, 34, 45]. I'm interpreting the question as asking for the size of the largest subset of the input where all differences between elements of the subset are multiples of 11, and where size-1 subsets don't count.
All inputs with the same residue mod 11 are spaced by multiples of 11, so we only need to count how many ints in the input have each possible value of i % 11. This takes time linear in the size of the input.
static int eval(int[] a) {
int[] inputsPerResidue = new int[11];
for (int i : a) {
inputsPerResidue[i % 11]++;
}
int maxGroupSize = 0;
for (int groupSize : inputsPerResidue) {
if (groupSize > 1 && groupSize > maxGroupSize) {
maxGroupSize = groupSize;
}
}
return maxGroupSize;
}
You would need 2 loops to accomplish this. Calculate the difference between every element, and if that number is a multiple of 11, increment the counter. Return half the counter, as if you hit a multiple of 11 between two elements, you will end up hitting the same two elements again later in the loop:
static int eval(int [] a) {
int counter = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
if (i != j && Math.abs(a[i] - a[j]) % 11 == 0) {
counter++;
}
}
}
return counter / 2;
}

What is wrong with this Selection Sort Code?

I was asked to make a selection sort algorithm, but it's not working and I don't know why. Here's the code:
int count = 0;
int count2;
int min;
int size = scan.nextInt();
int temp = 0;
int[] numbers = new int[size];
while (count < size) {
numbers[count] = scan.nextInt();
count ++;
}
count = 0;
while (count < size) {
count2 = size;
min = numbers[count];
while (count < count2) {
count2 --;
if (numbers[count2] < numbers[min]) {
min = count2;
}
}
temp = numbers[temp];
numbers[temp] = numbers[count];
numbers[count] = temp;
count ++;
}
count = 0;
while (count < size) {
System.out.println(numbers[count]);
count ++;
}
}
Input:
10
1
0
2
9
3
8
4
7
5
6
Output:
1
2
9
8
3
3
8
4
7
4
In while loop you try to use numbers[0] element as the index of numbers[] numbers[min]
min = numbers[count]; \\min is value of first element of numbers[]
while (count < count2) {
count2 --;
if (numbers[count2] < numbers[min]) { \\ you try to use value of numbers[0] element as index of numbers[] aray.
min = count2;
}
replace if (numbers[count2] < numbers[min]) with if (numbers[count2] < min)
temp = numbers[temp];
numbers[temp] = numbers[count];
numbers[count] = temp;
count ++;
Take a second look at this code.
If you ran this where the first input was 11, it would error with index out of range.
In particular, what do you plan to accomplish with temp = numbers[temp]? You're assigning temp to essentially an arbitrary number, because numbers[0] could be anything.
The fact that you're getting duplicate values in your output (that aren't in your input) means that your swap doesn't work, thus:
temp = numbers[temp];
numbers[temp] = numbers[count];
numbers[count] = temp;
is wrong.
It should be min, not temp:
temp = numbers[min];
numbers[min] = numbers[count];
numbers[count] = temp;
Here is an algorithm that works and make use of a great functionality of for in java. To go through an array or a list you can do for (int current : array) This is far more convinient than using while or for like you do.
int min;
int mem = 0;
int size = 11;
int [] numbers = {10, 1, 0, 2, 9, 3, 8, 4, 7, 5, 6};
for (int i=0; i<size-1; i++){
min =i;
for(int j=i+1; j<size; j++){
if (numbers[j]<numbers[min]){
min = j;
}
}
// swap
mem= numbers[i];
numbers[i] = numbers[min];
numbers[min] = mem;
}
for (int toPrint : numbers){
System.out.println(toPrint);
}
}

Categories

Resources