Target element is given and find the ceiling of that element - java

What I tried
here I've used order agnostic binary search
I've tried creating a method called webs inside which I declared a boolean variable to check whether the array is sorted in ascending or descending order(considering that order in unknown) and further I used an if condition for the same.
//find the ceiling of a number
//ceiling of a given number is the smallest element
//in the array greater than or equal to target element
public class webs{
public static void main(String[] args){
int arr[] = {-18, -12, -4, 0, 2, 3, 4, 15, 16, 18, 22, 45, 89};
int target = 45;
int sol = ceiling(arr, target);
System.out.println(sol);
}
static int ceiling(int arr[], int target){
int ans = Integer.MIN_VALUE;
int start = 0;
int end = arr.length-1;
while(start <= end){
int mid = start + (end - start)/2;
boolean isAsc = arr[start] < arr[end];
if(isAsc){
if(arr[mid] < target){
start = mid + 1;
} else{
end = mid - 1;
}
}else{
if(arr[mid] > target){
start = mid + 1;
}else{
end = mid - 1;
}
}
for(int nums: arr){
if(nums > target){
if(nums > ans){
ans = nums;
}
}
}
return ans;
}
return start;
}
}
I want it to return ceiling of the target element
Output
it is returning the greatest number present in the array

What you can do is simply perform a normal binary search. If the target is found at index i, then the ceiling is at i. If the target is not found, then the ceiling is the index where it stops.
static int ceiling(int[] arr, int target){
int low = 0, high = arr.length-1;
while(true){
int mid = (low+high)/2;
if (low >= high) return arr[low];
if (arr[mid] == target) return arr[mid];
else if (target > arr[mid]) low = mid+1;
else if (target < arr[mid]) high = mid-1;
}
}
public static void main(String[] args){
int arr[] = {-18, -12, -4, 0, 2, 3, 4, 15, 16, 18, 22, 45, 89, 100};
int target = 31;
int sol = ceiling(arr, target);
System.out.println(sol);
}

Related

Search an element in sorted 2d matrix

package kunal;
import java.util.Arrays;
public class SortedMatrix {
public static void main(String[] args) {
int[][] matrix = {
{20, 30, 40, 45},
{50, 55, 60, 65, 66, 67},
{70, 71, 72, 73},
{74, 75, 78, 80}
};
int target = 67;
System.out.println(Arrays.toString(search(matrix, target)));
}
static int[] search(int[][] matrix, int target) {
// return the index of floor number
int floorIndex = floor(matrix, target);
int binarySearch = binarySearch(matrix, target, floorIndex);
if(binarySearch != -1) {
return new int[] {floorIndex, binarySearch};
}
return new int[] {-1, -1};
}
static int floor(int[][] matrix, int target) {
int start = 0;
int end = matrix.length - 1;
int colFix = 0;
while(start <= end) {
int mid = start + (end - start)/2;
if(target == matrix[mid][colFix]) {
return mid;
}
if(target > matrix[mid][colFix]) {
start = mid + 1;
}else {
end = mid - 1;
}
}
return end;
}
static int binarySearch(int[][] matrix, int target, int floorIndex) {
int start = 0;
int end = matrix[floorIndex].length - 1;
int rowFix = floorIndex;
while(start <= end) {
int mid = start + (end - start)/2;
if(target == matrix[rowFix][mid]) {
return mid;
}
if(target > matrix[rowFix][mid]) {
start = mid + 1;
}else {
end = mid - 1;
}
}
return -1;
}
}
In this code first I find the floor(largest number smaller than or equal to the traget) in the first column. after that applying the binary search in the row where i found floor.
this code works on eclispe editor. And successfully run on leetcode too but when i try to submit it shows runtime error. "index -1 out of bond for length 1". please correct the code

I am not sure what is wrong with my quick select method

