Linear Search Algorithm of an Array in reverse order - java

I need to find out an element on an array in reverse manner i.e, checking elements from last element to first
Here is my code
public static int linearSearch(int[] array, int key) {
int size = array.length - 1;
for (int i = size; i > 0; i--) {
if (array[i] == key) {
return i;
}
}
return -1;
}
Here my test testcase -
count = 10
array = 44 55 66 77 88 22 11 66 99 33
key = 66
its output came 7 which is wrong
its actual output was clearly 2.
I don't know where my logic gone wrong.
Also I don't know how to implement this (if the key is repeated, print the index where the key is appearing for the first time in reverse order.)

So after a few inconsitencies regarding what you actually want, I think I got you now. This code should work for you:
public static void main(String[] args) {
int[] array = { 44, 55, 66, 77, 88, 22, 11, 66, 99, 33 };
int key = 66;
int result = linearSearch(array, key);
System.out.println("Index from the right for value " + key + " is: " + result);
}
public static int linearSearch(int[] array, int key) {
int size = array.length - 1;
for (int i = size; i >= 0; i--) {
if (array[i] == key) {
return size - i;
}
}
return -1;
}
The output is:
Index from the right for value 66 is: 2
Explanation:
The for-loop loops from size to 0 backwards. If a match is found, it returns the index from the right, so size - i.

If you are trying to return the number of iterations from the end, you can create an int and return the iteration value
public static int linearSearch(int[] array, int key) {
int size = array.length - 1;
int iteration =-1;
for (int i = size; i >= 0; i--) {
iteration++;
if (array[i] == key) {
return iteration;
}
}
return -1;
}

If you also want to return a "reversed" index, you must take that into account in your return statement:
public static int linearSearch(int[] array, int key)
{
int size = array.length - 1;
for (int i = size; i > 0; i--)
if (array[i] == key)
return size - i;
return -1;
}

Related

Java find value in column wise sorted matrix

I am currently in my first year of university and my teacher gave us an interesting problem
Given the 2 dimensional array m (the column length is equal to the row length for example 4x4, 3x3)
We know that if m goes through the function test it will return true
Now we need to write a function that based on that information will find the given value in m and return false or true if was found. In addition, the function must be with time complexity of O(n) or less when n is the length of row/column (For example if the matrix is 5x5 then n is 5). The function cannot use recursion
Here is function test:
public static boolean test(int [][] m)
{
int n=m.length;
for(int r=0; r<(n-1); r++)
for (int c=0; c<n; c++)
for (int i=0; i<n; i++)
if(m[r][c] > m[r+1][i]) return false;
return true;
}
Here is an example for a matrix that I came up with that returns true:
1, 3, 2, 5
10, 9, 7, 15
17, 25, 16, 20
50, 30, 28, 40
Here is a possible function signature:
public static boolean findValTest (int [][] m, int val)
Thanks for everyone who answers!
Update: Here's an O(nlogn) solution, we need further discussion to find a number in one column in O(1).
public static boolean findValTest(int[][] m, int val) {
for (int c = 0; c < m.length; c++) {
if (val < m[c][0] || val > m[c][m[c].length - 1]) continue;
if (binarySearch(m, c, val)) return true;
}
return false;
}
private static boolean binarySearch(int[][] m, int col, int key) {
int low = 0, high = m[col].length - 1;
while (low <= high) {
int mid = low + ((high - low) / 2);
if (m[mid][col] < key) {
low = mid + 1;
} else if (m[mid][col] > key) {
high = mid - 1;
} else if (m[mid][col] == key) {
return true;
}
}
return false;
}
I have managed to figure it out. It is basically O(3n) but since 3 is constant it is O(n).
Basically we use the first column to give us the index of two rows where the value might be in.
For example if we use the matrix we I gave as an example and the value is 16 we go like this:
Is val between 1 and 10? No.
Is val between 10 and 17? Yes
Search second row and third row.
Here is the code(It is kinda long and ugly but hopefully you will understand it):
// We search in the first column between what two numbers the value is,
// Then we search for row of the first index, if not there we search the row of the other index
// Time Complexity: O(n). We go through the first column which is O(n) and then we go over 2 rows which is O(2n). Together its O(3n) but because 3 is constant the time is O(n)
public static boolean findValTest(int[][] m, int val) {
int[] index = whichRows(m,val);
if(index[0] == -1 && index[1] == -1) // Indicator that the number was found in the first column
return true;
if(index[1] == -1){
// We search in only one row
for(int i = 0; i < m.length - 1; i++){
if(val == m[index[0]][i]) {
return true;
}
}
}
else {
// Search both given rows by index
for(int i = 0; i < index.length; i++){
for(int j = 0; j < m.length; j++) {
if(val == m[index[i]][j])
return true;
}
}
}
return false;
}
public static int[] whichRows(int[][] m, int val) {
int[] index = {0,0}; int len = m.length;
// -1 in the index indicates that only one row needs to be searched, or the first or the last
if(m[len-1][0] < val) // Only the last row(Which contains the biggest numbers in the matrix) needs to be searched
{
index[0] = len-1; index[1] = -1;
}
else if(m[0][0] > val){ // Only the first row needs to be searched
index[0] = 0; index[1] = -1;
}
else { // We search between
for(int i = 0; i < len - 1; i++){
if(m[0][i] == val)
{
index[0] = -1; index[1] = -1;
return index;
}
if(m[i][0] < val && val < m[i+1][0]){
index[0] = i; index[1] = i +1;
break;
}
}
}
return index;
}
just wanted to update you that your code doesn't work at certain times.
Wanted to give you a breakdown but unfortunately something came up and I will have to go for the next couple of days, so it is my hope that you fix whatever's plaguing your design.
Try to test it with other numbers and see for yourself.
I tested it with the following matrix:
int[][] matrix = {
{13, 2, 17, 29},
{52, 54, 62, 73},
{140, 120, 111, 100},
{235, 245, 255, 265},
};
and used 265 and 235 as inputs, to which the output was false.
Good luck :)

