Java quicksort.Identify changes in the partition while loop - java

What changes do i need to make to the partition loop if inside the partition method i want to initialise l=start or l=start+1 and end =end-1 ? If these values are initialised to l=start-1; and r=end; than the loop works fine but it does not satisfy the invariant.Any ideas?
public class qs {
private qs(){}
/**
* Sort an array in ascending order
* #param arr array to sor */
public static void quickSort(int[] arr){
qs(arr, 0, arr.length);
}
/**
* Sort a region of an array in ascending order.
* Elements outside the given region are unchanged.
* requires: 0 <= start <= end <= arr.length
* #param arr array to sort
* #param start start of region (inclusive)
* #param end end of region (exclusive)
*/
private static void qs(int[] arr, int start, int end){
if (end <= start+1){ //region of length 0 or 1
return;
}
int x = arr[start];
int p = partition(arr, start+1, end, x);
//now swap arr[start] with arr[p-1]
arr[start] = arr[p-1];
arr[p-1] = x;
qs(arr, start, p-1);
qs(arr, p, end);
}
/**
* Partition a region of an array.
* Rearranges elements in region so that small ones
* all have smaller indexes than the big ones.
* Elements outside the region are unchanged.
* requires: 0 <= start <= end <= arr.length
* #param arr array to partition
* #param start start of region (inclusive)
* #param end end of region (exclusive)
* #param x pivot - "small" and "big" are <x, >=x.
* #return start index (inclusive) of big elements
* in region after partition.
*/
private static int partition(
int[] arr, int start, int end, int x)
{
int l = start ;
int r = end-1;
while (l<r) {
while(++l< r && arr[l] < x);
while(--r > l && arr[r] > x);
if(l >= r) // if pointers cross,
break; // partition done
else {
int temp;
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
}
}
return l;
}
public static void main(String[] args) {
int[] a = {15,8,4,8,9,6,};
quickSort(a);
for (int i = 0; i < a.length; i++){
System.out.print(" "+a[i]);
}
}
}

Pivot should be Middle point, not the starting of the array.
int x = arr[start];
Replace this line with this...
int x = arr[(start+end)/2]

Related

CopyOf returning array

jump is an array that has been initialised.
FunctionMonius3.difRandoms method returns an array
jump = FunctionMonius3.difRandoms(posMonius.length, lines * col, generator);
or
jump = Arrays.copyOf(FunctionMonius3.difRandoms(posMonius.length, lines * col, generator), v.length);
Does the first option just creates a reference that is destroyed when the method FunctionMonius3.difRandoms ends or is it ok?
* #param n - number of array elements
* #param sup - max value
* #param g - generator
public static int[] difRandom (int n, int sup, Random g){
int[] result = new int [n];
int i = 0;
while (i < result.length) {
int random = g.nextInt(sup) + 1;
if (!contidoEmParte(aleatorio,result,i)){
result[i] = random;
i++;
}
}
return result;
}

time complexity - Binary Indexed Tree

