< >C++快速排序法和Select K问题 2021-06-08

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
void swap(int &a,int &b){
	int t=a;a=b;b=t;
}
void print(int arr[],int l){
	for(int i=0;i<=l;i++) cout<<arr[i]<<" ";
	cout<<endl;
}

/*---------基本的快速排序---------*/
int partition(int arr[],int l,int r){
	//arr[l+1...j]<v ; arr[j+1....i]>=v
	int j=l;
	for(int i=l+1;i<=r;i++)
		if(arr[i]<arr[l]){
			j++;swap(arr[i],arr[j]);
		}
	swap(arr[l],arr[j]);
	return j;
}
void QuickSort(int arr[],int l,int r){
	if(l>=r) return;
	int p=partition(arr,l,r);
	QuickSort(arr,l,p-1);
	QuickSort(arr,p+1,r);
}

/*---------使用插入排序优化的快速排序---------*/
void insertsort(int arr[],int l,int r){
	for(int i=r-1;i>=l;i--){
		int t=arr[i];int j;
		for(j=i;j+1<=r&&t>arr[j+1];j++)
			arr[j]=arr[j+1];
		arr[j]=t; 
	}
} 
void QuickSort2(int arr[],int l,int r){
	if(r-l<=15){
		insertsort(arr,l,r);return;
	} 
	
	//为快速排序添加随机索引 
	srand(time(NULL));
	int t=rand()%(r-l)+l+1;
	swap(arr[l],arr[t]);
	
	int p=partition(arr,l,r);
	QuickSort2(arr,l,p-1);
	QuickSort2(arr,p+1,r);
}

/*---------双路快速排序---------*/
int partition_2ways(int arr[],int l,int r){
	//为快速排序添加随机索引 
	srand(time(NULL));
	int t=rand()%(r-l)+l+1;
	swap(arr[l],arr[t]);
	
	//arr[l+1...i-1]<=v ; arr[j+1....i]>=v
	int i=l+1,j=r;
	while(true){
		while(i<=j&&arr[i]<=arr[l]) i++;
		while(j>=i&&arr[j]>=arr[l]) j--;
		if(i>=j) break;
		swap(arr[i],arr[j]);i++;j--;
	}
	swap(arr[l],arr[j]);
	return j;
}
void QuickSort_2ways(int arr[],int l,int r){
	if(l>=r) return;
	int p=partition_2ways(arr,l,r);
	QuickSort_2ways(arr,l,p-1);
	QuickSort_2ways(arr,p+1,r);
}

/*---------三路快速排序---------*/
void QuickSort_3ways(int arr[],int l,int r){
	if(l>=r) return;
	
	//为快速排序添加随机索引 
	srand(time(NULL));
	int t=rand()%(r-l)+l+1;
	swap(arr[l],arr[t]);
	
	//arr[l+1,lt]<v ; arr[lt+1,i-1]==v ; arr[gt,r]>v 
	int lt=l,i=l+1,gt=r+1;
	while(i<gt){
		if(arr[i]<arr[l]){lt++;swap(arr[i],arr[lt]);i++;}
		else if(arr[i]>arr[l]){gt--;swap(arr[i],arr[gt]);}
		else {i++;}//arr[i]==arr[l]
	}
	swap(arr[l],arr[lt]);
	
	//arr[l,lt-1]<v ; arr[lt,gt-1]==v ; arr[gt,r]>v 
	QuickSort_3ways(arr,l,lt-1);
	QuickSort_3ways(arr,gt,r);
}

int main(int argc, char *argv[])
{
	int arr[]={4,6,2,3,1,5,7,8};
	QuickSort_3ways(arr,0,7);
	print(arr,7);

	return 0;
}

75. 颜色分类
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

示例 1:
输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]

示例 2:
输入:nums = [2,0,1]
输出:[0,1,2]

示例 3:
输入:nums = [0]
输出:[0]

示例 4:
输入:nums = [1]
输出:[1]
 

提示:
n == nums.length
1 <= n <= 300
nums[i] 为 0、1 或 2
 

进阶:
你可以不使用代码库中的排序函数来解决这道题吗?
你能想出一个仅使用常数空间的一趟扫描算法吗?

class Solution {
public:
    void swap(int &a,int &b){
        int t=a;a=b;b=t;
    }
    void sortColors(vector<int>& nums) {
        int zero=-1,i=0,two=nums.size();
        while(i<two){
            if(nums[i]==0){zero++;swap(nums[i],nums[zero]);i++;}
            else if(nums[i]==2){two--;swap(nums[i],nums[two]);}
            else i++;
        }
    }
};

剑指 Offer 40. 最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]

示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]
 
限制:
0 <= k <= arr.length <= 10000
0 <= arr[i] <= 10000

class Solution {
public:
    void swap(int &a,int &b){int t=a;a=b;b=t;}
    int partition(vector<int>& arr,int l,int r){
        srand(time(NULL));
        int p=l+rand()%(r-l+1);
        swap(arr[l],arr[p]);

        int i=l+1,j=r;
        while(true){
            while(i<=j&&arr[i]<arr[l])i++;
            while(i<=j&&arr[l]<arr[j])j--;
            if(i>=j) break;
            swap(arr[i],arr[j]);i++;j--;
        }
        swap(arr[l],arr[j]);
        return j;
    }
    int selectK(vector<int>& arr,int l,int r,int k){
        int t=partition(arr,l,r);
        if(t==k) return arr[t];
        if(k<t) return selectK(arr,l,t-1,k);
        return selectK(arr,t+1,r,k);
    }
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
        if(k==0) return  vector<int>(0);
        int t=selectK(arr,0,arr.size()-1,k-1);
        return  vector<int>(arr.begin(),arr.begin()+k);
    }
};

215. 数组中的第K个最大元素
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

class Solution {
public:
    void swap(int &a,int &b){int t=a;a=b;b=t;}
    int partition(vector<int>& arr,int l,int r){
        srand(time(NULL));
        int p=l+rand()%(r-l+1);
        swap(arr[l],arr[p]);

        int i=l+1,j=r;
        while(true){
            while(i<=j&&arr[i]<arr[l])i++;
            while(i<=j&&arr[l]<arr[j])j--;
            if(i>=j) break;
            swap(arr[i],arr[j]);i++;j--;
        }
        swap(arr[l],arr[j]);
        return j;
    }
    int selectK(vector<int>& nums,int l,int r,int k){
        int t=partition(nums,l,r);
        if(t==k) return nums[t];
        if(k<t) return selectK(nums,0,t-1,k);
        return selectK(nums,t+1,r,k);
    }
    int findKthLargest(vector<int>& nums, int k) {
        return selectK(nums,0,nums.size()-1,nums.size()-k);
    }
};

猜你喜欢

转载自blog.csdn.net/lybc2019/article/details/117700510