Largest 5 in array of 10 numbers without sorting

Here's my code to find the max number in an array of numbers, but i can't seem to understand how to get the top 5 numbers and store them in an array and later retrieve them
Here's the code:
public class Max {
public static void main (String[] args)
{
int i;
int large[]=new int[5];
int array[] = {33,55,13,46,87,42,10,34,43,56};
int max = array[0]; // Assume array[0] to be the max for time-being
//Looping n-1 times, O(n)
for( i = 1; i < array.length; i++) // Iterate through the First Index and compare with max
{
// O(1)
if( max < array[i])
{
// O(1)
max = array[i];// Change max if condition is True
large[i] = max;
}
}
for (int j = 0; j<5; j++)
{
System.out.println("Largest 5 : "+large[j]);
}
System.out.println("Largest is: "+ max);
// Time complexity being: O(n) * [O(1) + O(1)] = O(n)
}
}
I'm using an array to store 5 numbers, but when i run it, it is not what i want.
Can anyone help me with the program?
The optimum data structure to retrieve top n items from a larger collection is the min/max heap and the related abstract data structure is called the priority queue. Java has an unbounded PriorityQueue which is based on the heap structure, but there is no version specialized for primitive types. It can used as a bounded queue by adding external logic, see this comment for details..
Apache Lucene has an implementation of the bounded priority queue:
http://grepcode.com/file/repo1.maven.org/maven2/org.apache.lucene/lucene-core/5.2.0/org/apache/lucene/util/PriorityQueue.java#PriorityQueue
Here is a simple modification that specializes it for ints:
/*
* Original work Copyright 2014 The Apache Software Foundation
* Modified work Copyright 2015 Marko Topolnik
*
* Licensed under the Apache License, Version 2.0 (the "License");
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** A PriorityQueue maintains a partial ordering of its elements such that the
* worst element can always be found in constant time. Put()'s and pop()'s
* require log(size) time.
*/
class IntPriorityQueue {
private static int NO_ELEMENT = Integer.MIN_VALUE;
private int size;
private final int maxSize;
private final int[] heap;
IntPriorityQueue(int maxSize) {
this.heap = new int[maxSize == 0 ? 2 : maxSize + 1];
this.maxSize = maxSize;
}
private static boolean betterThan(int left, int right) {
return left > right;
}
/**
* Adds an int to a PriorityQueue in log(size) time.
* It returns the object (if any) that was
* dropped off the heap because it was full. This can be
* the given parameter (in case it isn't better than the
* full heap's minimum, and couldn't be added), or another
* object that was previously the worst value in the
* heap and now has been replaced by a better one, or null
* if the queue wasn't yet full with maxSize elements.
*/
public void consider(int element) {
if (size < maxSize) {
size++;
heap[size] = element;
upHeap();
} else if (size > 0 && betterThan(element, heap[1])) {
heap[1] = element;
downHeap();
}
}
public int head() {
return size > 0 ? heap[1] : NO_ELEMENT;
}
/** Removes and returns the least element of the PriorityQueue in log(size)
time. */
public int pop() {
if (size > 0) {
int result = heap[1];
heap[1] = heap[size];
size--;
downHeap();
return result;
} else {
return NO_ELEMENT;
}
}
public int size() {
return size;
}
public void clear() {
size = 0;
}
public boolean isEmpty() {
return size == 0;
}
private void upHeap() {
int i = size;
// save bottom node
int node = heap[i];
int j = i >>> 1;
while (j > 0 && betterThan(heap[j], node)) {
// shift parents down
heap[i] = heap[j];
i = j;
j >>>= 1;
}
// install saved node
heap[i] = node;
}
private void downHeap() {
int i = 1;
// save top node
int node = heap[i];
// find worse child
int j = i << 1;
int k = j + 1;
if (k <= size && betterThan(heap[j], heap[k])) {
j = k;
}
while (j <= size && betterThan(node, heap[j])) {
// shift up child
heap[i] = heap[j];
i = j;
j = i << 1;
k = j + 1;
if (k <= size && betterThan(heap[j], heap[k])) {
j = k;
}
}
// install saved node
heap[i] = node;
}
}
The way you implement betterThan decides whether it will behave as a min or max heap. This is how it's used:
public int[] maxN(int[] input, int n) {
final int[] output = new int[n];
final IntPriorityQueue q = new IntPriorityQueue(output.length);
for (int i : input) {
q.consider(i);
}
// Extract items from heap in sort order
for (int i = output.length - 1; i >= 0; i--) {
output[i] = q.pop();
}
return output;
}
Some interest was expressed in the performance of this approach vs. the simple linear scan from user rakeb.void. These are the results, size pertaining to the input size, always looking for 16 top elements:
Benchmark (size) Mode Cnt Score Error Units
MeasureMinMax.heap 32 avgt 5 270.056 ± 37.948 ns/op
MeasureMinMax.heap 64 avgt 5 379.832 ± 44.703 ns/op
MeasureMinMax.heap 128 avgt 5 543.522 ± 52.970 ns/op
MeasureMinMax.heap 4096 avgt 5 4548.352 ± 208.768 ns/op
MeasureMinMax.linear 32 avgt 5 188.711 ± 27.085 ns/op
MeasureMinMax.linear 64 avgt 5 333.586 ± 18.955 ns/op
MeasureMinMax.linear 128 avgt 5 677.692 ± 163.470 ns/op
MeasureMinMax.linear 4096 avgt 5 18290.981 ± 5783.255 ns/op
Conclusion: constant factors working against the heap approach are quite low. The breakeven point is around 70-80 input elements and from then on the simple approach loses steeply. Note that the constant factor stems from the final operation of extracting items in sort order. If this is not needed (i.e., just a set of the best items is enough), the we can simply retrieve the internal heap array directly and ignore the heap[0] element which is not used by the algorithm. In that case this solution beats one like rakib.void's even for the smallest input size (I tested with 4 top elements out of 32).
Look at the following code:
public static void main(String args[]) {
int i;
int large[] = new int[5];
int array[] = { 33, 55, 13, 46, 87, 42, 10, 34, 43, 56 };
int max = 0, index;
for (int j = 0; j < 5; j++) {
max = array[0];
index = 0;
for (i = 1; i < array.length; i++) {
if (max < array[i]) {
max = array[i];
index = i;
}
}
large[j] = max;
array[index] = Integer.MIN_VALUE;
System.out.println("Largest " + j + " : " + large[j]);
}
}
Note: If you don't want to change the inputted array, then make a copy of it and do the same operation on the copied array.
Take a look at Integer.MIN_VALUE.
I get the following output:
Largest 0 : 87
Largest 1 : 56
Largest 2 : 55
Largest 3 : 46
Largest 4 : 43
Here is a simple solution i quickly knocked up
public class Main {
public static void main(String args[]) {
int i;
int large[] = new int[5];
int array[] = { 33, 55, 13, 46, 87, 42, 10, 34, 43, 56 };
for (int j = 0; j < array.length; j++) {
for (i = 4; i >= 0; i--) {
if (array[j] > large[i]) {
if (i == 4) {
large[i] = array[j];
}
else{
int temp = large[i];
large[i] = array[j];
large[i+1] = temp;
}
}
}
}
for (int j = 0; j<5; j++)
{
System.out.println("Largest "+ j + ":"+ large[j]);
}
}
}
Sorting, regular expressions, complex data structures are fine and make programming easy. However, I constantly see them misused nowadays and no one has to wonder:
Even if computers have become thousands of times faster over the past decades, the perceived performance still continues to not only not grow, but actually slows down. Once in your terminal application, you had instant feedback, even in Windows 3.11 or Windows 98 or Gnome 1, you often had instant feedback from your machine.
But it seems that it becomes increasingly popular to not only crack nuts with a sledgehammer, but even corns of wheat with steam hammers.
You don't need no friggin' sorting or complex datastructures for such a small problem. Don't let me invoke Z̴̲̝̻̹̣̥͎̀A̞̭̞̩̠̝̲͢L̛̤̥̲͟͜G͘҉̯̯̼̺O̦͈͙̗͎͇̳̞̕͡. I cannot take it, and even if I don't have a Java compiler at hands, here's my take in C++ (but will work in Java, too).
Basically, it initializes your 5 maxima to the lowest possible integer values. Then, it goes through your list of numbers, and for each number, it looks up into your maxima to see if it has a place there.
#include <vector>
#include <limits> // for integer minimum
#include <iostream> // for cout
using namespace std; // not my style, I just do so to increase readability
int main () {
// basically, an array of length 5, initialized to the minimum integer
vector<int> maxima(5, numeric_limits<int>::lowest());
// your numbers
vector<int> numbers = {33, 55, 13, 46, 87, 42, 10, 34, 43, 56};
// go through all numbers.
for(auto n : numbers) {
// find smallest in maxima.
auto smallestIndex = 0;
for (auto m=0; m!=maxima.size(); ++m) {
if (maxima[m] < maxima[smallestIndex]) {
smallestIndex = m;
}
}
// check if smallest is smaller than current number
if (maxima[smallestIndex] < n)
maxima[smallestIndex] = n;
}
cout << "maximum values:\n";
for(auto m : maxima) {
cout << " - " << m << '\n';
}
}
It is a similar solution to rakeb.voids' answer, but flips the loops inside out and does not have to modify the input array.
Use steam hammers when appropriate only. Learn algorithms and datastructures. And know when NOT TO USE YOUR KUNG-FU. Otherwise, you are guilty of increasing the society's waste unecessarily and contribute to overall crapness.
(Java translation by Marko, signature adapted to zero allocation)
static int[] phresnel(int[] input, int[] output) {
Arrays.fill(output, Integer.MIN_VALUE);
for (int in : input) {
int indexWithMin = 0;
for (int i = 0; i < output.length; i++) {
if (output[i] < output[indexWithMin]) {
indexWithMin = i;
}
}
if (output[indexWithMin] < in) {
output[indexWithMin] = in;
}
}
Arrays.sort(output);
return output;
}
As an alternative to sorting, here is the logic. You figure out the code.
Keep a list (or array) of the top X values found so far. Will of course start out empty.
For each new value (iteration), check against top X list.
If top X list is shorter than X, add value.
If top X list is full, check if new value is greater than any value. If it is, remove smallest value from top X list and add new value.
Hint: Code will be better if top X list is sorted.
If you don't want to sort you can check lower number and it's position and replace. WORKING DEMO HERE.
public static void main(String[] args) {
int array[] = {33,55,13,46,87,42,10,34,43,56};
int mArray[] = new int[5];
int j = 0;
for(int i = 0; i < array.length; i++) {
if (array[i] > lower(mArray)) {
mArray[lowerPos(mArray)] = array[i];
}
}
System.out.println(Arrays.toString(mArray));
}
public static int lower(int[] array) {
int lower = Integer.MAX_VALUE;
for (int n : array) {
if (n < lower)
lower = n;
}
return lower;
}
public static int lowerPos(int[] array) {
int lower = Integer.MAX_VALUE;
int lowerPos = 0;
for (int n = 0; n < array.length; n++) {
if (array[n] < lower) {
lowerPos = n;
lower = array[n];
}
}
return lowerPos;
}
OUTPUT:
[43, 55, 56, 46, 87]
try :
public static int getMax(int max,int[] arr ){
int pos=0;
//Looping n-1 times, O(n)
for( int i = 0; i < arr.length; i++) // Iterate through the First Index and compare with max
{
// O(1)
if( max < arr[i])
{
// O(1)
max = arr[i];// Change max if condition is True
pos=i;
}
}
arr[pos]=0;
return max;
}
public static void main(String[] args) {
int large[]=new int[10];
int array[] = {33,55,13,46,87,42,10,34,43,56};
int k=0;
for(int i=0;i<array.length;i++){
large[k++]=getMax(0,array);
}
System.out.println("Largest 5 is: "+ Arrays.toString(Arrays.copyOf(large,5)));
}
output:
Largest 5 is: [87, 56, 55, 46, 43]
Here is another approach:
public static void main(String args[]){
int i;
int largestSize = 4;
int array[] = {33,55,13,46,87,42,10,34};
// copy first 4 elemets, they can just be the highest
int large[]= Arrays.copyOf(array, largestSize);
// get the smallest value of the large array before the first start
int smallest = large[0];
int smallestIndex = 0;
for (int j = 1;j<large.length;++j) {
if (smallest > large[j]) {
smallest = large[j];
smallestIndex = j;
}
}
// First Loop start one elemnt after the copy
for(i = large.length; i < array.length; i++)
{
// get the smallest value and index of the large array
if(smallest < array[i])
{
large[smallestIndex] = array[i];
// check the next smallest value
smallest = large[0];
smallestIndex = 0;
for (int j = 1;j<large.length;++j) {
if (smallest > large[j]) {
smallest = large[j];
smallestIndex = j;
}
}
}
}
for (int j = 0; j<large.length; j++)
{
System.out.println("Largest 5 : "+large[j]);
}
System.out.println();
System.out.println("Largest is: "+ getHighest(large));
}
private static int getHighest(int[] array) {
int highest = array[0];
for (int i = 1;i<array.length;++i) {
if (highest < array[i]) {
highest = array[i];
}
}
return highest;
}
First of all, you can't use the i constant with large array. i goes up to 10, while large length is 5.
Use a separate variable for that and increment when you add a new value.
Second, this logic is not retrieving the max values, you need to go over your array fully, retrieve the max value and add it to your array. Then you have to it again. You can write a first loop which use large.length as a condition and the inner loop which will use array.length. Or, you can use recursion.
You could do this properly in an OOp way. This maintains a list of the n largest values of a list of offered values.
class Largest<T extends Comparable<T>> {
// Largest so far - null if we haven't yet seen that many.
List<T> largest;
public Largest(int n) {
// Build my list.
largest = new ArrayList(n);
// Clear it.
for (int i = 0; i < n; i++) {
largest.add(i, null);
}
}
public void offer(T next) {
// Where to put it - or -1 if nowhere.
int place = -1;
// Must replace only the smallest replaceable one.
T smallest = null;
for (int i = 0; i < largest.size(); i++) {
// What's there?
T l = largest.get(i);
if (l == null) {
// Always replace null.
place = i;
break;
}
if (l.compareTo(next) < 0) {
// Only replace the smallest.
if (smallest == null || l.compareTo(smallest) < 0) {
// Remember here but keep looking in case there is a null or a smaller.
smallest = l;
place = i;
}
}
}
if (place != -1) {
// Replace it.
largest.set(place, next);
}
}
public List<T> get() {
return largest;
}
}
public void test() {
Integer array[] = {33, 55, 13, 46, 87, 42, 10, 34, 43, 56};
Largest<Integer> l = new Largest<>(5);
for (int i : array) {
l.offer(i);
}
List<Integer> largest = l.get();
Collections.sort(largest);
System.out.println(largest);
// Check it.
List<Integer> asList = Arrays.asList(array);
Collections.sort(asList);
asList = asList.subList(asList.size() - largest.size(), asList.size());
System.out.println(asList);
}
For larger numbers you can improve the algorithm using binarySearch to find the best place to put the new item instead of blindly walking the whole list. This has the added benefit of returning a sorted list.
class Largest<T extends Comparable<T>> {
// Largest so far - null if we haven't yet seen that many.
List<T> largest;
// Limit.
final int n;
public Largest(int n) {
// Build my list.
largest = new ArrayList(n + 1);
this.n = n;
}
public void offer(T next) {
// Try to find it in the list.
int where = Collections.binarySearch(largest, next, Collections.reverseOrder());
// Positive means found.
if (where < 0) {
// -1 means at start.
int place = -where - 1;
// Discard anything beyond n.
if (place < n) {
// Insert here.
largest.add(place, next);
// Trim if necessary.
if (largest.size() > n) {
largest.remove(n);
}
}
}
}
public List<T> get() {
return largest;
}
}
Simple working solution for this for all condition is as given below. Please refer code below and let me know in case of any issue in comments.
public static void main(String[] args) {
int arr[] = {75, 4, 2, 43, 56, 1,66};
int k = 5;
int result = find5thMaxValueApproach3(arr, k);
System.out.println("\n 5th largest element is : " + result);
}
static int find5thMaxValueApproach3(int arr[], int k){
int newMax = 0;
int len = arr.length;
int lastMax = Integer.MAX_VALUE;
for(int j = 0; j < k; j++){
int i = 0;
while(arr[i] >= lastMax )
i++;
if(i >= len)
break;
newMax = arr[i];
for( ; i < len; i++){
if( arr[i] < lastMax && arr[i] > newMax){
newMax = arr[i];
}
}
System.out.println("newMax =" + newMax+ " lastMax="+ lastMax);
lastMax = newMax;
}
return lastMax;
}

