leetcode912 排序数组
给你一个整数数组 nums
,请你将该数组升序排列。
//v1.0 未优化的快排
class Solution {
public int[] sortArray(int[] nums) {
int low=0;
int high=nums.length-1;
QSort(nums,low,high);
return nums;
}
public void QSort(int[] nums, int low, int high){
int pivot;
if(low<high){
//将nums一分为二,算出枢轴值pivot
pivot=Partition(nums,low,high);
//对低子表递归排序
QSort(nums,low,pivot-1);
//对高子表递归排序
QSort(nums,pivot+1,high);
}
}
//交换顺序表中子表的记录,使枢轴记录到位,并返回其位置
//此时在它之前(后)的记录均不大于(小)于它
public int Partition(int[] nums,int low,int high){
int pivotKey;
pivotKey=nums[low];
while(low<high){
while(low<high&&nums[high]>=pivotKey) high--;
swap(nums,low,high);
while(low<high&&nums[low]<=pivotKey) low++;
swap(nums,low,high);
}
return low;
}
public void swap(int[] nums, int i, int j){
int temp=nums[j];
nums[j]=nums[i];
nums[i]=temp;
}
}
//v2.0 优化后的快排
class Solution {
public int[] sortArray(int[] nums) {
int low=0;
int high=nums.length-1;
QSort(nums,low,high);
return nums;
}
public void QSort(int[] nums, int low, int high){
int pivot;
while(low<high){
//将nums一分为二,算出枢轴值pivot
pivot=Partition(nums,low,high);
//对低子表递归排序
QSort(nums,low,pivot-1);
//对高子表递归排序
low=pivot+1;
}
}
//交换顺序表中子表的记录,使枢轴记录到位,并返回其位置
//此时在它之前(后)的记录均不大于(小)于它
public int Partition(int[] nums,int low,int high){
int pivotKey;
//优化枢轴选取
int m=low+(high-low)/2;
if(nums[high]<nums[m]) swap(nums,high,m);
if(nums[high]<nums[low]) swap(nums,high,low);
if(nums[low]<nums[m]) swap(nums,low,m);
pivotKey=nums[low];
while(low<high){
while(low<high&&nums[high]>=pivotKey) high--;
nums[low]=nums[high];
while(low<high&&nums[low]<=pivotKey) low++;
nums[high]=nums[low];
}
nums[low] = pivotKey;
return low;
}
public void swap(int[] nums, int i, int j){
int temp=nums[j];
nums[j]=nums[i];
nums[i]=temp;
}
}
class Solution {
public int[] sortArray(int[] nums) {
//堆排序
int i;
for (i = nums.length / 2 - 1; i >= 0; i--) {
HeapAdjust(nums, i, nums.length);
}
for (i = nums.length - 1; i >= 1; i--) {
int temp = nums[i];
nums[i] = nums[0];
nums[0] = temp;
HeapAdjust(nums, 0, i);
}
return nums;
}
public void HeapAdjust(int[] nums, int parent, int length) {
int temp = nums[parent];
int lChild = 2 * parent + 1;
while (lChild < length) {
if (lChild + 1 < length && nums[lChild + 1] > nums[lChild]) lChild++;
if (temp > nums[lChild]) break;
nums[parent] = nums[lChild];
parent = lChild;
lChild = 2 * lChild + 1;
}
nums[parent] = temp;
}
}
剑指51 数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
//利用归并算法(分治思想)
class Solution {
private int count;
public int reversePairs(int[] nums) {
int len = nums.length;
merge(nums,0,len-1);
return count;
}
private void merge(int[] arr, int left, int right){
if(left<right){
int mid = left+((right-left)>>1);
merge(arr,left,mid);
merge(arr,mid+1,right);
mergeSort(arr,left,mid,right);
}
}
private void mergeSort(int[] arr,int left, int mid, int right){
int[] temp = new int[right-left+1];
int index=0;
int temp1 = left;
int temp2 = mid+1;
while(temp1<=mid&&temp2<=right){
if(arr[temp1]<=arr[temp2]){
temp[index++]=arr[temp1++];
}else{
count+=mid-temp1+1; //主要代码
temp[index++]=arr[temp2++];
}
}
if(temp2<=right) System.arraycopy(arr,temp2,temp,index,right-temp2+1);
if(temp1<=mid) System.arraycopy(arr,temp1,temp,index,mid-temp1+1);
System.arraycopy(temp,0,arr,left,right-left+1);
}
}
leetcode493 翻转对
给定一个数组 nums
,如果 i < j
且 nums[i] > 2*nums[j]
我们就将 (i, j)
称作一个重要翻转对。
class Solution {
private int count;
public int reversePairs(int[] nums) {
int len = nums.length;
merge(nums,0,len-1);
return count;
}
private void merge(int[] arr, int left, int right){
if(left<right){
int mid = left+((right-left)>>1);
merge(arr,left,mid);
merge(arr,mid+1,right);
mergeSort(arr,left,mid,right);
}
}
private void mergeSort(int[] arr,int left, int mid, int right){
int[] temp = new int[right-left+1];
int index=0;
int temp1 = left;
int temp2 = mid+1;
//计算翻转对
while(temp1<=mid&&temp2<=right){
if(arr[temp1]>2*(long)arr[temp2]){
count+=mid-temp1+1;
temp2++;
}else{
temp1++;
}
}
//将temp1和temp2复原
temp1=left;
temp2=mid+1;
while(temp1<=mid&&temp2<=right){
if(arr[temp1]<=arr[temp2]){
temp[index++]=arr[temp1++];
}else{
temp[index++]=arr[temp2++];
}
}
if(temp2<=right) System.arraycopy(arr,temp2,temp,index,right-temp2+1);
if(temp1<=mid) System.arraycopy(arr,temp1,temp,index,mid-temp1+1);
System.arraycopy(temp,0,arr,left,right-left+1);
}
}
剑指40 最小的k个数
输入整数数组 arr
,找出其中最小的 k
个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
class Solution {
private static int INSERTION_MAX_VALUE = 7;
private static int K = 0;
public int[] getLeastNumbers(int[] arr, int k) {
K = k;
int low = 0;
int hight = arr.length-1;
quickSort(arr,low,hight);
int[] res = Arrays.copyOfRange(arr,0,k);
return res;
}
public void quickSort(int[] arr, int low, int hight){
int right = hight;
int left = low;
if(right<=left) return;
if((right-left+1)<=7){
insertSort(arr,left,right);
return;
}
int pivot = arr[left];
int i = left+1;
while(i<=right){
if(arr[i]>pivot){
swap(arr,i,right--);
}else if(arr[i]<pivot){
swap(arr,i++,left++);
}else{
i++;
}
}
if(left+1>=K){
quickSort(arr,low,left-1);
}else{
quickSort(arr,low,left-1);
quickSort(arr,left+1,hight);
}
}
public void insertSort(int[] arr, int low, int hight){
for(int m = low+1;m<=hight;m++){
int temp = arr[m];
int n=m-1;
for(;n>=0;n--){
if(arr[n]>temp){
arr[n+1]=arr[n];
continue;
}
break;
}
arr[n+1] = temp;
}
}
public void swap(int[] arr,int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}