剑指offer-排序
1.数组中重复的数字
使nums[i] = i;
交换不动了就是重复的数字。
int duplicate(vector<int>& nums) {
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] < 0 or nums[i] >= nums.size())
return -1;
}
for (int i = 0; i < nums.size(); ++i) {
while (nums[i] != i and nums[i] != nums[nums[i]]) {
swap(nums[i], nums[nums[i]]);
}
if (nums[i] != i and nums[i] == nums[nums[i]])
return nums[i];
}
return -1;
}
2.数组中的逆序对
归并排序。
class Solution {
using LL = long long;
const int MOD = 1000000007;
vector<int> temp;
LL mergeSort(vector<int>& nums, int l, int r){
if(l >= r) return 0;
int mid = (l + r) >> 1;
LL res = mergeSort(nums, l, mid) + mergeSort(nums, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while(i <= mid and j <= r){
if(nums[i] <= nums[j]) temp[k++] = nums[i++];
else {
temp[k++] = nums[j++];
res += mid - i + 1;
}
}
while(i <= mid) temp[k++] = nums[i++];
while(j <= r) temp[k++] = nums[j++];
for(int i = l, j = 0; i <= r; ++i, ++j) nums[i] = temp[j];
return res % MOD;
}
public:
int InversePairs(vector<int> data) {
if (data.size() == 1) return 0;
temp = vector<int>(data.size());
return mergeSort(data, 0, data.size() - 1);
}
};
3.最小的K个数
快排
快排返回的数字l
是一个下标,[0, l]
之间就是最小的l + 1
个数(该区间无序)。
class Solution {
int quickSort(vector<int>& nums, int l, int r, int k) {
if (l >= r) return l;
int i = l - 1, j = r + 1, x = nums[l + r >> 1];
while (i < j) {
do i++; while (nums[i] < x);
do j--; while (nums[j] > x);
if (i < j) swap(nums[i], nums[j]);
}
int len = j - l + 1;
if (k <= len) return quickSort(nums, l, j, k);
else return quickSort(nums, j + 1, r, k - len);
}
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
if (k == 0 or input.empty()) return {};
auto end = quickSort(input, 0, input.size() - 1, k);
return vector<int>(input.begin(), input.begin() + end + 1);
}
};
堆排
使用make_heap
函数和仿函数greater<int>()
建小根堆。
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
int n = input.size();
if (n == 0) return {};
vector<int> res(k);
for (int i = 0; i < k; ++i) {
make_heap(input.begin(), input.begin() + n, greater<int>());
res[i] = input[0];
swap(input[0], input[--n]);
}
return res;
}
4.数据流中的中位数
上面是一个小根堆,下面是一个大根堆。
class Solution {
priority_queue<int> maxQ;
priority_queue<int, vector<int>, greater<int>> minQ;
public:
void Insert(int num) {
maxQ.push(num);
if (!minQ.empty() and maxQ.top() > minQ.top()) {
int maxV = maxQ.top(), minV = minQ.top();
maxQ.pop(), minQ.pop();
maxQ.push(minV);
minQ.push(maxV);
}
if (maxQ.si***Q.size() + 1) {
minQ.push(maxQ.top());
maxQ.pop();
}
}
double GetMedian() {
if ((maxQ.si***Q.size()) & 1) return maxQ.top();
else return (maxQ.top() + minQ.top()) / 2.0;
}
};