Debugging HeapSort Java Code

I have a test program to randomly generate data are randomly generated, and then pass them to the class constructor of class Sorter. Then Sorter will sort the data and pass it back through a method to the main function. I have also implemented several other sorting method as the subclass of the Sorter class, and they work just fine. So I think there're no problems in my Sorter class.
Below is the output of my test program when using heapsort.
Data:
48 96 71 81 78 72 93 52 67 70
Sorted Data:
48 71 81 78 72 67 52 93 70 96
As you can see, data is not sorted after going through the following code. And below is the code.
public class HeapSort extends Sorter{
private int[] heap;
private int size;
public HeapSort(int[] data){
super(data);
}
public void sort(){
constructHeap();
for(int i = size - 1; i >= 0; i--){
numbers[i] = extractMax();
}
}
public void constructHeap(){
size = numbers.length;
heap = new int[size];
for(int j = 0; j < size; j++) heap[j] = numbers[j];
for(int i = size/2 - 1; i >= 0; i--){
fixHeap(i, heap[i]);
}
}
public int extractMax(){
int max = heap[0];
fixHeap(0, heap[--size]);
return max;
}
public void fixHeap(int pos, int key){
if(left(pos) > size) heap[pos] = key; // if current position is leaf
else{
int largest = pos;
int r = right(pos);
int l = left(pos);
if(r < size && heap[largest] < heap[r]) largest = r;
if(l < size && heap[largest] < heap[l]) largest = l;
if(largest == pos) heap[pos] = key;
else{
heap[pos] = heap[largest];
fixHeap(largest, key);
}
}
}
public int left(int i){return 2*i+1;}
public int right(int i){return 2*i+2;}
}
Edited:
Below is the debugged code. Hopefully someone would find it useful.
public class HeapSort extends Sorter{
private int[] heap;
private int size;
public HeapSort(int[] data){
super(data);
}
public void sort(){
constructHeap();
for(int i = size - 1; i >= 0; i--){
numbers[i] = extractMax();
}
}
public void constructHeap(){
size = numbers.length;
heap = new int[size];
for(int j = 0; j < size; j++) heap[j] = numbers[j];
for(int i = size/2 - 1; i >= 0; i--){
fixHeap(i);
}
}
public int extractMax(){
int max = heap[0];
heap[0] = heap[--size];
fixHeap(0);
return max;
}
public void fixHeap(int pos){
if(left(pos) < size){ // if current position is not leaf
int largest = pos;
int r = right(pos);
int l = left(pos);
if(r < size && heap[largest] < heap[r]) largest = r;
if(l < size && heap[largest] < heap[l]) largest = l;
if(largest != pos){
exchange(pos, largest);
fixHeap(largest);
}
}
}
public int left(int i){return 2*i+1;}
public int right(int i){return 2*i+2;}
public void exchange(int a, int b){
int temp = heap[a];
heap[a] = heap[b];
heap[b] = temp;
}
}
I assume you have a debugger, and know how to use it.
In my opinion, the best way to debug complex code is what I call "divide and conquer debugging". Pseudocode:
void debug(Time beforeTheBug, Time afterTheBug) {
do {
Time pivot = between(beforeTheBug, afterTheBug);
if (stateIsAsExceptedAt(pivot)) {
afterTheBug = pivot;
} else {
beforetheBug = pivot;
}
} while (amountOfCodeExecutedBetween(beforeTheBug, afterTheBug) is not trivial);
}
In your case, my first check was the output. Indeed, it was not sorted, so the bug is in this class.
My next check was whether the heap invariant was satisfied after constructHeap. At that time, heap is [96, 48, 93, 81, 78, 72, 71, 52, 67, 70], so the heap invariant is not satisfied (48 is not greater than 78), and a bug occurs during construction of the heap.
Looking at constructHeap() reveals no useful break point, because the first loop is quite simpe, and very unlikely to be wrong, while the second loop (with its call to fixHeap) contains all the complexity.
The first iteration of the loop finds nothing to change, which is correct, as the subtree already satisfies the heap invariant. Same for the second iteration.
The third iteration correctly identifies that the right child is greater than the root, and swaps the two.
The forth iteration finds nothing to change, which is correct.
So it is the very last iteration of the loop that contains the problem. Both children are greater than the parent. fixHeap correctly moves the greater child into the root, and invokes itself recursively. That invocation finds the heap invariant satisfied, and returns. But the invariant is not satisfied after the return.
So the problem is somewhere from detection of the heap invariant to the return. The detection checks:
if (r < size && heap[largest] < heap[r])
largest = r;
if (l < size && heap[largest] < heap[l])
largest = l;
where heap is [96, 96, 93, 81, 78, 72, 71, 52, 67, 70]. Yes, 96 is greater than 81 and 78. But actually, shouldn't heap[pos] == key? Ah, that's what the next statement does...
Put differently, we were checking the heap invariant before completing the previous update, and then finishing that update, which broke the invariant in this case ...

