Representation of an array as a Heap - java

I am trying to represent an array in form of a Minimum-Heap. And I am facing a problem in one of the leaf nodes, where parent is greater than (12 grater than 6) the right child. I am not understanding what is wrong in my coding, please help.
Here is my code:
public class MinHeap {
public void heapify(int Array[], int i){
int min;
int left=2*i;
int right= 2*i+1;
int length=Array.length;
if(left<length && Array[left]< Array[i] && Array[left]< Array[right])
min=left;
else if(right<length && Array[right]<Array[i] && Array[right]<Array[left])
min=right;
else min=i;
if(min!=i){
int temp=Array[i];
Array[i] = Array[min];
Array[min]=temp;
heapify(Array,min);
}
}
public void display(int Array[]){
for(int i=0; i<Array.length; i++)
System.out.print(Array[i]+" ");
}
public static void main(String[] args){
int Array[]={2,1,4,5,6,100,0,9,8,3,12,32,6,7,1000,999,20};
//int Array[]={1, 8, 9, 2, 10, 14, 3, 4, 7, 16};
int length=Array.length;
MinHeap object= new MinHeap();
System.out.println(length);
object.display(Array);
System.out.println();
for(int i=(length/2)-1;i>=0;i--){
object.heapify(Array,i);
}
System.out.println();
object.display(Array);
}
}
The output that I am getting is:
0 1 3 2 4 12 5 9 8 6 100 32 6 7 1000 999 20

Try this.
static void heap(int[] a) {
for (int i = 0; i < a.length; ++i) {
while (true) {
int p = (i - 1) / 2;
if (a[p] <= a[i])
break;
int t = a[i];
a[i] = a[p];
a[p] = t;
i = p;
}
}
}
and
int a[]={2,1,4,5,6,100,0,9,8,3,12,32,6,7,1000,999,20};
heap(a);
System.out.println(Arrays.toString(a));
// -> [0, 2, 1, 5, 3, 6, 4, 9, 8, 6, 12, 100, 32, 7, 1000, 999, 20]

Your children index is calculated wrong. You should use:
int left=2*i+1;
int right=2*i+2;
And the output will be:
0 1 2 5 3 6 4 9 8 6 12 32 100 7 1000 999 20

Related

Can someone please point out error for the code "Number of Subsequences That Satisfy the Given Sum Condition" which is giving stack overflow error

This is leetCode problem. I solved it using the following method but its giving stack overflow error.
Given an array of integers nums and an integer target.
Return the number of non-empty subsequences of nums such that the sum of the minimum and maximum element on it is less or equal than the target.
Since the answer may be too large, return it modulo 10^9 + 7.
Input: nums = [3,5,6,7], target = 9
Output: 4
Explanation: There are 4 subsequences that satisfy the condition.
[3] : Min value + max value <= target (3 + 3 <= 9)
[3,5] : (3 + 5 <= 9)
[3,5,6] : (3 + 6 <= 9)
[3,6] : (3 + 6 <= 9)
enter code here:
import java.lang.Math;
class Solution {
static int maxIndex=0;
static long M=1000000007;
public int numSubseq(int[] nums, int target) {
Arrays.sort(nums);
maxIndex=nums.length-1;
return numSubseq(nums,target,0);
}
public int numSubseq(int[] nums,int target, int i){
if(target==0 || nums.length==0 || i==nums.length)
return 0;
int res=0;
if(2*nums[i]<=target){
res=1;
if(nums[i]<nums[maxIndex]){
int j=maxIndex;
while(j>i){
if(nums[i]+nums[maxIndex]<=target)
break;
j--;
}
maxIndex=j;
if(nums[i]+nums[maxIndex]<=target && i!=maxIndex)
{
int diffIndex=maxIndex-i;
res+=Math.pow(2,diffIndex)-1;
}
}
}
else{
return 0;
}
return (int)((res+numSubseq(nums,target,i++))%M);
}
}``
I guess there would be a problem here in this line:
return (int)((res+numSubseq(nums,target,i++))%M);
We can solve the problem a bit easier though, similarly using sort, then two pointers.
Test with a b.java:
import java.util.*;
class Solution {
private static final int MOD = (int)1e9 + 7;
public static final int numSubseq(
final int[] nums,
final int target
) {
Arrays.sort(nums);
int[] pows = new int[nums.length];
pows[0] = 1;
int subsequences = 0;
int left = 0;
int right = nums.length - 1;
for (int index = 1 ; index < nums.length ; ++index) {
pows[index] = pows[index - 1] * 2;
pows[index] %= MOD;
}
while (left <= right) {
if (nums[left] + nums[right] > target) {
--right;
} else {
subsequences += pows[right - left++];
subsequences %= MOD;
}
}
return subsequences;
}
}
class b {
public static void main(String[] args) {
System.out.println(new Solution().numSubseq(new int[] {3, 5, 6, 7}, 9));
System.out.println(new Solution().numSubseq(new int[] {3, 3, 6, 8}, 10));
System.out.println(new Solution().numSubseq(new int[] {2, 3, 3, 4, 6, 7}, 12));
System.out.println(new Solution().numSubseq(new int[] {5, 2, 4, 1, 7, 6, 8}, 16));
}
}
prints
4
6
61
127

