归并排序代码
public class 归并排序及扩展 {
public static void mergeSort(int[] nums) {
mergeSort(nums, 0, nums.length - 1);
}
private static void mergeSort(int[] nums, int l, int r) {
if (l == r) {
return;
}
int mid = l + ((r-l) >> 1);
mergeSort(nums, l, mid);
mergeSort(nums, mid + 1, r);
merge(nums, l, r, mid);
}
public static void mergeSort2(int[] nums) {
int step = 1;
while (step < nums.length) {
for (int i = 0; i < nums.length && i+step < nums.length; i += 2*step) {
merge(nums, i, Math.min(i + 2*step - 1, nums.length-1), i + step - 1);
}
if (step > nums.length/2) {
break;
}
step <<= 1;
}
}
private static void merge(int[] nums, int l, int r, int mid) {
int[] help = new int[r-l+1];
for (int i = l; i <= r; i++) {
help[i-l] = nums[i];
}
int left = l;
int right = mid + 1;
int index = l;
while (left <= mid && right <= r) {
if (help[left - l] <= help[right - l]) {
nums[index] = help[left-l];
left ++;
} else {
nums[index] = help[right-l];
right ++;
}
index ++;
}
while (left <= mid) {
nums[index++] = help[left-l];
left ++;
}
while (right <= r) {
nums[index++] = help[right-l];
right ++;
}
}
}
扩展题:求较小和
public static int minSum(int[] nums, int l, int r) {
if (l == r) {
return 0;
}
int mid = l + ((r-l) >> 1);
return minSum(nums, l, mid) +
minSum(nums, mid+1, r) +
minSumMerge(nums, l, r, mid);
}
public static int minSumMerge(int[] nums, int l, int r, int mid) {
int[] help = new int[r-l+1];
for (int i = l; i <= r; i++) {
help[i-l] = nums[i];
}
int ans = 0;
int left = l;
int right = mid + 1;
int index = l;
while (left <= mid && right <= r) {
if (help[left-l] < help[right-l]) {
nums[index++] = help[left-l];
ans += help[left-l] * (r-right+1);
left ++;
} else {
nums[index++] = help[right-l];
right ++;
}
}
while (left <= mid) {
nums[index++] = help[left-l];
left ++;
}
while (right <= r) {
nums[index++] = help[right-l];
right ++;
}
return ans;
}
扩展题:逆序对
public static int niXuDui(int[] nums, int l, int r) {
if (l == r) {
return 0;
}
int mid = l + ((r-l) >> 1);
return niXuDui(nums, l, mid) +
niXuDui(nums, mid + 1, r) +
niXuDuiMerge(nums, l, r, mid);
}
public static int niXuDuiMerge(int[] nums, int l, int r, int mid) {
int[] help = new int[r-l+1];
for (int i = l; i <= r; i++) {
help[i-l] = nums[i];
}
int ans = 0;
int left = mid;
int right = r;
int index = r;
while (left >= l && right > mid) {
if (help[right - l] < help[left - l]) {
ans += left - l + 1;
nums[index--] = help[right - l];
right --;
} else {
nums[index--] = help[left - l];
left --;
}
}
while (left >= l) {
nums[index--] = help[left - l];
left --;
}
while (right > mid) {
nums[index--] = help[right - l];
right --;
}
return ans;
}