printing arrngements

How can I do arrangements. of numbers... such that each new number formed out of arrangement has at max a difference of 1 from prev maxima.
e.g.
if input is k=1 output will be 1
if k =2 outputs are : 11, 12
2,1 is wrong as left most has to be 1 always.
if k = 3 outputs are: 111,112, 121, 122, 123
if k = 4 : 1111,1112,1121,1122,1123,1212,1211,1213,1223,1221, 1222, 1233, 1234
1423 is wrong diff b/w 1 and 4 is 3.
1243 is wrong diff b/w 2 and 4 is 2....
How I do this using DP, if possible?
This is one of the solution for above question... can anyone help me to understand this code...
Thanks in advance...
public class MaxOneDiff {
public static void main(String[] args) {
int k = 4;
getList(k);
}
public static void getList(int k) {
int arr[] = new int[k];
int index = 0;
printRecList(k, arr, index, k);
}
public static void printRecList(int k, int arr[], int index, int range) {
if (k == 0) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
System.out.println();
} else {
for (int i = 1; i <= range; i++) {
if (index == 0) {
arr[index] = i;
printRecList(k - 1, arr, index + 1, range);
} else {
int t = arr[index-1]-i;
t = t > 0 ? t : -t;
if (t < 2) {
arr[index] = i;
printRecList(k - 1, arr, index + 1, range);
}
}
}
}
}
}
Let's start with the easy part:
public static void getList(int k) {
int arr[] = new int[k];
int index = 0;
printRecList(k, arr, index, k);
}
This is a helper to the Print Recursive List function, just setting up the initial stuff.
public static void printRecList(int k, int arr[], int index, int range) {
This is a recursive function, it should (and does) contain two main parts:
A base case (here, when k==0 )
A non-base case which does something, reducing the problem into smaller problem(s), and recurses.
Base case:
if (k == 0) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]);
}
System.out.println();
If k==0, print out the numbers in the array from left to right, then put a new-line at the end.
Non-Base Case: (the more complicated part)
else {
for (int i = 1; i <= range; i++) {
if (index == 0) {
arr[index] = i;
printRecList(k - 1, arr, index + 1, range);
} else {
int t = arr[index-1]-i;
t = t > 0 ? t : -t;
if (t < 2) {
arr[index] = i;
printRecList(k - 1, arr, index + 1, range);
}
}
}
}
'i' goes from 1 to range,
The helper function calls this with index=0, so the first/top level of recursion, is composed of setting the first element (element 0) of the array to i, and calling the recursive method.
Never again will index == 0 in the recursive calls, so we turn our attention to the else clause.
Here we want to know if we can assign the value i to the next element over, so we check to see if the absolute value of elementToLeft minus i is greater than or equal to 2.
If 'i' is valid to assign in that position (i.e. it is only 1 or 0 different from the value to the left, and 'i' can only get as high as range from the for loop.)
Then we assign it, and check the next position over.
This ends when we have reached the last element in the array.