So I tried to write a code to select kth smallest element in a given input integer array using quick sort, but for some reason as you can see in the code below,
public static int partition(int[] input, int first, int end) {
int pivot = input[(first + end)/2];
int i = first - 1;
int j = end + 1;
while (true) {
do {
i++;
} while (input[i] < pivot);
do {
j--;
} while (input[j] > pivot);
if (i < j)
swap(input, i, j);
else
return j;
}
}
public static void swap(int[] input, int i, int j){
int temp = input[i];
input[i] = input[j];
input[j] = temp;
}
public static int select(int[] input, int k){
return mySelect(input, 0, input.length-1, k);
}
public static int mySelect(int[] input, int left, int right, int k){
// If k is smaller than number of elements in array
if (k > 0 && k <= right - left + 1) {
int pos = partition(input, left, right);
if (pos - left == k - 1)
return input[pos];
// If position is larger, recursive call on the left subarray
if (pos - left > k - 1)
return mySelect(input, left, pos-1, k);
// if smaller, recursive call on the right subarray
return mySelect(input, pos+1, right, k-pos+left-1);
}
System.out.println("Invalid k value");
return Integer.MAX_VALUE;
}
public static void main(String[] args){
test2 = new int[]{99, 44, 77, 22, 55, 66, 11, 88, 33};
int[] test2 = new int[]{99, 44, 77, 22, 55, 66, 11, 88, 33};
//testing for selecting kth min
System.out.println("The 1st smallest : " + select(test2, 1));
System.out.println("The 2nd smallest : " + select(test2, 2));
System.out.println("The 3rd smallest : " + select(test2, 3));
System.out.println("The 4th smallest : " + select(test2, 4));
System.out.println("The 6th smallest : " + select(test2, 6));
System.out.println("The 9th smallest : " + select(test2, 9));
}
but my 1st smallest element appears 22, 2nd smallest returns 11, while others values are normal.
can someone please help me find what is the mistake I made?
The problem in your code is in the partition. The do while is the culprit here. You are updating the positions before checking the conditions and that's causing the problem with the last swap operation.
Update your method to this and you will be good to go
public static int partition(int[] input, int first, int end) {
int pivot = input[(first + end)/2];
int i = first;
int j = end;
while (true) {
while (input[i] < pivot) {
i++;
}
while (input[j] > pivot) {
j--;
}
if (i < j)
swap(input, i, j);
else
return j;
}
}
I wrote this code while I was learning quick sort. The mistake I made was in not realizing that
'left' and 'right' are indices in array whereas,
'pivot' is one of the values stored in array
You can study my code below and determine what's wrong in your understanding of the algorithm!!
public class QuickSort
{
public static void main(String[] args)
{
int[] nums = {1,5,9,2,7,8,4,2,5,8,9,12,35,21,34,22,1,45};
quickSort(0,nums.length-1,nums);
//print nums to see if sort is working as expected,omit printing in your case
print(nums);
//now you can write code to select kth smallest number from sorted nums here
}
/**
* left and right are indices in array whereas
* pivot is one of the values stored in array
*/
static int partition(int left, int right , int pivot, int[] nums)
{
int leftIndex = left -1;
int rightIndex = right;
int temp = 0;
while(true)
{
while( nums[++leftIndex] < pivot );
while( rightIndex>0 && nums[--rightIndex] > pivot );
if( leftIndex >= rightIndex ) break;
else//swap value at leftIndex and rightIndex
{
temp = nums[leftIndex];
nums[leftIndex]= nums[rightIndex];
nums[rightIndex] = temp;
}
}
//swap value at leftIndex and initial right index
temp = nums[leftIndex];
nums[leftIndex]= nums[right];
nums[right] = temp;
return leftIndex;
}
static void quickSort( int leftIndex , int rightIndex ,int[] nums)
{
if( rightIndex-leftIndex <= 0 ) return;
else
{
int pivot = nums[rightIndex];
int partitionIndex = partition(leftIndex, rightIndex , pivot,nums);
quickSort(leftIndex,partitionIndex-1,nums);
quickSort(partitionIndex+1,rightIndex,nums);
}
}
static void print(int[] nums)
{
for( int i = 0 ; i < nums.length ; i++ )
{
System.out.print(nums[i]+", ");
}
}
}

