I am trying some heapsorting in java for fun.
First, I create a max-heap. Then take the first element to variable max, move the last item from unarranged array to the heap top, and then push down.
I tried 21 elements, it works fine 70% of time, I am wondering whether anyone find the problem.
Thanks.
public class HeapSort extends Sort{
public int sort(int arr[]) {
for (int i = 1; i < arr.length; i++) {
// add to heap
int p = i;
int pp = p /2 ;
while (p > 0 && arr[pp] < arr[p]) {
swap(arr, p, pp);
p = pp;
pp = p / 2;
}
}
for (int i = arr.length - 1; i > 0; i--) {
swap(arr, 0, i);
int p = 0;
int child1 = (p << 1) + 1;
int child2 = (p << 1) + 2;
while (child2 < i || child1 < i) {
if (child1 >= i) {
if (arr[p] < arr[child2]) {
swap(arr, p, child2);
p = child2;
} else {
break;
}
} else if (child2 >= i) {
if (arr[p] < arr[child1]) {
swap(arr, p, child1);
p = child1;
} else {
break;
}
} else {
int minIdx = arr[child1] < arr[child2] ? child1 : child2;
int maxIdx = child1 == minIdx ? child2 : child1;
if (arr[p] < arr[maxIdx]) {
swap(arr, p, maxIdx);
p = maxIdx;
} else {
break;
}
}
child1 = (p << 1) + 1;
child2 = (p << 1) + 2;
}
}
return 0;
}
void swap(int arr[], int idx1, int idx2) {
int tmp = arr[idx1]; arr[idx1] = arr[idx2]; arr[idx2] = tmp;
}
public String toString() {
return "HeapSort";
}
}
You're not building the heap correctly in the first step of heap-sort. You need to subtract one before dividing by two on zero based arrays.
public class HeapSort extends Sort{
public int sort(int arr[]) {
for (int i = 1; i < arr.length; i++) { // add to heap
int p = i;
// int pp = p /2 ; <======= Problem!
int pp = (p-1) / 2;
while (p > 0 && arr[pp] < arr[p]) {
swap(arr, p, pp); p = pp;
// pp = p / 2; // <=====Problem!
pp = (p-1) /2;
}
Related
I am trying to find the maximum product of two non overlapping palindromic sub-sequences of string s that we'll refer to as a and b. I came up with below code but it's not giving correct output:
public static int max(String s) {
int[][] dp = new int[s.length()][s.length()];
for (int i = s.length() - 1; i >= 0; i--) {
dp[i][i] = 1;
for (int j = i+1; j < s.length(); j++) {
if (s.charAt(i) == s.charAt(j)) {
dp[i][j] = dp[i+1][j-1] + 2;
} else {
dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]);
}
}
}
return dp[0][s.length()-1];
}
For input string "acdapmpomp", we can choose a = "aca" and b ="pmpmp" to get a maximal product of score 3 * 5 = 15. But my program gives output as 5.
Firstly you should traverse the dp table to find out the length of longest palindromic subsequences using bottom up approach, then you can calculate the max product by multiplying dp[i][j] with dp[j+1][n-1] : Given below is the code in C++;
int longestPalindromicSubsequenceProduct(string x){
int n = x.size();
vector<vector<int>> dp(n,vector<int>(n,0));
for(int i=0;i<n;i++){
dp[i][i] = 1;
}
for(int k=1;k<n;k++){
for(int i=0;i<n-k;i++){
int j = i + k;
if(x[i]==x[j]){
dp[i][j] = 2 + dp[i+1][j-1];
} else{
dp[i][j] = max(dp[i][j-1],dp[i+1][j]);
}
}
}
int maxProd = 0;
for(int i=0;i<n;i++){
for(int j=0;j<n-1;j++){
maxProd = max(maxProd,dp[i][j]*dp[j+1][n-1]);
}
}
return maxProd;
}
int multiplyPalindrome(string s) {
int n=s.size(),m=0;
vector<vector<int>> dp(n, vector<int> (n));
for(int i=0;i<n;i++) dp[i][i]=1;
for (int cl=2; cl<=n; cl++) {
for (int i=0; i<n-cl+1; i++){
int j = i+cl-1;
if (s[i] == s[j] && cl == 2) dp[i][j] = 2;
else if (s[i] == s[j]) dp[i][j] = dp[i+1][j-1] + 2;
else dp[i][j] = max(dp[i][j-1], dp[i+1][j]);
}
}
for(int i=0;i<n-1;i++){
m = max( m, dp[0][i]*dp[i+1][n-1] );
}
return m;
}
int palSize(string &s, int mask) {
int p1 = 0, p2 = s.size(), res = 0;
while (p1 <= p2) {
if ((mask & (1 << p1)) == 0)
++p1;
else if ((mask & (1 << p2)) == 0)
--p2;
else if (s[p1] != s[p2])
return 0;
else
res += 1 + (p1++ != p2--);
}
return res;
}
int maxProduct(string s) {
int mask[4096] = {}, res = 0;
for (int m = 1; m < (1 << s.size()); ++m)
mask[m] = palSize(s, m);
for (int m1 = 1; m1 < (1 << s.size()); ++m1)
if (mask[m1])
for (int m2 = 1; m2 < (1 << s.size()); ++m2)
if ((m1 & m2) == 0)
res = max(res, mask[m1] * mask[m2]);
return res;
}
You can loop through all non-overlapping palindromic subsequences and return the maximum value.
public int longestPalindromicSubsequenceProduct(String str) {
int maxProduct = 0;
for (int k = 0; k < str.length(); k++) {
String left = str.substring(0, k);
String right = str.substring(k);
int currProduct = longestPalindromicSubsequence(left) * longestPalindromicSubsequence(right);
maxProduct = Math.max(maxProduct, currProduct);
}
return maxProduct;
}
private int longestPalindromicSubsequence(String org) {
String rev = new StringBuilder(org).reverse().toString();
return longestCommonSubsequence(org, rev);
}
private int longestCommonSubsequence(String str1, String str2) {
int rows = str1.length();
int cols = str2.length();
int[][] dp = new int[rows + 1][cols + 1];
for (int r = 1; r <= rows; r++) {
for (int c = 1; c <= cols; c++) {
if (str1.charAt(r - 1) == str2.charAt(c - 1)) dp[r][c] = 1 + dp[r - 1][c - 1];
else dp[r][c] = Math.max(dp[r - 1][c], dp[r][c - 1]);
}
}
return dp[rows][cols];
}
Your algorithm returns the maximum length of a palyndrome, not the maximum of the product of two lengths.
UPDATE
Here's a possible solution:
public static int max(String s) {
int max = 0;
for (int i = 1; i < s.length()-1; ++i) {
String p1 = bestPalyndrome(s, 0, i);
String p2 = bestPalyndrome(s, i, s.length());
int prod = p1.length()*p2.length();
if (prod > max) {
System.out.println(p1 + " " + p2 + " -> " + prod);
max = prod;
}
}
return max;
}
private static String bestPalyndrome(String s, int start, int end) {
if (start >= end) {
return "";
} else if (end-start == 1) {
return s.substring(start, end);
} else if (s.charAt(start) == s.charAt(end-1)) {
return s.charAt(start) + bestPalyndrome(s, start+1, end-1)
+ s.charAt(end-1);
} else {
String s1 = bestPalyndrome(s, start, end-1);
String s2 = bestPalyndrome(s, start+1, end);
return s2.length() > s1.length() ? s2 : s1;
}
}
I work with a Codility problem provided below,
The Fibonacci sequence is defined using the following recursive formula:
F(0) = 0
F(1) = 1
F(M) = F(M - 1) + F(M - 2) if M >= 2
A small frog wants to get to the other side of a river. The frog is initially located at one bank of the river (position −1) and wants to get to the other bank (position N). The frog can jump over any distance F(K), where F(K) is the K-th Fibonacci number. Luckily, there are many leaves on the river, and the frog can jump between the leaves, but only in the direction of the bank at position N.
The leaves on the river are represented in an array A consisting of N integers. Consecutive elements of array A represent consecutive positions from 0 to N − 1 on the river. Array A contains only 0s and/or 1s:
0 represents a position without a leaf;
1 represents a position containing a leaf.
The goal is to count the minimum number of jumps in which the frog can get to the other side of the river (from position −1 to position N). The frog can jump between positions −1 and N (the banks of the river) and every position containing a leaf.
For example, consider array A such that:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
The frog can make three jumps of length F(5) = 5, F(3) = 2 and F(5) = 5.
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A consisting of N integers, returns the minimum number of jumps by which the frog can get to the other side of the river. If the frog cannot reach the other side of the river, the function should return −1.
For example, given:
A[0] = 0
A[1] = 0
A[2] = 0
A[3] = 1
A[4] = 1
A[5] = 0
A[6] = 1
A[7] = 0
A[8] = 0
A[9] = 0
A[10] = 0
the function should return 3, as explained above.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer that can have one of the following values: 0, 1.
Complexity:
expected worst-case time complexity is O(N*log(N));
expected worst-case space complexity is O(N) (not counting the storage required for input arguments).
I wrote the following solution,
class Solution {
private class Jump {
int position;
int number;
public int getPosition() {
return position;
}
public int getNumber() {
return number;
}
public Jump(int pos, int number) {
this.position = pos;
this.number = number;
}
}
public int solution(int[] A) {
int N = A.length;
List<Integer> fibs = getFibonacciNumbers(N + 1);
Stack<Jump> jumps = new Stack<>();
jumps.push(new Jump(-1, 0));
boolean[] visited = new boolean[N];
while (!jumps.isEmpty()) {
Jump jump = jumps.pop();
int position = jump.getPosition();
int number = jump.getNumber();
for (int fib : fibs) {
if (position + fib > N) {
break;
} else if (position + fib == N) {
return number + 1;
} else if (!visited[position + fib] && A[position + fib] == 1) {
visited[position + fib] = true;
jumps.add(new Jump(position + fib, number + 1));
}
}
}
return -1;
}
private List<Integer> getFibonacciNumbers(int N) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 2; i++) {
list.add(i);
}
int i = 2;
while (list.get(list.size() - 1) <= N) {
list.add(i, (list.get(i - 1) + list.get(i - 2)));
i++;
}
for (i = 0; i < 2; i++) {
list.remove(i);
}
return list;
}
public static void main(String[] args) {
int[] A = new int[11];
A[0] = 0;
A[1] = 0;
A[2] = 0;
A[3] = 1;
A[4] = 1;
A[5] = 0;
A[6] = 1;
A[7] = 0;
A[8] = 0;
A[9] = 0;
A[10] = 0;
System.out.println(solution(A));
}
}
However, while the correctness seems good, the performance is not high enough. Is there a bug in the code and how do I improve the performance?
Got 100% with simple BFS:
public class Jump {
int pos;
int move;
public Jump(int pos, int move) {
this.pos = pos;
this.move = move;
}
}
public int solution(int[] A) {
int n = A.length;
List < Integer > fibs = fibArray(n + 1);
Queue < Jump > positions = new LinkedList < Jump > ();
boolean[] visited = new boolean[n + 1];
if (A.length <= 2)
return 1;
for (int i = 0; i < fibs.size(); i++) {
int initPos = fibs.get(i) - 1;
if (A[initPos] == 0)
continue;
positions.add(new Jump(initPos, 1));
visited[initPos] = true;
}
while (!positions.isEmpty()) {
Jump jump = positions.remove();
for (int j = fibs.size() - 1; j >= 0; j--) {
int nextPos = jump.pos + fibs.get(j);
if (nextPos == n)
return jump.move + 1;
else if (nextPos < n && A[nextPos] == 1 && !visited[nextPos]) {
positions.add(new Jump(nextPos, jump.move + 1));
visited[nextPos] = true;
}
}
}
return -1;
}
private List < Integer > fibArray(int n) {
List < Integer > fibs = new ArrayList < > ();
fibs.add(1);
fibs.add(2);
while (fibs.get(fibs.size() - 1) + fibs.get(fibs.size() - 2) <= n) {
fibs.add(fibs.get(fibs.size() - 1) + fibs.get(fibs.size() - 2));
}
return fibs;
}
You can apply knapsack algorithms to solve this problem.
In my solution I precomputed fibonacci numbers. And applied knapsack algorithm to solve it. It contains duplicate code, did not have much time to refactor it. Online ide with the same code is in repl
import java.util.*;
class Main {
public static int solution(int[] A) {
int N = A.length;
int inf=1000000;
int[] fibs={1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025};
int[] moves = new int[N+1];
for(int i=0; i<=N; i++){
moves[i]=inf;
}
for(int i=0; i<fibs.length; i++){
if(fibs[i]-1<N && A[fibs[i]-1]==1){
moves[ fibs[i]-1 ] = 1;
}
if(fibs[i]-1==N){
moves[N] = 1;
}
}
for(int i=0; i<N; i++){
if(A[i]==1)
for(int j=0; j<fibs.length; j++){
if(i-fibs[j]>=0 && moves[i-fibs[j]]!=inf && moves[i]>moves[i-fibs[j]]+1){
moves[i]=moves[i-fibs[j]]+1;
}
}
System.out.println(i + " => " + moves[i]);
}
for(int i=N; i<=N; i++){
for(int j=0; j<fibs.length; j++){
if(i-fibs[j]>=0 && moves[i-fibs[j]]!=inf && moves[i]>moves[i-fibs[j]]+1){
moves[i]=moves[i-fibs[j]]+1;
}
}
System.out.println(i + " => " + moves[i]);
}
if(moves[N]==inf) return -1;
return moves[N];
}
public static void main(String[] args) {
int[] A = new int[4];
A[0] = 0;
A[1] = 0;
A[2] = 0;
A[3] = 0;
System.out.println(solution(A));
}
}
Javascript 100%
function solution(A) {
function fibonacciUntilNumber(n) {
const fib = [0,1];
while (true) {
let newFib = fib[fib.length - 1] + fib[fib.length - 2];
if (newFib > n) {
break;
}
fib.push(newFib);
}
return fib.slice(2);
}
A.push(1);
const fibSet = fibonacciUntilNumber(A.length);
if (fibSet.includes(A.length)) return 1;
const reachable = Array.from({length: A.length}, () => -1);
fibSet.forEach(jump => {
if (A[jump - 1] === 1) {
reachable[jump - 1] = 1;
}
})
for (let index = 0; index < A.length; index++) {
if (A[index] === 0 || reachable[index] > 0) {
continue;
}
let minValue = 100005;
for (let jump of fibSet) {
let previousIndex = index - jump;
if (previousIndex < 0) {
break;
}
if (reachable[previousIndex] > 0 && minValue > reachable[previousIndex]) {
minValue = reachable[previousIndex];
}
}
if (minValue !== 100005) {
reachable[index] = minValue + 1;
}
}
return reachable[A.length - 1];
}
Python 100% answer.
For me the easiest solution was to locate all leaves within one fib jump of -1. Then consider each of these leaves to be index[0] and find all jumps from there.
Each generation or jump is recorded in a set until a generation contains len(A) or no more jumps can be found.
def gen_fib(n):
fn = [0,1]
i = 2
s = 2
while s < n:
s = fn[i-2] + fn[i-1]
fn.append(s)
i+=1
return fn
def new_paths(A, n, last_pos, fn):
"""
Given an array A of len n.
From index last_pos which numbers in fn jump to a leaf?
returns list: set of indexes with leaves.
"""
paths = []
for f in fn:
new_pos = last_pos + f
if new_pos == n or (new_pos < n and A[new_pos]):
paths.append(new_pos)
return path
def solution(A):
n = len(A)
if n < 3:
return 1
# A.append(1) # mark final jump
fn = sorted(gen_fib(100000)[2:]) # Fib numbers with 0, 1, 1, 2.. clipped to just 1, 2..
# print(fn)
paths = set([-1]) # locate all the leaves that are one fib jump from the start position.
jump = 1
while True:
# Considering each of the previous jump positions - How many leaves from there are one fib jump away
paths = set([idx for pos in paths for idx in new_paths(A, n, pos, fn)])
# no new jumps means game over!
if not paths:
break
# If there was a result in the new jumps record that
if n in paths:
return jump
jump += 1
return -1
https://app.codility.com/demo/results/training4GQV8Y-9ES/
https://github.com/niall-oc/things/blob/master/codility/fib_frog.py
Got 100%- solution in C.
typedef struct state {
int pos;
int step;
}state;
int solution(int A[], int N) {
int f1 = 0;
int f2 = 1;
int count = 2;
// precalculating count of maximum possible fibonacci numbers to allocate array in next loop. since this is C language we do not have flexible dynamic structure as in C++
while(1)
{
int f3 = f2 + f1;
if(f3 > N)
break;
f1 = f2;
f2 = f3;
++count;
}
int fib[count+1];
fib[0] = 0;
fib[1] = 1;
int i = 2;
// calculating fibonacci numbers in array
while(1)
{
fib[i] = fib[i-1] + fib[i-2];
if(fib[i] > N)
break;
++i;
}
// reversing the fibonacci numbers because we need to create minumum jump counts with bigger jumps
for(int j = 0, k = count; j < count/2; j++,k--)
{
int t = fib[j];
fib[j] = fib[k];
fib[k] = t;
}
state q[N];
int front = 0 ;
int rear = 0;
q[0].pos = -1;
q[0].step = 0;
int que_s = 1;
while(que_s > 0)
{
state s = q[front];
front++;
que_s--;
for(int i = 0; i <= count; i++)
{
int nextpo = s.pos + fib[i];
if(nextpo == N)
{
return s.step+1;
}
else if(nextpo > N || nextpo < 0 || A[nextpo] == 0){
continue;
}
else
{
q[++rear].pos = nextpo;
q[rear].step = s.step + 1;
que_s++;
A[nextpo] = 0;
}
}
}
return -1;
}
//100% on codility Dynamic Programming Solution. https://app.codility.com/demo/results/training7WSQJW-WTX/
class Solution {
public int solution(int[] A) {
int n = A.length + 1;
int dp[] = new int[n];
for(int i=0;i<n;i++) {
dp[i] = -1;
}
int f[] = new int[100005];
f[0] = 1;
f[1] = 1;
for(int i=2;i<100005;i++) {
f[i] = f[i - 1] + f[i - 2];
}
for(int i=-1;i<n;i++) {
if(i == -1 || dp[i] > 0) {
for(int j=0;i+f[j] <n;j++) {
if(i + f[j] == n -1 || A[i+f[j]] == 1) {
if(i == -1) {
dp[i + f[j]] = 1;
} else if(dp[i + f[j]] == -1) {
dp[i + f[j]] = dp[i] + 1;
} else {
dp[i + f[j]] = Math.min(dp[i + f[j]], dp[i] + 1);
}
}
}
}
}
return dp[n - 1];
}
}
Ruby 100% solution
def solution(a)
f = 2.step.inject([1,2]) {|acc,e| acc[e] = acc[e-1] + acc[e-2]; break(acc) if acc[e] > a.size + 1;acc }.reverse
mins = []
(a.size + 1).times do |i|
next mins[i] = -1 if i < a.size && a[i] == 0
mins[i] = f.inject(nil) do |min, j|
k = i - j
next min if k < -1
break 1 if k == -1
next min if mins[k] < 0
[mins[k] + 1, min || Float::INFINITY].min
end || -1
end
mins[a.size]
end
I have translated the previous C solution to Java and find the performance is improved.
import java.util.*;
class Solution {
private static class State {
int pos;
int step;
public State(int pos, int step) {
this.pos = pos;
this.step = step;
}
}
public static int solution(int A[]) {
int N = A.length;
int f1 = 0;
int f2 = 1;
int count = 2;
while (true) {
int f3 = f2 + f1;
if (f3 > N) {
break;
}
f1 = f2;
f2 = f3;
++count;
}
int[] fib = new int[count + 1];
fib[0] = 0;
fib[1] = 1;
int i = 2;
while (true) {
fib[i] = fib[i - 1] + fib[i - 2];
if (fib[i] > N) {
break;
}
++i;
}
for (int j = 0, k = count; j < count / 2; j++, k--) {
int t = fib[j];
fib[j] = fib[k];
fib[k] = t;
}
State[] q = new State[N];
for (int j = 0; j < N; j++) {
q[j] = new State(-1,0);
}
int front = 0;
int rear = 0;
// q[0].pos = -1;
// q[0].step = 0;
int que_s = 1;
while (que_s > 0) {
State s = q[front];
front++;
que_s--;
for (i = 0; i <= count; i++) {
int nextpo = s.pos + fib[i];
if (nextpo == N) {
return s.step + 1;
}
//
else if (nextpo > N || nextpo < 0 || A[nextpo] == 0) {
continue;
}
//
else {
q[++rear].pos = nextpo;
q[rear].step = s.step + 1;
que_s++;
A[nextpo] = 0;
}
}
}
return -1;
}
}
JavaScript with 100%.
Inspired from here.
function solution(A) {
const createFibs = n => {
const fibs = Array(n + 2).fill(null)
fibs[1] = 1
for (let i = 2; i < n + 1; i++) {
fibs[i] = fibs[i - 1] + fibs[i - 2]
}
return fibs
}
const createJumps = (A, fibs) => {
const jumps = Array(A.length + 1).fill(null)
let prev = null
for (i = 2; i < fibs.length; i++) {
const j = -1 + fibs[i]
if (j > A.length) break
if (j === A.length || A[j] === 1) {
jumps[j] = 1
if (prev === null) prev = j
}
}
if (prev === null) {
jumps[A.length] = -1
return jumps
}
while (prev < A.length) {
for (let i = 2; i < fibs.length; i++) {
const j = prev + fibs[i]
if (j > A.length) break
if (j === A.length || A[j] === 1) {
const x = jumps[prev] + 1
const y = jumps[j]
jumps[j] = y === null ? x : Math.min(y, x)
}
}
prev++
while (prev < A.length) {
if (jumps[prev] !== null) break
prev++
}
}
if (jumps[A.length] === null) jumps[A.length] = -1
return jumps
}
const fibs = createFibs(26)
const jumps = createJumps(A, fibs)
return jumps[A.length]
}
const A = [0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0]
console.log(A)
const s = solution(A)
console.log(s)
You should use a QUEUE AND NOT A STACK. This is a form of breadth-first search and your code needs to visit nodes that were added first to the queue to get the minimum distance.
A stack uses the last-in, first-out mechanism to remove items while a queue uses the first-in, first-out mechanism.
I copied and pasted your exact code but used a queue instead of a stack and I got 100% on codility.
100% C++ solution
More answers in my github
Inspired from here
Solution1 : Bottom-Top, using Dynamic programming algorithm (storing calculated values in an array)
vector<int> getFibonacciArrayMax(int MaxNum) {
if (MaxNum == 0)
return vector<int>(1, 0);
vector<int> fib(2, 0);
fib[1] = 1;
for (int i = 2; fib[fib.size()-1] + fib[fib.size() - 2] <= MaxNum; i++)
fib.push_back(fib[i - 1] + fib[i - 2]);
return fib;
}
int solution(vector<int>& A) {
int N = A.size();
A.push_back(1);
N++;
vector<int> f = getFibonacciArrayMax(N);
const int oo = 1'000'000;
vector<int> moves(N, oo);
for (auto i : f)
if (i - 1 >= 0 && A[i-1])
moves[i-1] = 1;
for (int pos = 0; pos < N; pos++) {
if (A[pos] == 0)
continue;
for (int i = f.size()-1; i >= 0; i--) {
if (pos + f[i] < N && A[pos + f[i]]) {
moves[pos + f[i]] = min(moves[pos]+1, moves[pos + f[i]]);
}
}
}
if (moves[N - 1] != oo) {
return moves[N - 1];
}
return -1;
}
Solution2: Top-Bottom using set container:
#include <set>
int solution2(vector<int>& A) {
int N = A.size();
vector<int> fib = getFibonacciArrayMax(N);
set<int> positions;
positions.insert(N);
for (int jumps = 1; ; jumps++)
{
set<int> new_positions;
for (int pos : positions)
{
for (int f : fib)
{
// return jumps if we reach to the start point
if (pos - (f - 1) == 0)
return jumps;
int prev_pos = pos - f;
// we do not need to calculate bigger jumps.
if (prev_pos < 0)
break;
if (prev_pos < A.size() && A[prev_pos])
new_positions.insert(prev_pos);
}
}
if (new_positions.size() == 0)
return -1;
positions = new_positions;
}
return -1;
}
My code is working during compilation but the runtime error points to an if condition in my MaxHeapify function. I marked it out. Any help would be simply lovely, and would make me stop banging my head against the wall.
public class HeapSort {
public static void main(String[] args) {
int A[] = {-100, 1, 2, 5, 7, 2, 9};
Heapsort(A);
//System.out.println(A.length);
for (int x = 1; x < A.length; x++) {
System.out.println(A[x] + " ");
}
}
public static void Build_MAX_heap(int A[]) {
int n = A.length;
for (int i = n / 2; i >= 1; i--) {
MAX_heapify(A, i);
}
}
public static void MAX_heapify(int A[], int i) {
int heapsize = A.length;
int l = 2 * i;
int r = 2 * i + 1;
//find the largest of A[i].A[l],A[r]
int largest = i;
if (A[l] > A[largest]) {
largest = l;
if (A[l] > A[largest] && l <= heapsize) {
largest = l;
}
if (A[r] > A[largest] && r <= heapsize) { //runtime error here
largest = r;
}
if (largest != i) {
int temp = A[i];
A[i] = A[largest];
A[largest] = temp;
MAX_heapify(A, largest);
}
}
}
public static void Heapsort(int A[]) {
Build_MAX_heap(A);
int heapsize = A.length;
for (int last = heapsize; last >= 2; last--) {
int temp = A[1];
A[1] = A[last];
A[last] = temp;
heapsize--;
MAX_heapify(A,1);
}
}
}
You're doing you bounds checking for r (and l, too, in the previous statement) after checking the element at index r. If r is out of bounds, the first half of the expression will throw an exception, and never make it to the bounds check.
Your if statements should be structured
if (r < heapsize && A[r] > A[largest]) ...
so that you know you're in bounds before you start trying to access your array. In addition, since arrays are zero-indexed, the index of heapsize isn't valid, so r needs to be less than, not less than or equal to.
Your problem is that your are checking A[r] before checking if r is out of range
so i would try to modify the code this way
public class HeapSort {
public static void main(String[] args) {
int A[] = {-100, 1, 2, 5, 7, 2, 9};
Heapsort(A);
//System.out.println(A.length);
for (int x = 1; x < A.length; x++) {
System.out.println(A[x] + " ");
}
}
public static void Build_MAX_heap(int A[]) {
int n = A.length;
for (int i = n / 2; i >= 1; i--) {
MAX_heapify(A, i);
}
}
public static void MAX_heapify(int A[], int i) {
int heapsize = A.length;
int l = 2 * i;
int r = 2 * i + 1;
//find the largest of A[i].A[l],A[r]
int largest = i;
if (A[l] > A[largest]) {
largest = l;
if (A[l] > A[largest] && l <= heapsize) {
largest = l;
}
if (r<=heapsize && A[r] > A[largest]) { //modification here
largest = r;
}
if (largest != i) {
int temp = A[i];
A[i] = A[largest];
A[largest] = temp;
MAX_heapify(A, largest);
}
}
}
public static void Heapsort(int A[]) {
Build_MAX_heap(A);
int heapsize = A.length;
for (int last = heapsize; last >= 2; last--) {
int temp = A[1];
A[1] = A[last];
A[last] = temp;
heapsize--;
MAX_heapify(A,1);
}
}
}
Variable r is set to:
int r = 2 * i + 1;
In first case of loop:
for (int i = n / 2; i >= 1; i--) {
MAX_heapify(A, i);
}
i is n/2
so to function is passed:
MAX_heapify(A,n/2);
and r is 2 * (n/2) + 1 which is n+1
when you want to do this line
if (A[r] > A[largest] && r <= heapsize) {
then A[r] is A[n+1]=A[A.length+1] - this causes IndexOutOfBoundsException
It was an interview question and I was asked to fix the code-->
Given a sorted array, I have to find the array index of the element if it is present, else I have to return -1. Following is my code:
public static int returnIndex(int[] a, int x) {
int n = a.length;
if (n == 0) {
return -1;
}
int l = 0;
int r = n - 1;
while (l < r) {
int m = (l + r) / 2;
if (a[m] > x) {
r = m - 1;
} else {
l = m;
}
}
if (a[l] == x) {
return l;
}
return -1;
}
Code works fine if I have to find the middle element but fails (goes into infinite loop) when I have to find any other element. Can anyone point out the mistake?
I am allowed to make only 3 modifications in this code.
Worst case Time Complexity-O(log(n))
Worst case Space Complexity-O(1)
You are trying binary search here. So you need to have 3 conditions. midValue > key, midValue < key and midValue == key. You are handling only 2. Also when midValue > key you need to add one to index. So modify your method like
public static int returnIndex(int[] a, int x) {
int n = a.length;
if (n == 0) {
return -1;
}
int l = 0;
int r = n - 1;
while (l < r) {
int m = (l + r) / 2;
if (a[m] > x) {
r = m - 1;
} else if(a[m] < x){
l = m + 1;
} else {
return m;
}
}
return -1;
}
If you are not doing it for an exercise you could achieve the same via Arrays.binarySearch() method.
I would it this way:
public static int returnIndex(int[] a, int x) {
int n = a.length;
if (n == 0) {
return -1;
}
int l = 0;
int r = n - 1;
while (l < r) {
int m = (l + r) / 2;
if (a[m] == x) {
return m;
}
if (a[m] > x) {
r = m - 1;
} else {
l = m + 1;
}
}
return -1;
}
I finally got my bubblesort and quicksort working but am curious as to how to change my code so that when I reach the last 10 elements being sorted in my quicksort I instead change to bubblesort for faster overhead times.
static int num_comps;
public static void main(String[] args)
{
Random rnd = new Random();
// max size of array and number of N sets
int array_size = 32768;
int num_datasets = 10;
// array set to max size
int[] vals = new int[array_size];
// temporary array with allocated array to max size
int[] tvals = new int[array_size];
// array to hold operation counts
int[] op_counts = new int[num_datasets];
int[] op_counts2 = new int[num_datasets];
// array to hold the size of each array
int[] arraySizes = new int[num_datasets];
int i;
int size;
for (i = 0, size = 64; i < num_datasets; i++, size *= 2)
arraySizes[i] = size;
for (int iter = 0; iter < num_datasets; iter++)
{
int curr_size = arraySizes[iter];
// fill array with random values form 0-4999
for (i = 0; i < curr_size; i++)
vals[i] = rnd.nextInt(4999);
//set the temporary array to the actual array
for (i = 0; i < curr_size; i++)
tvals[i] = vals[i];
// run the bubble sort algorithm
num_comps = 0;
bubbleSort(tvals, curr_size);
op_counts[iter] = num_comps;
//System.out.println("Num comps at " + iter + " is " + num_comps);
num_comps = 0;
quickSort(tvals, curr_size);
op_counts2[iter] = num_comps;
}
System.out.println("N Bubble Sort OP Count Quick Sort OP Count");
for (int k = 0; k < num_datasets; k++)
{
System.out.println(arraySizes[k] + "\t\t" + op_counts[k] + "\t\t\t" + op_counts2[k]);
}
}
static void bubbleSort(int vals[], int curr_size)
{
int temp;
for (int i = 0; i < curr_size - 1; i++)
{
for (int j = 0; j < curr_size - i - 1; j++)
{
// swap
num_comps = num_comps + 1;
if (vals[j+1] < vals[j])
{
temp = vals[j];
vals[j] = vals[j+1];
vals[j+1] = temp;
}
}
}
}
static void quickSort(int vals[], int curr_size)
{
quickSort_R(vals, 0, curr_size - 1);
}
static void quickSort_R(int vals[], int l, int r)
{
if (l < r)
{
if ((r-1) == 1) // two elements - trivial sort
{
num_comps = num_comps + 1;
if (vals[l] > vals[r])
swap(vals, l, r);
return;
}
// partition the elements on the pivot s
int s = partition(vals, l, r);
//recurse on the two partitioned values
quickSort_R(vals, l, s-1);
quickSort_R(vals, s+1, r);
}
}
static int partition(int vals[], int l, int r)
{
int mid = (l+r) / 2;
int p = medianOfThree(vals, l, r);
// swap with first element
swap(vals, l, p);
int pivot_val = vals[l];
int i = l;
int j = r+1;
do
{
num_comps = num_comps + 1;
do
{
i = i + 1;
num_comps = num_comps + 1;
} while (vals[i] < pivot_val);
do
{
j = j - 1;
num_comps = num_comps + 1;
} while (vals[j] > pivot_val);
swap(vals, i, j);
} while (i < j);
swap(vals, i, j); // undo last swap
swap(vals, i, j); // put pivot at j, its correct position
return j;
}
static int medianOfThree(int vals[], int first, int last)
{
int mid = (first+last) / 2;
if (vals[first] <= vals[mid] && vals[mid] <= vals[last])
{
num_comps = num_comps + 1;
return mid;
}
else if (vals[mid] <= vals[first] && vals[first] <= vals[last])
{
num_comps = num_comps + 1;
return first;
}
else
return last;
}
static void swap(int vals[], int i, int j)
{
int temp = vals[i];
vals[i] = vals[j];
vals[j] = temp;
}
}
EJP is right, but if you want to, just modify your code like so:
public static void quickSort_R(int vals[], int l, int r) {
if (l < r) {
if((r-l) < 10) {
bubbleSort(vals, r-l); //<--HERE
}
else {
if ((r-1) == 1) { // two elements - trivial sort
num_comps = num_comps + 1;
if (vals[l] > vals[r])
swap(vals, l, r);
return;
}
// partition the elements on the pivot s
int s = partition(vals, l, r);
//recurse on the two partitioned values
quickSort_R(vals, l, s-1);
quickSort_R(vals, s+1, r);
}
}
}