Small exercise for Java given two arrays which represents a path

Given two arrays which represents a path and each element in the array represent the time it takes the driver to travel, write a method that chooses the fastest path he can take. The driver can switch paths only once between arrays.
For example the following arrays:
int[] road1 = new int[] { 5, 4, 5, 8, 12, 9, 9, 3 };
int[] road2 = new int[] { 7, 3, 3, 12, 10, 2, 10, 7 };
the output should be 49 since the driver will start at road2 and switch at index 6 to the second Array.
Edit:
My question is how do I make the recursion stop after switching to the other array? I tried to put a counter marker but it didn't work and I reverted back to my original output. Am I missing something about how recursion works?
My code prints 53 where it should print 49.
My code:
public class MyClass {
public static int shortestRoad(int[] road1, int[] road2) {
return shortestRoadNumbers(road1, road2, 0);
}
private static int shortestRoadNumbers(int[] road1, int[] road2, int index) {
if (index == road1.length || index == road2.length) {
return 0;
}
if (road1[index] >= road2[index] && road1[index + 2] >= road2[index + 2]) {
return (road2[index] + shortestRoadNumbers(road1, road2, index + 1));
} else {
return (road1[index] + shortestRoadNumbers(road1, road2, index + 1));
}
}
public static void main(String args[]) {
int[] road1 = new int[] { 5, 4, 5, 8, 12, 9, 9, 3 };
int[] road2 = new int[] { 7, 3, 3, 12, 10, 2, 10, 7 };
MyClass.shortestRoad(road1, road2);
int result = MyClass.shortestRoad(road1, road2);
System.out.println(result);
}
}
Let the following schema to illustrate your problem
We have two paths, and each path contain many nodes (values) , we can switch from one path to another just one time. Find the best combination of nodes (values) that minimise the score.
We can distinguish 4 cases:
1- the sum of the values of the first path without switching.
2-the sum of the values of the second path without switching.
3-the sum of the values from the first path until a node i, then switch to path second path from node i+1 (sum from node+1 til the end)
4-the inverse of the point 3.
static int shortestRoad(int road1[], int road2[])
{
// case 1
int bestValue = sumValues(road1,0);
// case 2
int sumValuesRoad2 = sumValues(road2,0);
if ( sumValuesRoad2 < bestValue)
bestValue = sumValuesRoad2;
// case 3: best values of all combination from road 1 to road 2
int bestValuesSwitchFromRoad1ToRoad2 = shortestRoad_Switch_RoadFrom_RoadTo(road1, road2);
if ( bestValuesSwitchFromRoad1ToRoad2 < bestValue)
bestValue = bestValuesSwitchFromRoad1ToRoad2;
// case 4: best values of all combination from road 2 to road 1
int bestValuesSwitchFromRoad2ToRoad1 = shortestRoad_Switch_RoadFrom_RoadTo(road2, road1);
if ( bestValuesSwitchFromRoad2ToRoad1 < bestValue)
bestValue = bestValuesSwitchFromRoad2ToRoad1;
return bestValue;
}
sum the values of a given array from idx til the end:
static int sumValues(int array[], int idx_from)
{
int sum = 0;
for (int i = idx_from; i<array.length; ++i)
sum += array[i];
return sum;
}
case 3 and 4:
static int shortestRoad_Switch_RoadFrom_RoadTo(int[] road_from, int[] road_to)
{
int sumValues_RoadFrom_til_idx = 0;
int sumValues_RoadFrom_idx_switch_RoadTo = 0;
int bestValue = Integer.MAX_VALUE;
for (int i = 0; i<road_from.length-1; ++i)
{
sumValues_RoadFrom_til_idx += road_from[i];
sumValues_RoadFrom_idx_switch_RoadTo = sumValues_RoadFrom_til_idx+sumValues(road_to,i+1);
if(sumValues_RoadFrom_idx_switch_RoadTo < bestValue )
bestValue = sumValues_RoadFrom_idx_switch_RoadTo;
}
return bestValue;
}
Driver code:
public static void main(String[] args)
{
int road1[] = { 5, 4, 5, 8, 12, 9, 9, 3 };
int road2[] = { 7, 3, 3, 12, 10, 2, 10, 7 };
int road_a[] = { 1, 1, 1, 1, 1, 9, 9, 9,9,9 };
int road_b[] = { 9, 9, 9, 9, 9, 1, 1, 1,1,1 };
int road_c[] = { 1, 1, 1, 1, 1, 2 };
int road_d[] = { 9, 9, 9, 9, 9, 1, 1, 1,1,1 };
System.out.println("best road1, road2 = "+shortestRoad(road1,road2));
System.out.println("best road_a, road_b = "+shortestRoad(road_a,road_b));
System.out.println("best road_c, road_d = "+shortestRoad(road_c,road_d));
return 0;
}
Results:
best road1, road2 = 49
best road_a, road_b = 10
best road_c, road_d = 7
ps:
the best path in your example is begin from road2 and then switch to road 1 at i=5 (i begin from 0)
{ 5, 4, 5, 8, 12, 9, -->9, 3 }
{ -->7, 3, 3, 12, 10, 2 /, 10, 7 }
public static int shortestRoad(int[]road1, int[]road2)
{
int sumRoad1Only = 0;
int sumRoad2Only = 0;
for(int i=0; i<road1.length; i++)
{
sumRoad1Only += road1[i];
sumRoad2Only += road2[i];
}
Those sums are for the option that the driver chooses one lane, and doesn't change it until the end. Now, we can find the switch index, for options like starting at one road, and switching to the other. In this specific question I realized that the best point of switch between the arrays - is where the difference between the two collected sums until a certain index is the largest. In your example, it is index 6. That doesn't say that switching a lane is always giving a smaller sum.
int roadIndex1 = road1.length-1;
int roadIndex2 = road2.length-1;
int totalSumRoad1 = sumRoad1Only;
int totalSumRoad2 = sumRoad2Only;
int max = 0;
int indexOfSwitch = 0;
int diff = 0;
while(roadIndex1 >=0 && roadIndex2 >=0)
{
diff = Math.abs(totalSumRoad2 - totalSumRoad1);
if(diff > max)
{
max = diff;
indexOfSwitch = roadIndex1;
}
totalSumRoad1 -= road1[roadIndex1];
totalSumRoad2 -= road2[roadIndex2];
roadIndex1--;
roadIndex2--;
}
If the index of switch is at last index, we shall move it one left, so there be a transition between the arrays.
if(indexOfSwitch == road1.length-1)
{
indexOfSwitch--;
}
now we found the indexOfSwitch, we can calculate the options of starting at road1, and switching exactly once to road2, and vice versa:
int begin1 = 0;
int begin2 = 0;
for(int k = 0; k<=indexOfSwitch; k++)
{
begin1 += road1[k];
begin2 += road2[k];
}
int end1 = sumRoad1Only - begin1;
int end2 = sumRoad2Only - begin2;
int begin1End2 = begin1 + end2;
int begin2End1 = begin2 + end1;
and when we find all the options, we can return the minimum.
return Math.min(Math.min(sumRoad1Only, sumRoad2Only), Math.min(begin1End2, begin2End1));

Recursive function that reverses subarray X[i,...,j]. Elements from index i to j inclusive

So I am working on a textbook practice problem focusing on recursion which I'm half way there. I have come up with two functions that recursive copy the element in one array into another, but I am sort of stuck on my reverseArray3 function.
reverseArray3 should reverse the subarray X[i,...j] consisting of those elements from index i to index j inclusive. I know it should do this by swapping elements at position i and j then calling itself recursively on subarray X[i+1,...,j-1] from index i+1 and j-1.
I tried to look up question similar to mine, but no luck. Any help
class Recursion {
static void reverseArray1(int[] X, int n, int[] Y) {
if(n < 1)
return;
Y[Y.length-n] = X[n-1];
reverseArray1(X, n-1, Y);
}
static void reverseArray2(int[] X, int n, int[] Y) {
if(n < 1)
return;
Y[n-1] = X[X.length-n];
reverseArray2(X, n-1, Y);
}
static void reverseArray3(int[] X, int i, int j) {
//Where I'm stuck
}
public static void main(String[] args) {
int[] A = {-1, 2, 3, 12, 9, 2, -5, -2, 8, 5, 7};
int[] B = new int[A.length];
int[] C = new int[A.length];
for(int x: A) System.out.print(x+" ");
System.out.println();
reverseArray1(A, A.length, B);
for(int x: B) System.out.print(x+" ");
System.out.println();
reverseArray2(A, A.length, C);
for(int x: C) System.out.print(x+" ");
System.out.println();
reverseArray3(A, 0, A.length-1);
for(int x: A) System.out.println(x+" ");
System.out.println();
}
}
below is how the output should look like:
1 2 6 12 9 2 -5 -2 8 5 7
7 5 8 -2 -5 2 9 12 6 2 -1
7 5 8 -2 -5 2 9 12 6 2 -1
7 5 8 -2 -5 2 9 12 6 2 -1
I suggest this:
static void reverseArray3(int[] X, int i, int j) {
if(i>=j)
return;
int a=X[j];
X[j]=X[i];
X[i]=a;
reverseArray3(X,i+1,j-1);
}
I hope it helps.

how to print magic matrix upto n square for a given number n

I am trying to implement matrix logic in a program riddle. This is not a home work I am just trying to practice it on my own but could go further without guidance or approach.
The problem is suppose we have given number let's say n than a matrix should get generated upto n*n numbers with following pattern
ex: Number is 3
1 2 3
7 8 9
4 5 6
like wise if the the number is 4
than
1 2 3 4
9 10 11 12
13 14 15 16
5 6 7 8
for problem solving I used following logic but it could not give me expected output
public static void printPattern(int i){
int num= i*i;
int n=1;
int[][] matrixArray = new int[i][i];
for (int g=0;g<i ;g++ ){
for (int j=0; j<i&& n<=num; j++,n++){
System.out.println("i::"+i+"::j"+j+"number is :"+n);
if (g!=0 &&g%2==0){
System.out.println("g is "+g);
matrixArray[g][j]=n;
}
else{
matrixArray[g][j]=n;
}
}
}
for (int g=0;g<i ;g++ ) {
for (int j = 0; j < i; j++) {
System.out.print(matrixArray[g][j] + " ");
}
System.out.println();
}
}
}
Here's a much simpler approach. Just keep alternating between top and bottom rows within the main loop and you wouldn't have to use if-else constructs at all.
public static void printMatrix(int num) {
int n = 1;
int[][] matrix = new int[num][num];
for (int top = 0, bottom = num - 1; top <= bottom; top++, bottom--) {
for (int i = 0; i < num; i++) {
matrix[top][i] = n++;
}
if (top == bottom) {
break;
}
for (int i = 0; i < num; i++) {
matrix[bottom][i] = n++;
}
}
for (int[] arr : matrix) {
System.out.println(Arrays.toString(arr));
}
}
Here the loop runs till the top crosses bottom i.e. when top = bottom + 1 for even number of rows. For odd number of rows, the loop breaks out when top = bottom after filling that row once.
Output : printMatrix(4); // even
[1, 2, 3, 4]
[9, 10, 11, 12]
[13, 14, 15, 16]
[5, 6, 7, 8]
Output : printMatrix(5); // odd
[1, 2, 3, 4, 5]
[11, 12, 13, 14, 15]
[21, 22, 23, 24, 25]
[16, 17, 18, 19, 20]
[6, 7, 8, 9, 10]
Change the code in your inner for loop to the following
if (g % 2 == 1) { // Handle rows with odd index (second, fourth ...)
matrixArray[i - (g + 1) / 2][j] = n;
} else { // First, third ... rows
matrixArray[g / 2][j] = n;
}
See it run live