I am writing a binary indexed tree. As documentation, it requires nlogn time to pre process. But I am not able to understand why.
In my case I am constructing the tree from the Array, which should take 2n time, as first time traversing the array once to make it a Binary tree and then to update sum I am again traversing the tree in POST order fashion. so total 2n, not nlogn.
Can anybody explain why it needs nlogn time to pre-process the binary indexed tree.
public class BITree {
private class BTN {
int data;
int index;
BTN left,right;
public BTN(int data) {
this.data = data;
}
}
BTN head = null;
public BTN toBT(int[] arr,int start,int end){
if(start <= end){
int mid = start + (end - start)/2;
BTN btn = new BTN(arr[mid]);
btn.index = mid+1;
btn.left = toBT(arr,start,mid-1);
btn.right = toBT(arr,mid+1,end);
return btn;
}
return null;
}
public int sumAtIndex(BTN btn,int index){
int sum = 0;
if(index < btn.index)
sum += sumAtIndex(btn.left,index);
else if(index > btn.index) {
sum += btn.data + sumAtIndex(btn.right, index);
}
if(btn.index == index)
return btn.data + sum;
return sum;
}
public int replaceSum(BTN btn){
if(btn == null){
return 0;
}
int l = replaceSum(btn.left);
int r = replaceSum(btn.right);
int sum = btn.data + l + r;
btn.data += l;
return sum;
}
void inOrder(BTN btn){
if(btn != null) {
inOrder(btn.left);
System.out.print((btn.index+":"+btn.data)+",");
inOrder(btn.right);
}
}
public static void main(String[] args) {
int[] arr = {5,1,6,4,2,3,3};
BITree s2 = new BITree();
BTN btn = s2.toBT(arr,0,arr.length-1);
s2.replaceSum(btn);
s2.inOrder(btn);
System.out.println();
System.out.println(s2.sumAtIndex(btn,3));
}
}
This question is a duplicate of :Is it possible to build a Fenwick tree in O(n)?
#Thilo , Thanks for pointing out the optimized way for preprocessing the the BIT. Which can be done in O(n) time.
https://en.wikipedia.org/wiki/Talk:Fenwick_tree
https://stackoverflow.com/a/31070683/3080158
#SanketMakani, Thanks for sharing the link, it explains the BIT very well.
here is the working code, with O(n) pre processing time.
package com.rabin;
import java.util.StringJoiner;
/**
*
*/
public class BITree {
/**
* O(logn)
* #param arr
* #param index
* #param val
*/
void update(int arr[],int index, int val)
{
index++;
for(; index <= arr.length-1; index += index&-index)
arr[index] += val;
}
/**
* O(logn)
* #param arr
* #param noOfElements
* #return
*/
int query(int[] arr,int noOfElements)
{
int sum = 0;
for(; noOfElements > 0; noOfElements -= noOfElements&-noOfElements)
sum += arr[noOfElements-1];
return sum;
}
/**
* O(n)
* #param arr
*/
void toBIT(int[] arr){
int n = arr.length;
for(int i=1;i<=n;i++){
int j = i+ (i & -i);
if(j <= n)
arr[j-1] += arr[i-1];
}
}
static String arrayToString(int[] arr){
StringJoiner sj = new StringJoiner(",","[","]");
for(int i = 0; i< arr.length ;i++){
sj.add(String.valueOf(arr[i]));
}
return sj.toString();
}
public static void main(String[] args) {
int[] arr = {5,1,6,4,2,3,3};
BITree bit = new BITree();
System.out.println("Original Array:" +arrayToString(arr));
bit.toBIT(arr);
System.out.println("BIT Array:" +arrayToString(arr));
System.out.println("Sum of first 5 nos : "+ bit.query(arr,5));
bit.update(arr,0,8);
System.out.println("Sum of first 5 nos after update : "+ bit.query(arr,5));
}
}
#RBanerjee nicely written code, It is good to implement the BIT with one additional index, which helps in code comprehension. Plus it also signifies one additional thing - the least significant 1 bit from the BIT index indicates as to how many elements does the particular index stores. For e.g. index = 2 (010) can signify index 2 in BIT holds the values of 2 elements, similarly 4 (100) for 4, 6 (110) stores 2 values (namely, index 5 and 6) and so on.
Additionally, in your update method you aren't updating the value per se. You are adding the given value. Which I do not think signifies the meaning of update. It is a very subjective discussion, but I think of it as an update and not an increment. So, if the index 5 originally holds value 2, and when I want to update it to -1, it means the value after the update at index 5 is -1 and not 1.
As an extra step, it is good to provide a way to query the ranges in the array. For e.g. what is the value between indices 2 and 5 (inclusive).
<!-- language: java -->
package DataStructureImplementation;
import java.util.StringJoiner;
public class BinaryIndexedTree {
private final int[] bit;
private final int[] nums;
private final int n;
public BinaryIndexedTree(int[] nums) {
n = nums.length;
bit = new int[n + 1];
this.nums = nums;
System.arraycopy(nums, 0, bit, 1, nums.length);
build();
}
/**
* Builds a binary indexed tree in O(n) time.
*/
private void build() {
int j;
for (int i = 1; i <= n; ++i) {
j = i + (i & -i);
if (j <= n) bit[j] += bit[i];
}
}
/**
* Updates an indexed item in the original array to the given value.
* Also updates the values in the 'BIT' in O(logn) time.
* #param index - index of the item to update
* #param value - value to update to
*/
public void update(int index, int value) {
int diff = value - nums[index];
nums[index] = value;
index++;
while (index <= n) {
bit[index] += diff;
index += (index & -index);
}
}
/**
* Queries the sum of the first 'K' indices in the original array in O(logn) time.
* #param k - the number of items to aggregate.
* #return - the sum of first 'K' numbers in the original array.
* #throws Exception - if 'K' is out of bounds.
*/
public int query(int k) throws Exception {
if (k < 0 || k > n) throw new Exception("Invalid query range : " + k);
int sum = 0;
while (k > 0) {
sum += bit[k];
k -= (k & -k);
}
return sum;
}
/**
* Queries the sum of numbers from the original array between index1 and index2 (inclusive) in O(logn) time.
* #param index1 - left index.
* #param index2 - right index.
* #return - the sum of numbers between the given ranges.
* #throws Exception - if range is out of bounds.
*/
public int queryRange(int index1, int index2) throws Exception {
return query(index2 + 1) - query(index1);
}
/**
* Helper method to print the array contents.
* #param nums - the array to print.
* #return - the contents of the array as string.
*/
static String arrayToString(int[] nums){
StringJoiner stringJoiner = new StringJoiner(",","[","]");
for (int n : nums) {
stringJoiner.add(String.valueOf(n));
}
return stringJoiner.toString();
}
public static void main(String[] args) throws Exception {
int[] nums = {5,8,5,4,2,3};
BinaryIndexedTree binaryIndexedTree = new BinaryIndexedTree(nums);
System.out.println("Original Array : " + arrayToString(nums));
System.out.println("BIT Array : " + arrayToString(binaryIndexedTree.bit));
System.out.println("Sum of first 5 nos : " + binaryIndexedTree.query(5));
binaryIndexedTree.update(4,-1);
System.out.println("Original Array after update : " + arrayToString(nums));
System.out.println("BIT Array after update : " + arrayToString(binaryIndexedTree.bit));
System.out.println("Sum of first 5 nos after update : " + binaryIndexedTree.query(5));
System.out.println("Sum of numbers in range 2-5 : " + binaryIndexedTree.queryRange(2, 5));
}
}

