归并排序练习
Posted 小智RE0
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了归并排序练习相关的知识,希望对你有一定的参考价值。
力扣88. 合并两个有序数组
链接:https://leetcode-cn.com/problems/merge-sorted-array/
class Solution
public void merge(int[] nums1, int m, int[] nums2, int n)
//使用临时数组,先将数组排序到其中;
int[] temp = new int[m+n];
//临时数组的指针index;
int index = 0;
//数组1指针left 数组2指针right;
int left = 0;
int right = 0;
//在不超出指针范围的情况内操作;
while(left <m && right<n)
if(nums1[left]<=nums2[right])
temp[index++] = nums1[left++];
else
temp[index++] = nums2[right++];
//若某个数组没有结束,则直接拼接;
while(left<m)
temp[index++] = nums1[left++];
while(right<n)
temp[index++] = nums2[right++];
//数组内容复制到nums1;
for(int i = 0;i<m+n;i++)
nums1[i] = temp[i];
力扣剑指offer51题练习
剑指 Offer 51. 数组中的逆序对
在归并排序的过程中,第二段数组归并时 计算出逆序对的个数;
[逆序对,左边的数组元素 大于 右边的数组元素]
class Solution
//归并排序思想;
int res =0;
public int reversePairs(int[] nums)
int n = nums.length;
if(n<1) return 0;
//定义临时数组;
int[] temp = new int[n];
//调用方法;
int res = reversePairs(nums,0,n-1,temp);
return res;
//在[left,right]区间完成分组排序任务,计算出逆序对;
private int reversePairs(int[] nums,int left,int right,int[] temp)
//递归终止条件;
if(left == right)
return 0;
//分隔点;
int mid = left +(right -left)/2;
//递归计算左右的逆序对;
int leftPair = reversePairs(nums,left,mid,temp);
int rightPair = reversePairs(nums,mid+1,right,temp);
//复制一份数组;
for(int i = left;i<=right;i++)
temp[i] = nums[i];
//此处可优化;
if(nums[mid]<=nums[mid+1])
return leftPair + rightPair;
//归并排序处理;
int mergePair = mergeSort(nums,left,right,mid,temp);
return leftPair + rightPair + mergePair;
//归并排序;
private int mergeSort(int[] nums, int left,int right,int mid,int[] temp)
int i = left;
int j = mid+1;
int resPair = 0;
//定义出归并数组的索引 index;
for(int index = left;index<=right;index++)
//边界条件处理;
if(i == mid+1)
nums[index] = temp[j++];
else if(j == right+1)
nums[index] = temp[i++];
else if(temp[i] <= temp[j])
nums[index] = temp[i++];
else
nums[index] = temp[j++];
//注意这里的逆序对计算时计算规则,
//是第二部分数组合适时,此时的左边数组中剩余元素,
//正好就是 中点mid-此时i的位置, 由于索引i会由0开始,则加1;
resPair +=(mid - i)+1;
return resPair;
力扣315题练习
315. 计算右侧小于当前元素的个数
类似于剑指51题;不过这里需要将逆序对的个数具体查找存储;
class Solution
public List<Integer> countSmaller(int[] nums)
List<Integer> list = new ArrayList<>();
int n = nums.length;
//类似于剑指51的逆序对问题,不过它要把逆序对拼接称为一个集合;
//使用辅助索引数组;
int[] indexArr = new int[n];
int[] temp = new int[n];
int[] res = new int[n];
//辅助数组初始化;
for(int i=0;i<n;i++)
indexArr[i]=i;
//调用方法,在[0~n-1]区间内计算;
countSmaller(nums,0,n-1,temp,indexArr,res);
//将结果数组中的值存入到集合;
for(int i=0;i<n;i++)
list.add(res[i]);
return list;
//使用方法,在[left~right]区间内找到逆序对;
private void countSmaller(int[] nums,int left,int right,int[] temp,int[] indexArr,int[] res)
//递归终止条件;
if(left == right)
return;
//分隔点;
int mid = left +(right - left)/2;
//分别递归;
countSmaller(nums,left,mid,temp,indexArr,res);
countSmaller(nums,mid+1,right,temp,indexArr,res);
//优化提前退出;
if(nums[indexArr[mid]]<=nums[indexArr[mid+1]])
return;
//归并排序,当然要把逆序对UC存入到结果数组;
mergeSort(nums,left,right,mid,temp,indexArr,res);
//归并排序;
private void mergeSort(int[] nums,int left, int right,int mid,int[] temp,int[]indexArr,int[] res)
//对临时数组赋值;
for(int w = left;w<=right;w++)
//注意临时数组其实放的是索引;
temp[w] = indexArr[w];
//两个数组的指针;
int i = left;
int j = mid+1;
//排序数组的处理;
for(int index = left;index<=right;index++)
//边界条件处理;
if(i == mid+1)
//注意这里操作赋值的是索引;
indexArr[index] = temp[j++];
else if(j == right+1)
indexArr[index] = temp[i++];
//计算右侧后序数组的逆序对;
res[indexArr[index]] += (right-mid);
else if(nums[temp[i]]<=nums[temp[j]])
indexArr[index] = temp[i++];
//计算右侧后序数组的逆序对;
res[indexArr[index]] += j -mid -1;
else
indexArr[index] = temp[j++];
力扣439题练习
493. 翻转对
class Solution
public int reversePairs(int[] nums)
int n = nums.length;
if(n < 2) return 0;
//使用临时数组;
int[] temp = new int[n];
//调用方法;
return reversePairs(nums,0,n-1,temp);
//在[left~right] 区间内计算;
private int reversePairs(int[] nums,int left, int right, int[] temp)
//递归结束条件;
if(left == right)
return 0;
//分隔点;
int mid = left +(right - left)/2;
//左右递归;
int leftPair = reversePairs(nums,left,mid,temp);
int rightPair = reversePairs(nums,mid+1,right,temp);
//复制数组;
for(int i=left;i<=right;i++)
temp[i] = nums[i];
//归并排序中计算;
int mergePair = mergeSort(nums,left,right,mid,temp);
return leftPair + rightPair + mergePair;
//归并排序;[left~right]区间
private int mergeSort(int[] nums,int left,int right,int mid,int[] temp)
//返回值;
int res = 0;
//分隔的两个数组指针;
int i = left;
int j = mid+1;
//首先计算反转对;
//在left-right范围内;
while(i<=mid && j<=right)
if((long)temp[i] >2* (long)temp[j])
res += mid - i + 1;
j++;
else
i++;
//指针复位归并排序;
i = left;
j = mid+1;
for(int index = left;index<=right;index++)
//处理边界条件;
if(i == mid+1)
nums[index] = temp[j++];
else if(j == right+1)
nums[index] = temp[i++];
else if(temp[i] <= temp[j])
nums[index] = temp[i++];
else
nums[index] = temp[j++];
return res;
以上是关于归并排序练习的主要内容,如果未能解决你的问题,请参考以下文章