Search code examples
javascriptalgorithmrecursionmergesort

Undestanding Recursion with return values in Merge Sort


I'm trying to solve a basic problem in Hackerearth Given an array A of size N, you need to find the number of ordered pairs (i,j) such that i < j and A[i] > A[j].

I was able to find out an idea actually implemented it by having a global variable. But having a global value is not a good practice, hence I tried to pass it as parameter and I couldn't able to solve it. Am stuck with keeping an already returned value and adding an updated value to it.

// let ans = 0;

let mergeSort = (left, right, arr, ans) => {
    let i = 0,
        j = 0,
        k = 0;
    let leftLen = left.length,
        rightLen = right.length;
    while (i < leftLen && j < rightLen) {
        if (left[i] <= right[j]) {
        arr[k] = left[i];
        i++;
        } else {
        arr[k] = right[j];
        ans += leftLen - i;
        j++;
        }
        k++;
    }
    while (i < leftLen) {
        arr[k] = left[i];
        i++;
        k++;
    }
    while (j < rightLen) {
        arr[k] = right[j];
        j++;
        k++;
    }
    return { arr, ans };
};

let divideArray = (arr, ans) => {
    if (arr.length < 2) return { arr, ans };
    let N = arr.length;
    let mid = Math.round(N / 2);
    let left = arr.slice(0, mid);
    let right = arr.slice(mid, N);
    ans = ans;
    divideArray(left, ans);
    divideArray(right, ans);
    let blabla = mergeSort(left, right, arr, ans);
    return blabla;
};

let merge = (arr, ans) => {
    let res = divideArray(arr, ans);
    return res;
};

function main(input) {
    let arr = [1, 4, 3, 2, 5];
    let ans = 0;
    let output = merge(arr, ans);
    console.log('Final', output);
}

main();

In mergeSort function When the input of the left array is [1,4] and the right array is [3] the ans will be updated as 1, also when the left array is [1,3,4] and right is [2,5] the ans will be updated as 2. I would like to add both this ans values and return it as 3. But somewhere am making a mistake while returning. Any help will be appreciated.

JsFiddle

EDIT:

Please note that am trying to achieve it via MergeSort and recursion i know in lot of other ways i can solve this problem for instance i have clearly mentioned i had solved it by having a global variable,which is not a good practice so please provide me a solution only via recursion and merge sort


Solution

  • https://codepen.io/Santhoshsanz/pen/dybedgm?editors=1112

        // let ans = 0;
    
    let mergeSort = (left, right, arr, ans) => {
      // console.log(left)
      // console.log("*****")
      // console.log(right)
      // console.log("*****£££")
        let i = 0,
            j = 0,
            k = 0;
        let leftLen = left.length,
            rightLen = right.length;
        while (i < leftLen && j < rightLen) {
            if (left[i] <= right[j]) {
            arr[k] = left[i];
            i++;
            } else {
            arr[k] = right[j];
            ans += leftLen - i;
            j++;
            }
            k++;
        }
        while (i < leftLen) {
            arr[k] = left[i];
            i++;
            k++;
        }
        while (j < rightLen) {
            arr[k] = right[j];
            j++;
            k++;
        }
    
        return { arr, ans };
    };
    
    let divideArray = (arr, ans) => {
        if (arr.length < 2) return { arr, ans };
        let N = arr.length;
        let mid = Math.round(N / 2);
        let left = arr.slice(0, mid);
        let right = arr.slice(mid, N);
        ans = ans;
        let lans=divideArray(left, ans).ans;
        let bAns=divideArray(right, ans).ans;
      // console.log(bAns)
        let blabla= mergeSort(left, right, arr, lans+bAns);
      return blabla
    };
    
    let merge = (arr, ans) => {
        let res=0+ divideArray(arr, ans).ans;
      // console.log("asdad")
      // console.log(res)
        return res;
    };
    
    function main(input) {
        let arr = [1,4,3,2,5];
        let ans = 0;
        let output = merge(arr, ans);
        console.log('Final', output);
    }
    
    main();
    

    I have persisted the count val inside your divide array and used it to merge the 2 counts from the split array i.e left and right direction split