Error in Finding the nth largest number in the unsorted array (containing duplicates) using median of medians algo O(n)

If an array contains 1,7,7,3,6 and if user asks what 2nd largest element is the output should be 7(not 6) since duplicate values are treated as distinct.
This is my code.
I am using Deterministic search to find the suitable pivot .
Its complexity is O(n).
I am stuck at the error generated by my code .
Please do help me.
import java.util.Random;
import java.util.Scanner;
public class deven {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
int len=in.nextInt();
int n=in.nextInt();
int array[]=new int[len];
for (int i = 0; i < len; i++) {
array[i]=in.nextInt();
}
System.out.println(select(array,len,n));
}
static int below[];
static int above[];
static int pivot;
static int i;
static int j;
static int x;
static int y;
static int index;
static Random rand=new Random();
static int select(int array[],int len,int n){
if(len==1)
return array[0];
pivot=pivot(array, len);
below=new int[len];
above=new int[len];
//System.out.println("Block");
x=0;
y=0;
int temp=0;
for(i=0;i<len;i++){
if(array[i]>pivot){
below[x++]=array[i];
}
else if(array[i]<pivot){
above[y++]=array[i];
}
else {
if(temp!=0){
below[x++]=array[i];
}
temp=1;
}
}
i = x;
j = len - y;
if(n<i) return select(below,x,n);
else if(n>=j) return(select(above,y,n-j));
else return(pivot);
}
static int pivot(int array[],int len){
if(len==1){
return array[0];
}
int numOfGroups=len/5;
if(len%5!=0){
numOfGroups++;
}
int setOfMedians[]=new int[numOfGroups];
for (int i = 0 ; i < numOfGroups ; i++)
{
int[] subset;
if(array.length % 5 > 0)
{
if (i == numOfGroups - 1)
{
subset = new int[array.length % 5];
}
else
{
subset = new int[5];
}
}
else
{
subset = new int[5];
}
for (int j = 0; j < subset.length ; j++)
{
subset[j] = array[5*i+j];
}
setOfMedians[i] = median(subset);
}
int goodpivot=select(setOfMedians, numOfGroups,numOfGroups/2 );
return goodpivot;
}
static int median(int[] array)
{
if (array.length == 1)
{
return array[0];
}
int smallerCount = 0;
for (int i = 0 ; i < array.length ; i++)
{
for (int j = 0 ; j < array.length ; j++)
{
if (array[i] < array[j])
{
smallerCount++;
}
}
if (smallerCount == (array.length - 1)/2)
{
return array[i];
}
smallerCount = 0;
}
return -1;
}
}
Input
6
3
1 2 3 1 2 3
Output
Exception in thread "main" java.lang.StackOverflowError
at deven.pivot(deven.java:99)
at deven.select(deven.java:34)
at deven.pivot(deven.java:102)
at deven.select(deven.java:34)
at deven.select(deven.java:59)
at deven.select(deven.java:59)
at deven.select(deven.java:59)
If you maintained an equalsCount in addition to your smallerCount, you should be able to detect whether your candidate value is the median when it is also a duplicate.
(Explanation)
You appear to be deliberately returning -1 as an invalid value when your median method fails unexpectedly. It would be more proper to throw an exception of some sort, but what you really want is for it to never reach that point.
Your algorithm fails when the median is a duplicate. In the set { 1, 2, 2, 2, 3 }, for example, 2 is the obvious median, but there's never a point where there are exactly 2 values "smaller than" any of the values being verified.
If you count both smaller and equal values, then you can know your candidate to be a median if either your current test passes, or if the smaller count is less than the midpoint AND the smaller + equal count is greater than the midpoint.
The problem is your median method. It should not return -1. In the last line of the median method, instead of
return -1;
change it to
return array[rand.nextInt(array.length)];
Please note that this fix is just an attempt to fix the error you have. It's not a good fix in the sense that median method does not return the median. I think the application should be refactored. The idea of the fix is actually in the pivot method. A good pivot is the median. But if you cannot find the median efficiently, then a pivot can be a random choice among the array.
Update:
Let's fix the median method:
static int median(int[] array) {
if (array.length == 0) {
throw new IllegalArgumentException("array cannot be empty.");
}
int mid = array.length / 2;
for (int candidate : array) {
int lower = 0;
int higher = 0;
for (int value : array) {
if (value < candidate) {
lower++;
}
else if (value > candidate) {
higher++;
}
}
if (lower <= mid && higher <= mid) {
return candidate;
}
}
throw new IllegalStateException();
}

Categories