Based on what is a sorting algorithm considered efficient?

I have implemented a sorting algorithm to sort an un-ordered integer array. If I throw in a 100,000-element array, it took roughly 10,500 mil sec to return. Is my algorithm fast or very slow?. Below is the code.
public static void sort(int[] array) {
int lastItem = array[array.length - 1];
int length = array.length;
for (int j = 0; j < array.length; j++) {
for (int i = 0; i < length; i++) {
if (array[i] > lastItem) {
array[length-1] = array[i];
array[i] = lastItem;
lastItem = array[length - 1];
}
}
length--;
if (length > 1) lastItem = array[length - 1];
}
}
You algorithm is using bubble sort which takes o(n^2). For larger input it might be slow. Why not use quick sort which will achieve the result you desire in O(nlogn)?
Here is some code, please note that it might be better to select the pivot as mid-element.
/**
* o(nlogn) - high probability otherwise o(n SQUARE)
*
*
* Choose a pivot value. We take the value of the middle element
* as pivot value, but it can be any value, which is in range of
* sorted values, even if it doesn't present in the array.
*
* Partition. Rearrange elements in such a way, that all elements
* which are lesser than the pivot go to the left part of the array
* and all elements greater than the pivot, go to the right part
* of the array. Values equal to the pivot can stay in any part
* of the array. Notice, that array may be divided in non-equal parts.
*
* Sort both parts. Apply quicksort algorithm recursively to the left
* and the right parts.
*
* #param input
*/
public void quickSort(int[] input, int start, int end){
if( start < end ){
int pindex = findParition(input, start, end);
quickSort(input, start, pindex-1);
quickSort(input, pindex+1, end);
}
}
/**
* findParition for quick sort
* #param input
* #param start
* #param end
* #return
*/
private int findParition(int[] input, int start, int end) {
int pivot = input[end];
int pindex = start;
for( int i = start; i < end; i++){
if( input[i] <= pivot ){
int temp = input[pindex];
input[pindex] = input[i];
input[i] = temp;
pindex++;
}
}
int temp = input[pindex];
input[pindex] = input[end];
input[end] = temp;
return pindex;
}
Click here to compare various sorts.

Quicksort partition algorithm loop invariants defined in partition method

