Interpreting Big O Loops and arrays - java

So, I know I'm going wrong in my thinking but my answer for all three pieces of code is that they are O(n^2).
Can someone tell me if I'm wrong?
If yes, can you help me think through how to solve similar problems. Thank you in advance!
public static int firstLoop(int[] arr) {
int sum = 0; int n = arr.length;
int limit = n * n;
for ( int j = 0; j < limit; j += 2 ) {
sum = (sum + arr[j / n] ) % 100;
}
return sum; }
public static int withLoop(int[] arr) {
int sum = 0; int n = arr.length;
int j = 1;
int limit = n * n;
for ( j= limit - 1; j > 0; j /= 2 ) {
sum = (sum + arr[j / n] ) % 100; }
return sum; }
public static int fwLoop(int[] arr)
{ int sum = 0;
int n = arr.length;
int limit = n * n;
for ( int k = 0; k < limit; k += 2 ) {
int t = 1; for ( j = limit - 1; j > 0; j /= 2 ) {
t = (t + arr[j / n] ) % 100;
} sum = (sum + t + arr[k / n] ) % 200;
} return sum;
}

The first piece of code runs in O(n^2) as you rightly said because limit is of size n^2
The second however does j/=2 which divides the length of limit each time by 2, therefore the loop will run for k times where k=log(n^2) = 2log(n) therefore it is of O(log(n)) order
The third is a combination of first and the second, it runs in O((n^2)*log(n)) time

Related

How to increment an array with a nested for loop?