Quick Sort not sorting iterative solution

I currently have the below code for my quick sort. As you can see it is not producing the correct output. Any help will be greatly appreciated. I need the pivot to be the first item in the array. As you can also see i am measuring the time it takes to run, but please ignore that for the time being.
edit: to be specific it works correctly when i have a list in descending order and ascending order(already sorted), but when i try a random list it does not work.
Output:
QuickSort:
Quick Sort Took 181023 nanoseconds
Quick Sort Took 0 milliseconds
Sorted Quick Sort: 25, 12, 17, 13, 20, 7, 5, 16, 11, 26, 24, 18, 9, 4, 21, 1, 23, 27, 15, 19, 28, 14, 8, 22, 6, 3, 2, 10, 29, 40, 37, 32, 44, 38, 35, 41, 39, 31, 42, 30, 43, 36, 34, 33, 45, 46, 47, 48, 49, 50,
Code:
class QuickSort {
public static int Partition(int[] numbers, int left, int right){
//selects the first item at position [0] as the pivot
//left is given 0 when the method is called
int pivot = numbers[left];
while (true)
{
while (numbers[left] < pivot)
left++;
while (numbers[right] > pivot)
right--;
if (left < right)
{
int temp = numbers[right];
numbers[right] = numbers[left];
numbers[left] = temp;
}
else
{
return right;
}
}
}
//method to check for special cases
public static void QuickSort_Check(int[] numbers, int left, int right)
{
//special case of 2 items to be sorted
if(right == 1){
if(numbers[0] >= numbers[1]){
System.out.print("This is a special case of 2 inputs: ");
System.out.print(numbers[1] + ", " + numbers[0]);
System.exit(0);
}
else {
System.out.print("This is a special case of 2 inputs: ");
System.out.print(numbers[0] + ", " + numbers[1]);
System.exit(0);
}
System.exit(0);
}
//special case of 1 item to be sorted
else if (right == 0){
System.out.print("This is a special case of 1 input: ");
System.out.print(numbers[0]);
System.exit(0);
}
else {
QuickSort_Iterative(numbers, left, right);
}
}
public static class QuickPosInfo
{
public int left;
public int right;
};
public static QuickPosInfo spot = new QuickPosInfo();
public static void QuickSort_Iterative(int[] numbers, int left, int right)
{
if(left >= right)
return; // Invalid index range
LinkedList<QuickPosInfo> list = new LinkedList< QuickPosInfo>();
spot.left = left;
spot.right = right;
list.add(spot);
while(true)
{
if(list.size() == 0)
break;
left = list.get(0).left;
right = list.get(0).right;
list.remove(0);
int pivot = Partition(numbers, left, right);
if(pivot > 1)
{
spot.left = left;
spot.right = pivot - 1;
list.add(spot);
}
if(pivot + 1 < right)
{
spot.left = pivot + 1;
spot.right = right;
list.add(spot);
}
}
}
}
This partition method correctly sorted half the array, then did not sort the other half so I believe the problem is in your QuickSort_Iterative(); when the pivot equals 21 it just infinitely swaps 20 and 21.
private static int partition(int[] arr,int left,int right) {
int pivot = arr[right];
int small = left-1;
for(int k = left;k < right;k++)
{
if(arr[right] <= pivot)
{
small++;
swap(arr,right,small);
}
}
swap(arr,right,small+1);
System.out.println("Pivot= "+arr[small+1]);//prints out every sort
System.out.println(Arrays.toString(arr));
return small+1;
}
private static void swap(int[] arr, int k, int small) {//easy swap method
int temp;
temp = arr[k];
arr[k] = arr[small];
arr[small] = temp;
}
UPDATE
Here is the requested method. I believe that the problem with your original one is that you are not modifying that values of left and right properly as the array is sorted.
void QuickSort(int arr[], int left, int right)
{
// create auxiliary stack
int stack[] = new int[right-l+1];
// initialize top of stack
int top = -1;
// push initial values in the stack
stack[++top] = left;
stack[++top] = right;
// keep popping elements until stack is not empty
while (top >= 0)
{
// pop right and l
right = stack[top--];
left = stack[top--];
// set pivot element at it's proper position
int p = partition(arr, left, right);
// If there are elements on left side of pivot,
// then push left side to stack
if ( p-1 > left )
{
stack[ ++top ] = l;
stack[ ++top ] = p - 1;
}
// If there are elements on right side of pivot,
// then push right side to stack
if ( p+1 < right )
{
stack[ ++top ] = p + 1;
stack[ ++top ] = right;
}
}
}
I don't know that will help you out or not you can also try the below code for same.
public class Demo {
private int array[];
private int length;
public void sort(int[] inputArr) {
if (inputArr == null || inputArr.length == 0) {
return;
}
this.array = inputArr;
length = inputArr.length;
quickSort(0, length - 1);
}
private void quickSort(int lowerIndex, int higherIndex) {
int i = lowerIndex;
int j = higherIndex;
int pivot = array[lowerIndex+(higherIndex-lowerIndex)/2];
while (i <= j) {
while (array[i] < pivot) {
i++;
}
while (array[j] > pivot) {
j--;
}
if (i <= j) {
exchangeNumbers(i, j);
i++;
j--;
}
}
if (lowerIndex < j)
quickSort(lowerIndex, j);
if (i < higherIndex)
quickSort(i, higherIndex);
}
private void exchangeNumbers(int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static void main(String a[]){
Demo sorter = new Demo();
int[] input = {8,693,29,3,2,8,29,82,4,26,2,62,82,6,52,9,42,6,52,66,2,8};
sorter.sort(input);
for(int i:input){
System.out.print(i);
System.out.print(" ");
}
}
}

Searching a sorted list with two different algorithms to find if there exists an index i such that X[i]=i

Note that the list will never contain duplicates.
The list is loaded from a text file and is the following 1,2,3,4,5,6,7,8,9.
My first choice since the list is sorted was a linear search and worked fine. Then I tried to use binary search but it does not work correctly.
Here is the code:
public boolean binarySearch() {
int i=0;
int size = list.size() - 1;
while (i <= size) {
int mid = (i + size) / 2;
if (mid == list.get(mid)) {
return true;
}
if (mid < list.get(mid)) {
size = mid - 1;
} else {
i = mid + 1;
}
}
return false;
}
Here is an O(log n) solution.
public static void main(String args[]) {
System.out.println(binarySearch(new int[] {-100, -50, -30, 3, 500, 800}));
System.out.println(binarySearch(new int[] {-100, -50, -30, 42, 500, 800}));
System.out.println(binarySearch(new int[] {-8, 1, 2, 3, 4, 100, 200, 300, 500, 700, 9000}));
}
// Searches for a solution to x[i]=i, returning -1 if no solutions exist.
// The algorithm only works if the array is in ascending order and has no repeats.
// If there is more than one solution there is no guarantee which will
// be returned. Worst case time complexity O(log n) where n is length of array.
public static int binarySearch(int[] x) {
if (x == null || x.length == 0)
return -1;
int low = 0;
if (x[low] == low)
return 0;
else if (x[low] > low)
return -1;
int high = x.length - 1;
if (x[high] == high)
return high;
else if (x[high] < high)
return -1;
while (high - low >= 2) {
int mid = (high + low) / 2;
if (x[mid] == mid)
return mid;
else if (x[mid] > mid)
high = mid;
else low = mid;
}
return -1;
}
public class NewMain1 {
public static void main(String[] args) {
int [] x = {1,2,3,4,5,6};
int value = 7;
boolean check = binarySearch(x,value);
System.out.println(check);
}
public static boolean binarySearch(int [] list , int value) {
int i=0;
int size = list.length - 1;
while (i <= size) {
int mid = (i + size) / 2;
if (value == list[mid]) {
return true;
}
if (value < list[mid]) {
size = mid - 1;
} else {
i = mid + 1;
}
}
return false;
}
I think this could help you

Maximum Sum SubArray

I am trying to find the contiguous subarray within an array which has the largest sum. So, for the array
{5, 15, -30, 10, -5, 40, 10}
the maximum sum possible using those numbers contiguously would be 55, or (10 + (-5) + 40 + 10) = 55. The program below outputs the maximum sum of 55, however, the problem I am trying to figure out is how to print the sequence that produces this 55. In other words, how can I print out the 10, -5, 40, and 10?
public static void main(String[] args) {
int[] arr = {5, 15, -30, 10, -5, 40, 10};
System.out.println(maxSubsequenceSum(arr));
}
public static int maxSubsequenceSum(int[] X) {
int max = X[0];
int sum = X[0];
for (int i = 1; i < X.length; i++) {
sum = Math.max(X[i], sum + X[i]);
max = Math.max(max, sum);
}
return max;
}
I was thinking of creating an ArrayList to store the sum values at every index of i, so the ArrayList would look like (5, 20, -10, 10, 5, 45, 55). And then I was planning on clearing the ArrayList from index 0 to the first negative number in the list, however, this only solves the problem for this specific example, but if I change the original array of numbers, this solution won't work.
You can replace Math.Max functions by if statements and update start and end index of the best subarray. Pascal version:
if X[i] > sum + X[i] then begin
sum := X[i];
start := i;
end
else
sum := sum + X[i];
if max < sum then begin
max := sum;
finish := i;
end;
You can track the starting and ending indexes of the current best subarray in your loop. Instead of using max() to compute sumand max, just do the following :
int sum_start = 0, sum_end = 0, start = 0, end = 0;
// In the for loop
if (X[i] > sum + X[i]) {
sum = X[i];
sum_start = i;
sum_end = i;
} else {
++sum_end;
}
if (sum > max) {
start = sum_start;
end = sum_end;
max = sum;
}
there is an o(n) solution, a single for loop through the array and reset your sub-sequence whenever your current total is below 0.
{5, 15, -30, 10, -5, 40, 10}
5 + 15 = 20
20 - 30 = -10 (reset sub-sequence)
10 -5 +40 +10 = 55
end. 55 is max sub-sequence
edit: to get subsequence...
whenever you change max, update your subsequence
current left index changes only when u reset
current right index changes every iteration
new max -> save current left and right index...
It can be done by capturing the start and end while identifying maximum sub-array as follows:
Code
package recursion;
import java.util.Arrays;
public class MaximumSubArray {
private static SubArray maxSubArray(int[] values, int low, int high) {
if (low == high) {
// base condition
return new SubArray(low, high, values[low]);
} else {
int mid = (int) (low + high) / 2;
// Check left side
SubArray leftSubArray = maxSubArray(values, low, mid);
// Check right side
SubArray rightSubArray = maxSubArray(values, mid + 1, high);
// Check from middle
SubArray crossSubArray = maxCrossSubArray(values, low, mid, high);
// Compare left, right and middle arrays to find maximum sub-array
if (leftSubArray.getSum() >= rightSubArray.getSum()
&& leftSubArray.getSum() >= crossSubArray.getSum()) {
return leftSubArray;
} else if (rightSubArray.getSum() >= leftSubArray.getSum()
&& rightSubArray.getSum() >= crossSubArray.getSum()) {
return rightSubArray;
} else {
return crossSubArray;
}
}
}
private static SubArray maxCrossSubArray(int[] values, int low, int mid,
int high) {
int sum = 0;
int maxLeft = low;
int maxRight = high;
int leftSum = Integer.MIN_VALUE;
for (int i = mid; i >= low; i--) {
sum = sum + values[i];
if (sum > leftSum) {
leftSum = sum;
maxLeft = i;
}
}
sum = 0;
int rightSum = Integer.MIN_VALUE;
for (int j = mid + 1; j <= high; j++) {
sum = sum + values[j];
if (sum > rightSum) {
rightSum = sum;
maxRight = j;
}
}
SubArray max = new SubArray(maxLeft, maxRight, (leftSum + rightSum));
return max;
}
static class SubArray {
private int start;
private int end;
private int sum;
public SubArray(int start, int end, int sum) {
super();
this.start = start;
this.end = end;
this.sum = sum;
}
public int getStart() { return start; }
public void setStart(int start) { this.start = start; }
public int getEnd() { return end; }
public void setEnd(int end) { this.end = end; }
public int getSum() { return sum; }
public void setSum(int sum) { this.sum = sum; }
#Override
public String toString() {
return "SubArray [start=" + start + ", end=" + end + ", sum=" + sum + "]";
}
}
public static final void main(String[] args) {
int[] values = { 5, 15, -30, 10, -5, 40, 10 };
System.out.println("Maximum sub-array for array"
+ Arrays.toString(values) + ": " + maxSubArray(values, 0, 6));
}
}
Output
Maximum sub-array for array[5, 15, -30, 10, -5, 40, 10]: SubArray [start=3, end=6, sum=55]
Solution can be downloaded from https://github.com/gosaliajigar/Programs/blob/master/src/recursion/MaximumSubArray.java
Two subarray are
[1, 2, 3]
and [4, 9] excluding the negative number
The max sub array here is [ 4, 5]
so the output is 9
Here is the code
public class MaxSubArray{
static void sumM(int a[], int n){
int s1 = Integer.MAX_VALUE;
int k = Integer.MAX_VALUE;
int sum = 0;
int s2 = 0;
for(int i=0;i<n;i++){
if(a[i]<s1){
if(a[i]<0){
k = Math.min(a[i],s1);
}
}
if(a[i]>k){
sum+=a[i];
}
if(a[i]<k){
if(a[i]<0){
continue;
}
s2+=a[i];
}
}
if(sum>s2){
System.out.println(sum);
}
else{
System.out.println(s2);
}
}
public static void main(String[] args){
int a[] = {1,2,3,-7,4,5};
int n = a.length;
sumM(a,n);
}
}
public static int kadane(int[] A) {
int maxSoFar = 0;
int maxEndingHere = 0;
// traverse the given array
for (int i: A) {
// update the maximum sum of subarray "ending" at index `i` (by adding the
// current element to maximum sum ending at previous index `i-1`)
maxEndingHere = maxEndingHere + i;
// if the maximum sum is negative, set it to 0 (which represents
// an empty subarray)
maxEndingHere = Integer.max(maxEndingHere, 0);
// update the result if the current subarray sum is found to be greater
maxSoFar = Integer.max(maxSoFar, maxEndingHere);
}
return maxSoFar;
}
var maxSequence = function(arr){
// ...
if (arr.every((ele) => ele >= 0)) {
return arr.reduce((sum, ele) => sum + ele, 0);
} else if (arr.every((ele) => ele < 0)) {
return 0;
//for me the maximum would be the biggest negative number
//arr.reduce((max, elm) => (max > elm ? max : elm))
} else if (arr === [0]) {
return 0;
} else {
let maxSum = [];
let currentSum = 0;
for (let i = 0; i < arr.length; i++) {
currentSum = Math.max(arr[i], currentSum + arr[i]);
maxSum.push(currentSum);
}
return maxSum.reduce((max, elm) => (max > elm ? max : elm));
}
}
you need to sum all possible sub array. to do that, you can do this code
public static int maxSubsequenceSum(int[] X) {
int max = 0;
boolean max_init = false;
int max_from=0;
int max_to=0; // this is not included
for (int i = 0; i < X.length; i++) {
for (int j = i + 1; j < X.length + 1; j++) {
int total = 0;
for (int k = i; k < j; k++) {
total += X[k];
}
if (total > max || !max_init){
max = total;
max_init = true;
max_from = i;
max_to = j;
}
}
}
for (int i=max_from;i<max_to;i++)
System.out.print(X[i]+",");
System.out.println();
return max;
}

Categories

Resources