Alternating Ordination - java

Given a sequence of numbers in the array, return these numbers arranged alternately, that is, the lowest numbers, followed by the most, followed by the second lowest, followed by the second highest, and so on.
Input: 1 2 3 4 5
output: 1 5 2 4 3
input: 10 5 7 9 2 2
output: 2 10 2 9 5 7
I try something like this, but not working for me, can help me please.
I need two output into the same function or method.
public class Test{
int[] inputArray = { 1, 2, 3, 4, 5 };
void mergeSort(int[] array) {
int[] helper = new int[array.length];
mergesort(array, helper, 0, array.length - 1);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
private void mergesort(int[] array, int[] helper, int low, int high) {
if (low < high) {
int middle = (low + high) / 2;
mergesort(array, helper, low, middle);
mergesort(array, helper, middle + 1, high);
merge(array, helper, low, middle, high);
}
}
private void merge(int[] array, int[] helper, int low, int middle, int high) {
for (int i = low; i <= high; i++) {
helper[i] = array[i];
}
int helperLeft = low;
int counter = 0;
int helperRight = middle + 1;
int current = low;
while (helperLeft <= middle && helperRight <= high) {
if (counter % 2 == 0) {
if (helper[helperLeft] <= helper[helperRight]) {
array[current] = helper[helperLeft];
helperLeft++;
} else {
array[current] = helper[helperRight];
helperRight++;
}
} else {
if (helper[helperLeft] >= helper[helperRight]) {
array[current] = helper[helperLeft];
helperLeft++;
} else {
array[current] = helper[helperRight];
helperRight++;
}
}
counter++;
current++;
}
int remaining = middle - helperLeft;
for (int i = 0; i <= remaining; i++) {
array[current + i] = helper[helperLeft + i];
}
}
public static void main(String[] args) {
Solution i = new Solution();
i.mergeSort(i.inputArray);
}
}
output : 1,4,3,5,2

I would first start off by sorting the array as normal, then use it to alternate in the way you want.
int[] toReturn = new int[inputArray.length];
Arrays.sort(inputArray);
for (int i = 0; i < inputArray.length; i+=2) {
toReturn[i] = inputArray[i/2];
}
for (int i = 1; i < inputArray.length; i+=2) {
toReturn[i] = inputArray[inputArray.length - i/2 - 1];
}

You can simply sort your array then perform this operation:
initialize two variables : i = 0 and j = array.length - 1
while j > i then print array[i] followed by array[j]
increase i and decrease j
at the end of the loop, print array[i] (to handle the case when i == j)
Here is a sample code:
Arrays.sort(array);
int i = 0, j = array.length - 1;
while (i < j) {
System.out.print(array[i] + " ");
System.out.print(array[j] + " ");
i++;
j--;
}
if (i == j) {
System.out.println(array[i]);
}

Related

Find the number of distinct triplets sums to a given integer

You have been given a random integer array/list(ARR) and a number X. Find and return the number of distinct triplet(s) in the array/list which sum to X.
I have written this code:
public class Solution {
public static void merge(int arr[], int lb, int mid, int ub) {
int n1 = mid - lb + 1;
int n2 = ub - mid;
int arr1[] = new int[n1];
int arr2[] = new int[n2];
for (int i = 0; i < n1; i++)
arr1[i] = arr[lb + i];
for (int j = 0; j < n2; j++)
arr2[j] = arr[mid + 1 + j];
int i = 0, j = 0;
int k = lb;
while (i < n1 && j < n2) {
if (arr1[i] <= arr2[j])
arr[k] = arr1[i++];
else
arr[k] = arr2[j++];
k++;
}
while (i < n1)
arr[k++] = arr1[i++];
while (j < n2)
arr[k++] = arr2[j++];
}
public static void mergeSort(int arr[], int lb, int ub) {
if (lb < ub) {
int mid = lb + (ub - lb) / 2;
mergeSort(arr, lb, mid);
mergeSort(arr, mid + 1, ub);
merge(arr, lb, mid, ub);
}
}
public static int tripletSum(int[] arr, int num) {
mergeSort(arr, 0, arr.length - 1);
int n = arr.length;
int count = 0;
for (int i = 0; i < n - 2; i++) {
int sum = num - arr[i];
int j = i + 1;
int k = n - 1;
while (j < k) {
if (arr[j] + arr[k] == sum) {
count++;
k--;
} else if (arr[j] + arr[k] > sum) {
k--;
} else
j++;
}
}
return count;
}
}
Input array was - 1 3 3 3 3 3 3
Input num = 9
Output Generated - 10
Expected output - 20
Help me out with this I'm trying to find the solution for many hours. Also, the time complexity of the program should not exceed O(n²).
The given code works fine for all test cases.
import java.util.Arrays;
public class Solution {
public static int tripletSum(int[] arr, int num) {
Arrays.sort(arr);
int n = arr.length;
int Numtripletsum = 0;
for(int i=0;i<n;i++)
{
int pairSumFor = num - arr[i];
int numPairs = pairSum(arr, (i+1), (n-1), pairSumFor);
Numtripletsum+=numPairs;
}
return Numtripletsum;
}
private static int pairSum(int[] arr, int startIndex, int endIndex, int num ){
int numPair = 0;
while(startIndex < endIndex){
if(arr[startIndex] + arr[endIndex] < num){
startIndex++;
}
else if(arr[startIndex] + arr[endIndex] > num){
endIndex--;
}
else
{
int elementAtStart = arr[startIndex];
int elementAtEnd = arr[endIndex];
if(elementAtStart == elementAtEnd){
int totalElementsFromStartToEnd = (endIndex - startIndex) + 1;
numPair += (totalElementsFromStartToEnd * (totalElementsFromStartToEnd -1) /2);
return numPair;
}
int tempStartIndex = startIndex + 1;
int tempEndIndex = endIndex - 1;
while(tempStartIndex <= tempEndIndex && arr[tempStartIndex] == elementAtStart){
tempStartIndex+=1;
}
while(tempEndIndex >= tempStartIndex && arr[tempEndIndex] == elementAtEnd){
tempEndIndex-=1;
}
int totalElementsFromStart = (tempStartIndex - startIndex);
int totalElementsFromEnd = (endIndex - tempEndIndex);
numPair += (totalElementsFromStart * totalElementsFromEnd);
startIndex = tempStartIndex;
endIndex = tempEndIndex;
}
}
return numPair;
}
}
I did it in this way, hope I understood it well.
public static int tripletSum(int[] arr, int num) {
int loops = 0; // just to check the quality of the code
int counter = 0;
for (int i1 = 0; i1 < arr.length - 2; i1++) {
for (int i2 = i1 + 1; i2 < arr.length - 1; i2++) {
for (int i3 = i2 + 1; i3 < arr.length; i3++) {
loops++;
if (arr[i1] + arr[i2] + arr[i3] == num) {
counter++;
}
}
}
}
// Check for not exceeding O(n^2)
if (loops <= arr.length * arr.length) {
System.io.println("Well done");
} else {
System.io.println("Too many cycles");
}
return counter;
}
I iterate from "left" to "right" over the array and walking more and more to the "right".
1st, 2nd, 3rd
1st, 2nd, 4th
...
1st, 2nd, nth
2nd, 3rd, 4th
2nd, 3rd, 5th
...
2nd, 3rd, nth
.
.
.
nth - 2, nth - 1, nth
I iterated 35 times, but could iterate 7^2 = 49 times --> "Well done"
You missed one loop. The fixed code:
public static int tripletSum(int[] arr, int num) {
//Your code goes here
mergeSort(arr, 0, arr.length - 1);
int n = arr.length;
int count = 0;
for (int i = 0; i < n - 2; i++) {
int sum = num - arr[i];
for (int j = i+1; j < n-1; j++) {
int k = n-1;
while (j < k) {
if (arr[j] + arr[k] == sum) {
count++;
k--;
} else if (arr[j] + arr[k] > sum) {
k--;
} else {
j++;
}
}
}
}
return count;
}
OK, then optimized version:
public static int tripletSum(int[] arr, int num) {
//Your code goes here
mergeSort(arr, 0, arr.length - 1);
int n = arr.length;
int count = 0;
for (int i = 0; i < n - 2; i++) {
int sum = num - arr[i];
int maxK = n - 1;
for (int j = i + 1; j < n - 1; j++) {
int k = maxK;
while (j < k) {
if (arr[j] + arr[k] == sum) {
count++;
k--;
} else if (arr[j] + arr[k] > sum) {
k--;
maxK--;
} else {
j++;
}
}
}
}
return count;
}

Finding contiguous array

I am trying to get an output of [4,6,6,7] with length 4 where arr[i] <= arr[i+1] where it is non-decreasing and it is contiguous. I know what i have to do but i dont know how to do it. my code prints out [3,4,6,6,7]. I am just having trouble on the contiguous part, any help? im not allowed to use extra arrays.
public static void ascentLength(int arr[], int size) {
int length = 0;
int index = 0;
int count = 1;
for (int i = 0; i < size-1; i++) {
index = i;
if (arr[0] <= arr[i+1] && count >0) {
System.out.println(arr[i]+ " index:" + index);
length++;
count++;
}
if (arr[0] >= arr[i+1]) {
}
}
System.out.println("length: " + length);
}
/* Driver program to test above function */
public static void main(String[] args) {
int arr[] = {5, 3, 6, 4, 6, 6, 7, 5};
int n = arr.length;
ascentLength(arr, n);
}
Here is my solution, it would be easier, if you could work with List, but this works for arrays:
public static void ascentLength(int arr[], int size) {
if(size == 1) System.out.println("length: 1");
// variables keeping longest values
int longestStartingIndex = 0;
int longestLength = 1;
// variables keeping current values
int currentStartingIndex = 0;
int currentCount = 1;
for (int i = 1; i < size; i++) {
if (arr[i-1] <= arr[i]) {
currentCount++;
} else {
// check if current count is the longest
if(currentCount > longestLength) {
longestLength = currentCount;
longestStartingIndex = currentStartingIndex;
}
currentStartingIndex = i;
currentCount = 1;
}
}
if(currentCount > longestLength) {
longestLength = currentCount;
longestStartingIndex = currentStartingIndex;
}
}

How to find the maximum subarray of size >= 2 for the given array?

Given an array and an integer k, find the maximum for each and every contiguous subarray of size >=2.
INPUT:
int[] array = new int[]{-5,-2,-3,-1,-1};
int[] array1 = new int[]{5,2,3,-3,1,1};
OUTPUT:
-1,-1 //Since the maximum sum with maximum contiguous subarray can be of size 2 or greater than 2 and all are negative, so we taking the subarray = -1 -1
5,2,3 // Because we need to find the maximum sum and maximum subarray with limitation that array can be >= 2
I have solved this but my solution is not working when all the integers are negative. Also, it is not working when input is -5,-2,-3,-3,1,1. The output should be 1 and 1 but it is coming as -3,-3,1 and 1.
I need an optimized solution. Please find my code below:
public class Pro {
static int[] maxSubarray(int[] a) {
int max_sum = a[0];
int curr_sum = a[0];
int max_start_index = 0;
int startIndex = 0;
int max_end_index = 1;
for (int i = 1; i < a.length; i++) {
if (max_sum > curr_sum + a[i]) {
startIndex = i-1;
curr_sum = a[i];
} else {
curr_sum += a[i];
}
if (curr_sum > max_sum) {
max_sum = curr_sum;
max_start_index = startIndex;
max_end_index = i;
}
}
if (max_start_index <= max_end_index) {
return Arrays.copyOfRange(a, max_start_index, max_end_index + 1);
}
return null;
}
public static void main(String[] args) {
int[] array = new int[]{-5,-2,-3,-1,-1};
int[] array1 = new int[]{5,2,-3,1,1};
int[] out = maxSubarray(array1);
for(int a : out)
{
System.out.println(a);
}
}
}
There is one more code snippet which can be helpful. It finds the maximum subarray. See code below:
public int maxSubArray(int[] A) {
int max = A[0];
int[] sum = new int[A.length];
sum[0] = A[0];
for (int i = 1; i < A.length; i++) {
sum[i] = Math.max(A[i], sum[i - 1] + A[i]);
max = Math.max(max, sum[i]);
}
return max;
}
The algorithm you are using is called Kardane's algorith and cannot be used when all the numbers are negative. At least one number has to be positive for the algorithm to work. To make it work for arrays with negative numbers but also at least one positive number, curr_sum should be set to 0 whenever you come across a negative number in your array. One way to achieve this is to use a custom max-function
private int max(int first, int second) {
if (first < second) return first;
else return second;
}
Replace:
if (max_sum > curr_sum + a[i]) {
startIndex = i-1;
curr_sum = a[i];
} else {
curr_sum += a[i];
}
with:
curr_sum = max(curr_sum + a[i], 0);
if (curr_sum == 0) startIndex = i + 1;
Full code:
public int max(int[] a) {
int max_sum = a[0];
int curr_sum = a[0];
int startIndex = 0;
int max_start_index = 0;
int max_end_index = 1;
for (int i = 1; i < a.length; i++) {
max_sum = max(max_sum + a[i], 0);
if (max_sum == 0) startIndex = i + 1;
curr_sum = max(curr_sum, max_sum);
if (curr_sum == max_sum) {
max_start_index = startIndex;
max_end_index = i;
}
}
System.out.println("Start index: " + max_start_index);
System.out.println("End index: " + max_end_index);
return curr_sum;
}
Input: -5, -2, -3, -3, 1, 1
Output:
Start index: 4
End index: 5
2

How to find number of tuples whose sum is equal or less than a given number?

I'm designing an algorithm to find the number of tuples whose sum is equal or less than a given number. I know other ways of solving it using LinkedList, so, not looking for that solution. I just want to traverse through the array and count the possible matches that satisfy the relation. I come up so far,
public static int numberOfPairs(int[] a, int k ){
int len = a.length;
if (len == 0){
return -1;
}
Arrays.sort(a);
int count = 0, left = 0, right = len -1;
while( left < right ){
if ( a[left] + a[right] <= k ){
// System.out.println(a[left] + "\t" + a[right]);
count++;
/*may be the same numbers will also satisfy the relation*/
if ( a[left] + a[left+1] <= k) {
count ++;
// System.out.println(a[left] + "\t"+a[left+1]);
}
/*now, use iteration to traverse the same elements*/
while (a[left] == a[left+1] && left < len-1 ){
left++;
}
/*may be the same numbers will also satisfy the relation*/
if ( a[right] + a[right-1] <= k) {
count ++;
// System.out.println(a[right] +"\t"+ a[right-1]);
}
/*now, use iteration to traverse
the same elements*/
while ( a[right] == a[right-1] && right >1 ){
right-- ;
}
}
// traverse through the array
left++;
right--;
}
return count;
}
This is not providing the correct solution, say, if I pass array and number as following,
int [] arr = { 3, 3, -1, 4, 2,5, 5, 1};
System.out.println(numberOfPairs(arr, 8));
The correct solution will be 15 pairs as following,
{
{-1,1}, {-1,2} , {3,-1}, {-1,4 }, {-1,5},
{2,1},{3,1 },{4,1}, { 5,1},
{3,2 },{4,2}, {2,5 },
{3,4 } , {3,5 },
{3,3}
}
How can I improve my code ? thanks.
Note: the other way I solve it using LinkedList is as following,
public static int numberOfPairs10(int[] arr, int sum){
/*1.can be the same values of i
2. can be the same valus of j for the same i*/
List<Integer> li = new ArrayList<Integer>();
List<Integer> lj;
int count = 0;
for ( int i =0; i < arr.length -1 ; i++){
if (li.contains(arr[i]) )
continue;
lj = new ArrayList<Integer>();
for (int j = i+1; j < arr.length; j++){
if (lj.contains(arr[j]))
continue;
// if ( arr[i]+ arr[j] <= sum){
if ( arr[i]+ arr[j] == sum){
count++;
lj.add(arr[j]);
}
}
li.add(arr[i]);
}
return count;
}
This is tested with just
int [] arr = { 3, 3, -1, 4, 2,5, 5, 1};
numberOfPairs(arr, 8);
and here is codes
public static int numberOfPairs(int[] a, int k ) {
int len = a.length;
int counter = 0;
boolean isCheckedLeft = false;
boolean isCheckedRight = false;
int i, j, h;
Arrays.sort(a);
for (i = 0; i < len; i++) {
isCheckedLeft = false;
for (j = i - 1; j >= 0; j--) {
if (a[i] == a[j]) {
isCheckedLeft = true;
break;
}
}
if (isCheckedLeft) {
continue;
}
for (j = i + 1; j < len; j++) {
isCheckedRight = false;
for (h = j - 1; h > i; h--) {
if (a[j] == a[h]) {
isCheckedRight = true;
break;
}
}
if (isCheckedRight) {
continue;
}
System.out.print("("+a[i]+", "+a[j]+") ");
if (a[i] + a[j] <= k) {
counter++;
}
}
}
return counter;
}
If you are not too worried about performance then you could just find all unique combinations and then filter according to your condition. For example, using Java 8 streams:
public int numberOfPairs(int[] values, int maxVal) {
return IntStream.range(0, values.length)
.flatMap(i1 -> IntStream.range(i1 + 1, values.length)
.map(i2 -> Arrays.asList(values[i1], values[i2])))
.distinct().filter(l -> l.stream().sum() <= maxVal).count();
}

Where are comparisons in java sorting methods?

Question: Where are comparisons being made in each separate sorting method?
Also if you know please tell me which method count numbers are wrong and where to place my counters instead.trying to understand where and how many times sorting methods make comparisons.
Method A B
Selection 4950 4950
Bubble 99 9900
Insertion 99 5049
Merge 712 1028
Shell 413 649
Quick 543 1041
Okay so to explain some parts, basically Array A is an array from 1-100 in ascending order. So this should be the minimum number of comparisons.
Array B is 100-1 in descending order. So I believe it should be the maximum number of comparisons. Array C is just randomly generated numbers, so it changes every time.
I feel like my selection and bubble sorts were counted correctly. Feel free to let me know where comparisons are being made that I haven't counted, or if I'm counting wrong comparisons.
Side note: Made some global variable to count the methods that were recursive in multiple sections.
class Sorting
{
static int[] X = new int[100];
static int mergecount = 0;
static int quickcount = 0;
public static void selectionSort(int list[])
{
int count = 0;
int position = 0, n = list.length;
for(int j = 0; j < n-1; j++)
{
position = j;
for(int k = j+1; k < n; k++)
{
count++;
if(list[k] < list[position])
position = k;
}
Swap(list, j, position);
}
System.out.println("counter" + count);
}
public static void Swap(int list[], int j, int k)
{
int temp = list[j];
list[j] = list[k];
list[k] = temp;
}
public static void bubbleSort(int list[])
{
int count = 0;
boolean changed = false;
do
{
changed = false;
for(int j = 0; j < list.length - 1; j++)
{
count++;
if(list[j] > list[j + 1])
{
Swap(list, j, j+1);
changed = true;
}
}
} while(changed);
System.out.println("counter" + count);
}
public static void insertionSort(int list[])
{
int count = 0;
for(int p = 1; p < list.length; p++)
{
int temp = list[p];
int j = p;
count++;
for( ; j > 0 && temp < list[j - 1]; j = j-1)
{
list[j] = list[j - 1];
count++;
}
list[j] = temp;
}
System.out.println("counter" + count);
}
public static void mergeSort(int list[])
{
mergeSort(list, 0, list.length - 1);
System.out.println("counter" + mergecount);
}
public static void mergeSort(int list[], int first, int last)
{
if(first < last)
{
int mid = (first + last) / 2;
mergeSort(list, first, mid);
mergeSort(list, mid + 1, last);
Merge(list, first, mid, last);
}
}
public static void Merge(int list[], int first, int mid, int last)
{
int count = 0;
int first1 = first, last1 = mid;
int first2 = mid + 1, last2 = last;
int temp[] = new int[list.length];
int index = first1;
while(first1 <= last1 && first2 <= last2)
{
if(list[first1] < list[first2])
{
temp[index] = list[first1++];
mergecount++;
}
else
temp[index] = list[first2++];
index++;
mergecount++;
}
while(first1 <= last1)
temp[index++] = list[first1++];
while(first2 <= last2)
temp[index++] = list[first2++];
for(index = first; index <= last; index++)
list[index] = temp[index];
}
public static void shellSort(int list[])
{
int count = 0;
int n = list.length;
for(int gap = n / 2; gap > 0; gap = gap == 2 ? 1: (int) (gap/2.2))
for(int i = gap; i < n; i++)
{
int temp = list[i];
int j = i;
count++;
for( ; j >= gap && (temp < (list[j - gap])); j -= gap)
{
list[j] = list[j - gap];
count++;
}
list[j] = temp;
}
System.out.println("counter" + count);
}
public static void quickSort(int start, int finish, int list[])
{
int count = 0;
int left = start, right = finish, pivot, temp;
pivot = list[(start + finish) / 2];
do
{
while(list[left] < pivot)
{
left++;
quickcount++;
}
while(pivot < list[right])
{
right--;
quickcount++;
}
if(left <= right)
{
temp = list[left];
list[left++] = list[right];
list[right--] = temp;
quickcount++;
}
} while(left < right);
if(start < right)
quickSort(start, right, list);
if(left < finish)
quickSort(left, finish, list);
}
public static void copy(int list[])
{
for(int i = 0; i < list.length; i++)
X[i] = list[i];
}
public static void restore(int list[])
{
for(int i = 0; i < list.length; i++)
list[i] = X[i];
}
public static void displayArray(int list[])
{
for(int k = 0; k < list.length; k++)
System.out.print(list[k] + " ");
System.out.println();
}
public static void main(String args[])
{
int[] A = new int[100];
for(int i = 0; i < A.length; i++)
A[i] = i + 1;
int[] B = new int[100];
int q = 100;
for(int i = 0; i < B.length; i++)
B[i] = q--;
int[] C = new int[100];
for(int i = 0; i < C.length; i++)
C[i] = (int)(Math.random() * 100 + 1);
displayArray(A);
copy(A);
selectionSort(A);
displayArray(A);
restore(A);
}
Note that QuickSort performance is greatly influenced by your choice of the pivot. With both of your test arrays sorted (ascending / descending) and because you are picking pivot as array[length/2] you are actually always picking the best pivot. So your test case B won't generate maximum number of comparisons for quicksort. If you were picking array[0] as pivot you'd get maximum number of comparisons for test case A and B.
The easiest way to count comparisons is to use a compare function and do it in there.
static int compareCount = 0;
int compareInt(int a, int b) {
compareCount++;
return a - b; // if 0 they are equal, if negative a is smaller, if positive b is smaller
}
Now just use compareInt in all your algorithms and you'll get an accurate count. You'll have to reset compareCount between each run though.

Categories