Print sequence of numbers without consequtive duplicates?

Given a sequence of numbers like this:
1 2 2 5 5 5 1 7 3 7 7 7
Output should be
1 2 5 1 7 3 7
The current output of my code is
1 2 5 1 7 3
I am unable to fix the problem. Can anyone tell me what should I do or change in my code?
Here's my current code:
public class Q3 {
public static void main(String args[]) {
int [] input=new int[]{1 ,2, 2, 5, 5, 5, 1, 7, 3, 7, 7, 7};
int current= input[0];
boolean found=false;
for(int i=0; i< input.length; i++) {
if(current == input[i] && !found) {
found=true;
} else if(current!=input[i]) {
System.out.print(" " + current);
current=input[i];
found=false;
}
}
}
}
The basic problem is, you need to seed the current value with something that is not equal to the first element, this way, you can just loop through the array without issues, flags or other tricks, for example...
int[] input = new int[]{1, 2, 2, 5, 5, 5, 1, 7, 3, 7, 7, 7};
int current = -input[0];
for (int i = 0; i < input.length; i++) {
if (current != input[i]) {
current = input[i];
System.out.print(" " + current);
}
}
System.out.println("");
Which outputs...
1 2 5 1 7 3 7
This sets the current value to the negative of the first element (in this -1), so when we do our first comparison, -1 != 1 and then we can proceeded as normal...
You can try in this way
Eg:
int[] input = new int[]{1, 2, 2, 5, 5, 5, 1, 7, 3, 7, 7, 7};
int temp =input[0];
boolean isFirst=true;
for (int i = 0; i < input.length; i++) {
if(isFirst){
System.out.print(temp);
isFirst=false;
}
if (temp != input[i]) {
System.out.print(input[i]);
}
temp = input[i];
}
Out put:
1251737
Logic: I am taking only first occurrence of continuous numbers.
You can simplify code a lot, if you don't want to remove all duplicates, only closest one.
public class Q3 {
public static void main(String args[]) {
int [] input=new int[]{1 ,2, 2, 5, 5, 5, 1, 7, 3, 7, 7, 7};
int base = input[0];
System.out.print(base);
for (int current : input) {
if (current != base) {
base = current;
System.out.print(" " + base);
}
}
}
}
Output:
1 2 5 1 7 3 7
This is not right to use other's answer without giving the credit
int[] input = new int[]{1, 2, 2, 5, 5, 5, 1, 7, 3, 7, 7, 7};
int current = input[0];
boolean found = false;
for (int i = 0; i < input.length; i++) {
if (current == input[i] && !found) {
found = true;
} else if (current != input[i]) {
System.out.print(" " + current);
current = input[i];
found = false;
}
}
System.out.print(" " + current); <--- you forgot this line
output:
1 2 5 1 7 3 7
My answer can be found here
How to efficiently remove duplicates from an array without using Set
int [] input = new int[]{1 ,2, 2, 5, 5, 5, 1, 7, 3, 7, 7, 7};
int previous = 0;
boolean started = false; // loop is not started yet
for (int i = 0; i < input.length; i++)
{
// if the loop is not started, or the number is not equal to previously printed number...
if (!started || input[i] != previous) {
System.out.print(input[i] + " ");
previous = input[i];
}
started = true;
}

Categories