There must be a more elegant way to do the following:
for(int i = 0; i < subsets.length-10; i++) {
sample = (int)subsets[i];
int y = (sample
+ ((int)(subsets[i+1]))
+ ((int)(subsets[i+2]))
+ ((int)(subsets[i+3]))
+ ((int)(subsets[i+4]))
+ ((int)(subsets[i+5]))) / 6;
}
Basically, it adds the next 5 values for 'subsets' incrementally. How to use a nested for loop to use a single formula that means I can increase how many times it adds the next value and then divide by that many also to get an average.
Something like?:
y = (sample + ((int)(subsets[i++n]))/n
where n is number of times it incrementally adds the next value
any ideas?
y = Arrays.stream(subsets, i, i+6).sum()/6;
This Stream should give you all the y values:
IntStream.range(0, subsets.length - 10)
.map(i -> Arrays.stream(subsets, 0, 6).sum() / 6);
You could also use IntStream.average() instead of calculating it yourself if a double is ok.
sample is not special, it's only i+0 so you don't have to isolate it. You can try:
for(int i = 0; i < subsets.length-10; i++) {
int y = 0;
for(int j=i;j<i+n-1;j++) {
y += (int)subsets[j];
}
y = y / n;
}
Your approach of an nested loop is correct. Try something like this:
for ( int i = 0; i < subsets.length - 10; i++ )
{
sample = subsets[ i ];
int y = sample;
for ( int k = i; k < i + 5; k++ )
{
y += subsets[ k ];
}
y /= 6;
}
int sample;
for (int i = 0; i < subsets.length - 10; i++) {
sample = (int) subsets[i];
for (int j = i; (j < i + 6) && (j < subsets.length -10); j++) {
sample += subsets[i];
}
int y = sample / 6;
}

Search if there exist a row, in a 2D array, that its sum equals the sum of two other rows in the same 2D Array

I am trying to iterate throughout 2D Array to find a row that its sum equals the sum of two other rows in the same 2D array.
I am having hard time figuring out how to compare before I can reset sum2 and sum3 to zero;
* for sum2: its sum will be just the sum at row (n-1), same as for sum3
* Just need to find a way to compare before resetting sum2 and sum3 to zero
boolean compare(int n, int [][] A)
{
int i, j, k, x, y, p, sum, sum2, sum3, total;
//row
for ( i = 0; i < n; i++)
{
sum = 0;
//col
for ( j = 0; j < n; j++)
sum+= A[i][j];
//row
for ( k = 0; k < n; k++)
{
sum2 = 0;
//col
if (k != i)
for ( x = 0; x < n; x++)
sum2 += A[k][x];
}
for ( y = 0; y < n; y++)
{
sum3 = 0;
if ( (y != k) && (y != i) )
for ( p = 0; p < n; p++)
sum3 += A[y][p];
}
total = sum2 + sum3;
if ( sum == (total) )
return true;
}//for ( i = 0; i < n; i++)
return false;
}
Any input is greatly appreciated
**** Here we go, I updated my code as below:
boolean compare(int n, int [][] A)
{
int i, j, k, x, y;
int [] sumArray = new int[n];
for (i = 0; i < n; i++)
{
sum = 0;
for(j = 0; j < n; j++)
sum += A[i][j];
sumArray[i] = sum;
}
for ( k = 0; k < n; k++)
{
for(x = 0; x < n; x++)
{
if( x != k)
{
for(y = 0; y < n; y++)
{
if( (y != x) && (y != k) )
{
if( sumArray[k] == (sumArray[x] + sumArray[y]) )
return true;
}
}
}
}
}
return false;
}
Seems like it would be easier to calculate the sum of each row and put them in a 1D array. Then you can compare sums of each row in a more concise way and you also avoid computing the sum of each row more than once.
Also, the parameter int n is not needed for the compare() method, since you can just check the length property of the array that gets passed in.
public boolean compare(int[][] arr) {
final int rowLen = arr.length;
int[] sums = new int[rowLen];
// Compute sum of each row
for (int row = 0; row < rowLen; row++) {
int rowSum = 0;
int[] rowArr = arr[row];
for (int col = 0; col < rowArr.length; col++)
rowSum += rowArr[col];
sums[row] = rowSum;
}
// Check if row n equals the sum of any other 2 rows
for (int n = 0; n < sums.length; n++) {
for (int i = 0; i < sums.length; i++) {
for (int j = i + 1; j < sums.length; j++)
if (n != i && n != j && sums[n] == sums[i] + sums[j]) {
// sum of row n equals sums of rows i+j
System.out.println("Sum of row " + n + " is equal to the sums of rows " + i + " and " + j);
return true;
}
}
}
return false;
}
Disclaimer: untested code, but it gets my point accross

A zero-indexed array given & An equilibrium index of this array [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
Improve this question
A zero-indexed array A consisting of N integers is given. An equilibrium index of this array is any integer P such that 0 ≤ P < N and the sum of elements of lower indices is equal to the sum of elements of higher indices, i.e.
A[0] + A[1] + ... + A[P−1] = A[P+1] + ... + A[N−2] + A[N−1].
Sum of zero elements is assumed to be equal to 0. This can happen if P = 0 or if P = N−1.
For example, consider the following array A consisting of N = 8 elements:
A[0] = -1
A[1] = 3
A[2] = -4
A[3] = 5
A[4] = 1
A[5] = -6
A[6] = 2
A[7] = 1
P = 1 is an equilibrium index of this array, because:
A[0] = −1 = A[2] + A[3] + A[4] + A[5] + A[6] + A[7]
P = 3 is an equilibrium index of this array, because:
A[0] + A[1] + A[2] = −2 = A[4] + A[5] + A[6] + A[7]
P = 7 is also an equilibrium index, because:
A[0] + A[1] + A[2] + A[3] + A[4] + A[5] + A[6] = 0
and there are no elements with indices greater than 7.
P = 8 is not an equilibrium index, because it does not fulfill the condition 0 ≤ P < N.
Now i have to write a function:
int solution(int A[], int N);
that, given a zero-indexed array A consisting of N integers, returns any of its equilibrium indices. The function should return −1 if no equilibrium index exists.
For example, given array A shown above, the function may return 1, 3 or 7, as explained above.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range [−2,147,483,648..2,147,483,647].
here have some Complexity:
Elements of input arrays can be modified.
100% - Java
int solution(int A[], int N) {
long sum = 0;
for (int i = 0; i < A.length; i++) {
sum += (long) A[i];
}
long leftSum = 0;
long rightSum = 0;
for (int i = 0; i < A.length; i++) {
rightSum = sum - (leftSum + A[i]);
if (leftSum == rightSum) {
return i;
}
leftSum += A[i];
}
return -1;
}
}
100% scored with c#
using System;
class Solution {
public int solution(int[] A) {
// First calculate sum of complete array as `sum_right`
long sum_right = 0;
for (int i = 0; i < A.Length; i++)
{
sum_right += A[i];
}
// start calculating sum from left side (lower index) as `sum_left`
// in each iteration subtract A[i] from complete array sum - `sum_right`
long sum_left = 0;
for (int p = 0; p < A.Length; p++)
{
sum_left += p - 1 < 0 ? 0: A[p-1];
sum_right -= A[p];
if (sum_left == sum_right)
{
return p;
}
}
return -1;
}
}
100 Score in Javascript
function solution(V) {
var sum = 0;
for (i=0; i < V.length; i++) {
sum += V[i];
}
var leftSum= 0;
var rightSum = 0;
for (j=0; j < V.length; j++) {
rightSum = sum - (leftSum + V[j]);
if(leftSum == rightSum) {
return j;
}
leftSum += V[j];
}
return -1;
}
In C++ (because that was one of the original tags, though it looks like it has been removed...)
int solution(int a[], int N){
int left;
int right;
for(int i = 0; i < N; i++){
left = 0;
right = 0;
for(int t = 0; t < N; t++){
if(t < i) left += a[t];
else if(t > i) right += a[t];
else continue;
}
if(left == right) return i;
}
return -1;
}
...
int demo[] = {-1, 3, -4, 5, 1, -6, 2, 1};
cout << solution(demo,sizeof(demo)/sizeof(*demo));
if you want to see all the indices...
if(left == right) cout << "Equilibrium Index: " << i << endl;
I find it odd it doesn't need to return an array of indices; that said, should you need it that's not too hard to implement with some slight modification
The answer is posted in this blog: http://blog.codility.com/2011/03/solutions-for-task-equi.html. In order to avoid O(N^2) and achieve O(N) performance:
The key observation for better running time is to update the left/right sums in constant time instead of recomputing them from the scratch.
int equi(int arr[], int n)
{
if (n==0) return -1;
long long sum = 0;
int i;
for(i=0;i<n;i++) sum+=(long long) arr[i];
long long sum_left = 0;
for(i=0;i<n;i++) {
long long sum_right = sum - sum_left - (long long) arr[i];
if (sum_left == sum_right) return i;
sum_left += (long long) arr[i];
}
return -1;
}
Here is the java equivalent
public static int equilibriumIndex(int[] array) {
int INDEX_NOT_FOUND = -1;
int rSum = 0, lSum = 0;
for (int index = 0; index < array.length; index++) {
rSum += array[index];
}
for (int index = 0; index < array.length; index++) {
lSum += (index==0) ? 0 : array[index -1];// cumulative sum before (left sum) the current index
rSum -= array[index]; // sum after (right sum) the current index onwards
if (lSum == rSum) { // if both sums, cumulative sum before the current index and cumulative sum after the current index is equal, we got the equilibrium index
return index;
}
}
return INDEX_NOT_FOUND;
}
Here is how you would test it
#Test
public void equilibriumTest() {
int result = ArrayUtils.equilibriumIndex(new int[]{1,2,3,1,6});
assertThat(result, equalTo(3));
}
Dynamic programming approach. O(N) time. O(2N) space.
Keep two tables (arrays), tableBefore and tableAfter.
tableBefore has sum up to index i for every i; i -> 1 to N.
tableAfter has sum up to index i for every i; i -> N to 1.
Afterwards loops and compare every index in tableBefore and tableAfter. If it's equal, that's your equilibrium index.
public static int EquilibriumIndex2(int[] a) {
int len = a.length;
int[] tableBefore = new int[len];
int[] tableAfter = new int[len];
tableBefore[0] = 0;
for (int i = 1; i < len; i++) {
tableBefore[i] = tableBefore[i - 1] + a[i - 1];
}
//System.out.println("tableBefore: " + Arrays.toString(tableBefore));
tableAfter[len - 1] = 0;
for (int i = len - 2; i >= 0; i--) {
tableAfter[i] = tableAfter[i + 1] + a[i + 1];
}
//System.out.println("tableAfter: " + java.util.Arrays.toString(tableAfter));
for (int j = 0; j < len; j++) {
if (tableAfter[j] == tableBefore[j]) {
return j;
}
}
return -1;
}
You can use the sums approach to solve this. Whenever sum from left = sum from right, you have an equilibrium point.
public int solution(int[] A) {
int[] sumLeft = new int[A.length];
int[] sumRight = new int[A.length];
sumLeft[0] = A[0];
sumRight[A.length-1] = A[A.length-1];
for (int i=1; i<A.length; i++){
sumLeft[i] = A[i] + sumLeft[i-1];
}
for (int i=A.length-2; i>=0; i--) {
sumRight[i] = sumRight[i+1] + A[i];
}
for (int i=0; i<A.length; i++) {
if (sumLeft[i]==sumRight[i]) {
return i;
}
}
return -1;
}
The straightforward approach looks the following way.
First of all you need to calculate the sum of all elements of the array
For example if you have the array in C++
int a[] = { -1, 3, -4, 5, 1, -6, 2, 1 };
then you can use an ordinary loop to calculate the sum or standard algorithm std::accumulate declared in header <numeric>
For example
long long int right_sum =
std::accumulate( std::begin( a ), std::end( a ), 0ll );
The sum of the elements of the left subsequence initially is equal to zero
long long int left_sum = 0;
Then you can apply standard algorithm std::find_if with an appropriate lambda-expression or again write an ordinary loop as for example
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
{
right_sum -= a[i];
if ( left_sum == right_sum ) std::cout << i << ' ';
left_sum += a[i];
}
The result will be
1 3 7
My answer in Swift 3.0
public func solution(_ A : inout [Int]) -> Int {
var nElements = A.count
var equilibriumIndexArray = [Int]() /* to store all possible indices */
var equilibriumIndex = -1
for fixedIndex in 0..<nElements{
var sumLeft = 0
var sumRight = 0
//Sum the left part
for index in 0..<fixedIndex
{
sumLeft += A[index]
}
//Sum the right part
for index in fixedIndex+1..<nElements
{
sumRight += A[index]
}
//Check for equilibrium
if sumLeft == sumRight
{
equilibriumIndexArray.append(fixedIndex)
}
}
//pick a random element from the list of possible answers
if equilibriumIndexArray.count > 0
{
let randomIndex = Int(arc4random_uniform(UInt32(equilibriumIndexArray.count)))
equilibriumIndex = equilibriumIndexArray[randomIndex]
}
return equilibriumIndex
}
in python :)
def solution(A):
INDEX_NOT_FOUND = -1
right_sum = 0
left_sum = 0
for item in range(0, len(A)):
right_sum += A[item]
for item in range(0, len(A)):
if item == 0:
left_sum += 0
else:
left_sum += A[item -1]
right_sum -= A[item]
if left_sum == right_sum:
return item
return INDEX_NOT_FOUND;
100% - PHP
function solution(array $a)
{
$result = [];
for($i = 0; $count = count($a), $i < $count; $i++) {
if(sumLeft($a, $i-1) === sumRight($a, $i+1)) {
$result[] = $i;
}
}
return count($result) ? $result : -1;
}
function sumRight(array $a, int $position): int
{
return array_sum(array_slice($a, $position));;
}
function sumLeft(array $a, int $position): int
{
return array_sum(array_slice($a, 0, $position + 1));
}
echo "<pre>";
print_r(solution([-1, 3, -4, 5, 1, -6, 2, 1]));
output:
Array
(
[0] => 1
[1] => 3
[2] => 7
)
Simple Solution :
steps :
1) Check (Array = null)
Then Print “No Equilibrium point present as the array is NULL”
2) Check (length of Array = 1)
Then Print "Equilibrium_Index = 0" => Only single element present in array which is the equilibrium point
3) Check (Length of Array > 1)
Loop (Array Index 1 to Length-1)
Consider each index as equilibrium point
Check (sum of elements below equilibrium point = sum of elements above equilibrium poin)
Yes => equilibrium_index = i (break the loop)
No => continue step 3 with next value of loop counter
4) if control is not returned from step 3 means the equilibrium point is not present in loop
Then Print "No equilibrium point present in array."
Please find below code for same :
public int findSum(int equillibrium,int a[],int flag)
{
/*Flag - It represents whether sum is required for left side of equilibrium
point or right side of equilibrium point
*Flag = 0 => Sum is required for left side of equilibrium point
*Flag = 1 => Sum is required for right side of equilibrium point
*/
int lowlimit = 0, uplimit = a.length-1, i ,sum = 0;
if(flag==0)
uplimit = equillibrium - 1;
else
lowlimit = equillibrium + 1;
for(i=lowlimit ; i<=uplimit; i++)
sum = sum + a[i];
return sum;
}
public int findEquillibriumPoint(int a[])
{
int i = 0; //Loop Counter
//Since only one element is present it is at equilibrium only and index of equillibrium point is index of single element i.e 0
if(a.length==1)
return 0;
else
{
for(i=1;i<a.length;i++)
{
if(findSum(i,a,0)==findSum(i,a,1)) //checking if some of lower half from equilibrium point is equal to sum of upper half
return i; //if equilibrium point is found return the index of equilibrium point
}
}
return -1;//if equilibrium point is not present in array then return -1
}
For the lazy ones and PHP developers:
$A = [];
$A[0] = -1;
$A[1] = 3;
$A[2] = -4;
$A[3] = 5;
$A[4] = 1;
$A[5] = -6;
$A[6] = 2;
$A[7] = 1;
echo solution($A) . "\n";
function solution($A)
{
$sum = 0;
for ($i=0; $i < count($A); $i++) {
$sum += $A[$i];
}
$sumRight = 0;
$sumLeft = 0;
for ($j=0; $j < count($A); $j++) {
$sumRight = $sum - ($sumLeft + $A[$j]);
if ($sumLeft == $sumRight) {
return $j;
}
$sumLeft += $A[$j];
}
return -1;
}
Complexity O(N)
100 Score in Ruby
def equilibrium(a)
sum = 0
n = a.length
left_sum = 0
right_sum = 0
n.times do |i|
sum += a[i]
end
n.times do |i|
right_sum = sum - left_sum - a[i]
if right_sum == left_sum
return i
end
left_sum += a[i]
end
return -1
end
Fully tested C#
using System;
class Program
{
static int Function1(int[] arr, int n)
{
int i, j;
int leftsum;
int rightsum;
for (i = 0; i < n; ++i)
{
leftsum = 0;
rightsum = 0;
if(i == 0)
{
leftsum = 0;
for (j = 0; j < n; j++)
{
rightsum += arr[j];
}
if (leftsum == rightsum)
return i;
}
for (j = 0; j < i; j++)
{
leftsum += arr[j];
}
if (n-1 != j)
{
for (j = i + 1; j < n; j++)
{
rightsum += arr[j];
}
}
else
{
rightsum = arr[n-1];
}
if (leftsum == rightsum)
return i;
}
return -1;
}
public static void Main(string[] args)
{
int[] arr = { 1, 5, -8, 0, -2 };
int arr_size = arr.Length;
Console.Write(Function1(arr, arr_size));
}
}

