Program to implement Merge Sort Algorithm So, I just learned the Merge Sort algorithm from Youtube and tried implementing it. Is this the most efficient way to do it? 

public class MergeSort {

private static void merge(int[] left, int[] right, int[] arr) {
int i=0, j=0, k=0;
while(i&lt;left.length &amp;&amp; j&lt;right.length) {
if(left[i]&lt;right[j]) {
    arr[k++]=left[i++]; 
    }
else {
    arr[k++]=right[j++];
    }
}
while(i&lt;left.length)
    arr[k++] = left[i++];
while(j&lt;right.length)
    arr[k++] = right[j++];
}

public static void mergeSort(int[] arr) {
if(arr.length&lt;2)
    return;

int mid = arr.length/2;
int[] left = new int[mid];
int[] right;

//checking wether array is even or not, based on which right array length           is defined
int rightLength;
if((arr.length&amp;1)==0) //if even
    rightLength = mid;
else
    rightLength = mid+1;
right = new int[rightLength];

//assign values to left and right arrays from the original array
for(int i=0;i&lt;mid;i++)
    left[i] = arr[i];

for(int j=0;j&lt;rightLength;j++)
    right[j] = arr[j+mid];

mergeSort(left);
mergeSort(right);
merge(left,right,arr);

}

}
Is this the most efficient way to do it?


No.  First thing, if efficiency is your goal, you don't use mergesort for small inputs.  An insertion sort is lower overhead for small inputs.  I don't know where the crossover point is, but it is almost certainly higher than one.  So 


if(arr.length&lt;2)
    return;



would become something like 

if (arr.length &lt; MINIMUM_MERGESORT_SIZE) {
    insertionSort(arr);
    return;
}


Allocating and copying arrays


int rightLength;
if((arr.length&amp;1)==0) //if even
    rightLength = mid;
else
    rightLength = mid+1;
right = new int[rightLength];



This seems rather complicated.  Consider 

int[] right = new int[arr.length - left.length];


Same result.  Less code.  I don't know that it changes the efficiency that much, as the operations are pretty cheap.  But it does ensure that you don't accidentally create an error by messing up the length calculation.  

What has a better chance of improving efficiency is combining the allocation above with the copying.  So get rid of the declarations and 


for(int i=0;i&lt;mid;i++)
    left[i] = arr[i];

for(int j=0;j&lt;rightLength;j++)
    right[j] = arr[j+mid];



Now we can just say 

    int[] left = Arrays.copyOfRange(numbers, 0, numbers.length / 2);
    int[] right = Arrays.copyOfRange(numbers, left.length, numbers.length);


This will take advantage of other optimizations, like copying blocks of memory at once.  It likely also avoids clearing the new array, as we copy over those values anyway.  

I changed the name of arr to numbers, which I find more descriptive.  Another complaint you'll hear about arr as a name is it makes everyone sound like a pirate when they say it.  But more professionally, abbreviating by a small number of characters doesn't help much.  You could have just said array.  

I added more indentation.  Usually we indent every time we have a { and remove indent every time we }.  

Alternatives

Of course, if we really wanted to sort efficiently, we'd just say 

    Collections.sort(numbers);


We'd let it work out what method and how to split up the arrays.  But you may be trying this purely as an exercise.