I implemented the partition method in the quicksort algorithm but i dont know if it satisfies the loop invariant that they were given to me.
public class qs {
private qs(){}
/**
* Sort an array in ascending order
* #param arr array to sor */
public static void quickSort(int[] arr){
qs(arr, 0, arr.length);
}
/**
* Sort a region of an array in ascending order.
* Elements outside the given region are unchanged.
* requires: 0 <= start <= end <= arr.length
* #param arr array to sort
* #param start start of region (inclusive)
* #param end end of region (exclusive)
*/
private static void qs(int[] arr, int start, int end){
if (end <= start+1){ //region of length 0 or 1
return;
}
int x = arr[start];
int p = partition(arr, start+1, end, x);
//now swap arr[start] with arr[p-1]
arr[start] = arr[p-1];
arr[p-1] = x;
qs(arr, start, p-1);
qs(arr, p, end);
}
/**
* Partition a region of an array.
* Rearranges elements in region so that small ones
* all have smaller indexes than the big ones.
* Elements outside the region are unchanged.
* requires: 0 <= start <= end <= arr.length
* #param arr array to partition
* #param start start of region (inclusive)
* #param end end of region (exclusive)
* #param x pivot - "small" and "big" are <x, >=x.
* #return start index (inclusive) of big elements
* in region after partition.
*/
private static int partition(
int[] arr, int start, int end, int x)
{
int l = start-1 ;
int r = end;
while (true) {
while(++l< r && arr[l] < x);
while(r-- > l && arr[r] > x);// find smaller item
if(l >= r) // if pointers cross,
break; // partition done
else {
int temp;
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
}
}
return l;
}
public static void main(String[] args) {
int[] a = {15,8,4,8,9,6,4,1,2,5,6,4};
quickSort(a);
for (int i = 0; i < a.length; i++){
System.out.print(" "+a[i]);
}
}
}
Your code should work except one problem. Pivot that you are selecting is the starting point of the array rather than a middle point of the array. So instead assigning
int x = arr[start];
You better assign it to
int x = arr[(start + end)/2];
Your code must work.

How to convert a 1d array to 2d array?