Max value for the sum of consecutive indicies (Java)

Write a function int bentley(int a) that return the index, j, from a pair of indices (i,j) such that a[i]+a[i+1]++a[j-1] is maximum over all such pairs (i,j).
^^This is the question i have to answer. Im assuming "a[i]+a[i+1]++a[j-1]" means from a[i ] to a[j-1]. So far this is what i have:
public static int bentley(int[] a) {
int max = 0;
int oldsum = 0;
int sum = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
sum = oldsum + a[j];
if (sum > oldsum) {
max = j;
oldsum = sum;
}
else {
sum = oldsum;
}
}
}
return max;
}
It doesnt work, i dont know why or how to fix it.

Shell sort Java example

Can anyone give me example about shell sort? I'm a new person in here who must learn about shell sort, but first I must find a Java shell sort example. I found one example in Google but it's too difficult.
Here, this code is very simple :
/**
* Shellsort, using Shell’s (poor) increments.
* #param a an array of Comparable items.
*/
public static <T extends Comparable<? super T>>
void shellsort( T [ ] a )
{
int j;
for( int gap = a.length / 2; gap > 0; gap /= 2 )
{
for( int i = gap; i < a.length; i++ )
{
T tmp = a[ i ];
for( j = i; j >= gap && tmp.compareTo( a[ j - gap ] ) < 0; j -= gap )
{
a[ j ] = a[ j - gap ];
}
a[ j ] = tmp;
}
}
}
I stole it from a book called Data Structures and Algorithm Analysis in Java. It is very good book easy to understand. I advise you to read it.
May be, this java code will help you.
public class ShellSort {
private long[] data;
private int len;
public ShellSort(int max) {
data = new long[max];
len = 0;
}
public void insert(long value){
data[len] = value;
len++;
}
public void display() {
System.out.print("Data:");
for (int j = 0; j < len; j++)
System.out.print(data[j] + " ");
System.out.println("");
}
public void shellSort() {
int inner, outer;
long temp;
//find initial value of h
int h = 1;
while (h <= len / 3)
h = h * 3 + 1; // (1, 4, 13, 40, 121, ...)
while (h > 0) // decreasing h, until h=1
{
// h-sort the file
for (outer = h; outer < len; outer++) {
temp = data[outer];
inner = outer;
// one subpass (eg 0, 4, 8)
while (inner > h - 1 && data[inner - h] >= temp) {
data[inner] = data[inner - h];
inner -= h;
}
data[inner] = temp;
}
h = (h - 1) / 3; // decrease h
}
}
public static void main(String[] args) {
int maxSize = 10;
ShellSort arr = new ShellSort(maxSize);
for (int j = 0; j < maxSize; j++) {
long n = (int) (java.lang.Math.random() * 99);
arr.insert(n);
}
arr.display();
arr.shellSort();
arr.display();
}
}
Shell sort improves insertion sort by comparing elements separated by a gap of several positions.
This lets an element take "bigger steps" toward its expected position. Multiple passes over the data are taken with smaller and smaller gap sizes. The last step of Shell sort is a plain insertion sort, but by then, the array of data is guaranteed to be almost sorted.
This code might help you in understanding the logic better.
package Sorts;
public class ShellSort extends Sorter{
#Override
public <T extends Comparable<? super T>> void sort(T[] a) {
int h = 1;
while((h*3+1) < a.length)
h = 3*h+1;
while(h > 0){
for(int i = h-1; i < a.length; i++){
T s = a[i];
int j = i;
for(j = i; (j>=h) && (a[j-h].compareTo(s) > 0); j-=h)
a[j] = a[j-h];
a[j] = s;
}
h /= 3;
}
}
}
Here is a visualization of shell sort for a python implementation:
def exch(a,i,j):
t = a[i]
a[i] = a[j]
a[j] = t
def shellsort(string):
print string
a = list(string)
N = len(a)
h = 1
i = 0
j = 0
k = 0
#determine starting stride length
while ( h < N/3 ):
h = 3*h + 1
print "STRIDE LENGTH: " + str(h)
while (h >=1):
i = h
while i < N:
j = i
k = j - h
while j >= h and a[j] < a[j-h]:
k = j - h
exch(a,j,k)
j -= h
i += 1
h = h/3
print "STRIDE LENGTH: " + str(h)
print ''.join(a)·
if __name__ == '__main__':
shellsort("astringtosortwithshellsort")
Here's an example:
public static void shellsort( Comparable [ ] a )
{
for( int gap = a.length / 2; gap > 0;
gap = gap == 2 ? 1 : (int) ( gap / 2.2 ) )
for( int i = gap; i < a.length; i++ )
{
Comparable tmp = a[ i ];
int j = i;
for( ; j >= gap && tmp.compareTo( a[ j - gap ] ) < 0; j -= gap )
a[ j ] = a[ j - gap ];
a[ j ] = tmp;
}
}
I find the easiest way to understand shell sort is to break it down into segments:
private static void shellsort() {
int[] theArray = {44,5,33,22,765,43,53,12,57,97};
//first section gets the Knuth's interval sequence (very efficient)
int h=1;
while(h<= theArray.length/3){
h = 3*h + 1; //h is equal to highest sequence of h<=length/3 (1,4,13,40...)
}
//next section
while(h>0){ //for array of length 10, h=4
//similar to insertion sort below
for(int i=0; i<theArray.length; i++){
int temp = theArray[i];
int j;
for(j=i; j>h-1 && theArray[j-h] >= temp; j=j-h){
a[j] = a[j-h];
}
a[j] = temp;
}
h = (h-1)/3;
}
}
Output: 5, 12, 22, 33, 43, 44, 53, 57, 97, 765
Classic primitive type implementation:
package math;
import java.util.Arrays;
public class Sorter{
public static void main(String []args){
int[] a = {9,8,7,6,5,4,3,2,1};//plz use sophisticated random number generator
System.out.println( Arrays.toString(a) );
System.out.println( Arrays.toString(shellSort(a)) );
}
//Performs a shell sort on an array of ints.
public static int[] shellSort(int[] array){
int h = 1;
while (h < array.length) h = 3*h + 1;
while (h > 0){
h = h/3;
for (int k = 0; k < h; k++){
for (int i = h+k; i < array.length; i+=h){
int key = array[i];
int j = i-h;
while (j>=0 && array[j] > key){
array[j+h] = array[j];
j-=h;
}
array[j+h] = key;
//-> invariant: array[0,h,2*h..j] is sorted
}
}
//->invariant: each h-sub-array is sorted
}
return array;
};
}
P.S.: Check this link for other sorting algorithms (they are in c++, though, easily portable to java).
package sort_tester;
public class ShellSorter extends Sorter {
private final int[] gapArray = {1750,701,301,132,57,23,10,4,1};
#Override
public void makeSort (boolean trace) {
int size = list.length;
int i,j, temp;
for ( int gap : gapArray ) {
i = gap;
while ( i < size ) {
temp = list[i];
j = i-gap;
while ( j >= 0 && list[j] > temp ) {
list[j + gap] = list[j];
j -= gap;
}
list[j + gap] = temp;
i ++;
}
}
}
}
list - is int[];
GapArray taken from arcticle of Marcin Ciura
http://sun.aei.polsl.pl/~mciura/publikacje/shellsort.pdf
Here is a video link: https://youtu.be/SCBf7aqKQEY
The guy has made a good video of shell sort!!
And a simple code:
int sort(int arr[])
{
int n = arr.length;
int gap = n/2;
int i,j;
while(gap>0)
{ for (i=0,j=i+gap; j<n; i++,++j)
{
if(arr[i]>arr[j]) //swap
{ int temp = arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
gap=gap/2;
}
return 0;
}
Use this
public void shellSort(Integer[] arr) {
int interval = arr.length / 2;
while (interval != 0) {
for (int i = 0; i < interval; i++) {
for (int p = i + interval; p < arr.length; p += interval) {
int key = arr[p];
int j = p - interval;
while (j >= 0) {
if (key < arr[j]) {
arr[j + interval] = arr[j];
} else
break;
j -= interval;
}
arr[j + interval] = key;
}
}
interval /= 2;
}
}
Snippet with 3k+1 gap.
public void shellSort(Comparable arr[], int size, int h, int x) {
while (h >= 1) {
for (int i = 0; i <= size - h; i++) {
for (int j = i; j < size-h && (arr[j].compareTo(arr[j+h]) > 0); j += h)
swap(arr, j, j+h);
}
h = 3*(--x) + 1;
}
}

Categories