Say, I have a 1d array with 30 elements:
array1d[0] = 1
array1d[1] = 2
array1d[2] = 3
.
.
.
array1[29] = 30
How to convert the 1d array to 2d array?
Say 10x3?
array2d[0][0] = 1 array2d[0][1] =2 array2d[0][2] =3
.
.
.
array2d[9][0] = 28 array2d[9][1] =29 array2d[9][2] =30
Should I use a for loop?
But I cannot work it out.
Without writing any code for you...
Think about how big your 2d array needs to be.
Recognize that you'll need to loop over the contents of your source array to get each value into your destination array.
So it will look something like...
Create a 2d array of appropriate size.
Use a for loop to loop over your 1d array.
Inside that for loop, you'll need to figure out where each value in the 1d array should go in the 2d array. Try using the mod function against your counter variable to "wrap around" the indices of the 2d array.
I'm being intentionally vague, seeing as this is homework. Try posting some code so we can see where you get stuck.
int array2d[][] = new int[10][3];
for(int i=0; i<10;i++)
for(int j=0;j<3;j++)
array2d[i][j] = array1d[(j*10) + i];
Here a generic function to convert from 1D -> 2D array:
public int[][] monoToBidi( final int[] array, final int rows, final int cols ) {
if (array.length != (rows*cols))
throw new IllegalArgumentException("Invalid array length");
int[][] bidi = new int[rows][cols];
for ( int i = 0; i < rows; i++ )
System.arraycopy(array, (i*cols), bidi[i], 0, cols);
return bidi;
}
If you want to do the contrary (2D -> 1D), here the function:
public int[] bidiToMono( final int[][] array ) {
int rows = array.length, cols = array[0].length;
int[] mono = new int[(rows*cols)];
for ( int i = 0; i < rows; i++ )
System.arraycopy(array[i], 0, mono, (i*cols), cols);
return mono;
}
public class Test{
public static void main(String[] argv)
{
int x,y;
for(int num =0; num<81;num++)
{
if((num % 9)>0)
{
x = num/9;
y = num%9;
}else
{
x = num/9;
y = 0;
}
System.out.println("num ["+num+"]---["+x+","+y+"]");
}
}
}
/* Replace 9 by the size of single row of your 2D array */
You often will find the same problem: how to manipulate 2D array as 1D array.
I wrote a generic class Grid, that lets access objects by index or by (x,y).
See the following class and understand the idea behind it. :)
You could use the following class for data manipulation as 2D array or 1D array. Here is the code for that I wrote and use.
/**
* Grid represents a 2 dimensional grid.
*
* #param <E> the type of elements in this grid
*/
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
public class Grid<E>
{
private int size ;
private int width ;
private int height ;
private List<E> elements;
public int getCapacity()
{
return getWidth() * getHeight();
}
/**
* #return number of elements in grid. Null is also an element.
*/
public int getSize()
{
return getElements().size();
}
/**
* #param sideSize size of the grid side
*/
public Grid(int sideSize)
{
this(sideSize,sideSize);
}
/**
* #param width of the grid
* #param height of the grid
*/
public Grid(int width, int height)
{
this.width = width ;
this.height = height;
this.elements = new ArrayList<E>(
Collections.nCopies(width*height, (E)null));
}
public int getHeight()
{
return height;
}
public int getWidth()
{
return width;
}
/**
* #return all elements of the grid
*/
public List<E> getElements()
{
return elements;
}
/**
* #return iterator for a grid
*/
public Iterator<E> iterator()
{
return getElements().iterator();
}
/**
* Returns the element at position (x,y).
*
* #return the element at position (x,y)
*/
public E get(int x, int y)
{
return getElements().get(
idx(x,y));
}
/**
* Returns the element at index idx.
*
* #return the element at given index
*/
public E get(int idx)
{
return getElements().get(idx);
}
/**
* Puts an element to the position idx
*
* #param element to be added
*
* #param x position x to add element to
*
* #param y position y to add element to
*/
public void put(int x, int y, E element)
{
put(idx(x,y), element);
}
/**
* Puts an element to the position idx
*
* #param element to be added
*
* #param idx to add element at
*/
public void put(int idx, E element)
{
getElements().add(idx, element);
}
/**
* Returns the x coordinate from the index.
*
* #return x coordinate of the index
*/
public int x(int idx)
{
return idx % getHeight();
}
/**
* Returns the y coordinate from the index.
*
* #return y coordinate of the index
*/
public int y(int idx)
{
return (idx - idx % getHeight()) / getHeight();
}
/**
* Returns index of element at (x,y).
*
* #return index of the coordinates
*/
public int idx(int x, int y)
{
return y*getHeight() + x;
}
}
Here is how to use the class (see a test example):
public class TestGrid
{
public static final int SIZE = 10;
public static final Integer el1 = new Integer(2);
public static final Integer el2 = new Integer(3);
public static final Integer el3 = new Integer(3);
public static void main(String[] args)
{
Grid<Integer> grid = new Grid<>(SIZE);
assert grid.getCapacity() == SIZE*SIZE ;
assert grid.idx(0,0) == 0 ;
assert grid.idx(1,0) == 1 ;
assert grid.idx(0,1) == 10;
assert grid.idx(6,1) == 16;
assert grid.idx(9,9) == 99;
grid.put(1, el1);
assert grid.get(1) == el1 : grid.get(1);
grid.put(0, 1, el2);
assert grid.get(0,1) != el1 && el1 != el2 && grid.get(0,1) == el2;
grid.put(15, el3);
assert grid.get(5,1) == el3;
}
}
This is just a pseudo code. ROWS represent the length of the 2d array, and COLUMNS represent the length of the 1st element in the array
for(i=0; i<ROWS; i++)
for(j=0; j<COLUMNS; j++)
array2d[i][j] = array1d[ (i*COLUMNS) + j];
package com.vikrant;
import java.util.Arrays;
public class TwoD {
public static void main(String args[])
{
int a[][]=new int[4][3];
int d[]={10,20,30,40,50,60,70,80,90,100,110,120};
int count=0;
for(int i=0;i<4;i++)
{
for(int j=0;j<3;j++)
{
if(count==d.length) break;
a[i][j]=d[count];
count++;
}}
int j=0;
for (int i = 0; i<4;i++)
{
for(j=0;j<3;j++)
System.out.println(a[i][j]);
}
}}
THIS DOES THE WORK
int[] oneDArray = new int[arr.length*arr.length];
//Flatten 2D array to 1D array...
int s = 0;
for(int i = 0; i < arr.length; i ++)
for(int j = 0; j < arr.length; j ++){
oneDArray[s] = arr[i][j];
s++;
}
You can't "convert" a 1D array to a 2D array, but an array can be multi-dimensionnal when you declare it.
int myArray2d[][] = new int[10][3]

Categories

Resources