文章目录
1、快排
递归非递归,
快排的空间复杂度:O(logN),最差O(N)递归栈空间
1.1、递归
快排主要是两部分,哨兵划分,和递归
一:确定哨兵,(默认哨兵是arr[l],一趟把比哨兵小的放左边,把比哨兵大的放右边,当i和j相遇的时候,把哨兵放到正确的位置上。
二:之后进行下一轮的递归。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
void qsort(vector<int>& arr, int l, int r) {
if (l >= r) return; //子数组长度为1时,终止递归
int i = l, j = r; // 哨兵划分的操作,以arr[l]为哨兵,
while (i < j) { // 一趟
while (i < j && arr[j] >= arr[l]) j--; // 先从右往左,
while (i < j && arr[i] <= arr[l]) i++;
swap(arr[i], arr[j]); // 交换,
}
swap(arr[i], arr[l]); // i==j时候,把这个i和哨兵l,相交换,之后调用左右子序列,
qsort(arr, l, i - 1);
qsort(arr, i + 1, r);
}
int main() {
vector<int>nums; // 构造输入
int num;
do {
cin >> num;
nums.push_back(num);
} while (getchar() != '\n');
int l = 0, r = nums.size() - 1;
qsort(nums, 0, r);
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << " ";
}
cout << endl;
return 0;
}
3、手写归并排序
3.1、思路
递归写法,搞一个msort(),再去调用merge()函数
3.5、复杂度
时间: O(NlogN)
空间:O(N)
6、code
3、归并排序:
void merge(vector<int>&nums, int L, int M, int R) {
vector<int>help(R - L + 1); // 辅助数组
int i = 0;
int p1 = L; // 左边一半
int p2 = M + 1; // 右边一半
while (p1 <= M && p2 <= R) {
help[i++] = nums[p1] < nums[p2] ? nums[p1++] : nums[p2++];
}
while (p1 <= M) { // 有剩余的就填充进来。
help[i++] = nums[p1++];
}
while (p2 <= R) {
help[i++] = nums[p2++];
}
for ( i = 0; i < help.size(); i++) {
nums[L + i] = help[i];
}
}
void msort(vector<int> &nums, int L, int R) {
if (L == R) return;
int mid = L + ( (R - L) >> 1); // 小括号,得加上
msort(nums, L, mid);
msort(nums, mid + 1, R);
merge(nums, L, mid, R);
}
3.2、归并排序应用1:小和问题
小和问题:
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组 的小和。
例子:
[1,3,4,2,5]
1左边比1小的数,没有;
3左边比3小的数,1;
4左边比4小的数,1、3;
2左边比2小的数,1;
5左边比5小的数,1、3、4、2;
所以小和为1+1+3+1+1+3+4+2=16
#include<iostream>
#include<vector>
using namespace std;
int merge(vector<int>& nums, int L, int M, int R) {
vector<int> help(R - L + 1);
int i = 0;
int p1 = L;
int p2 = M + 1;
int res = 0;
while (p1 <= M && p2 <= R) {
res += nums[p1] < nums[p2] ? (R - p2 + 1) * nums[p1] : 0; // 这一行要放在上面一行
help[i++] = nums[p1] < nums[p2] ? nums[p1++] : nums[p2++];
}
while (p1 <= M) {
help[i++] = nums[p1++];
}
while (p2 <= R) {
help[i++] = nums[p2++];
}
for (i = 0; i < help.size(); i++) {
nums[L + i] = help[i];
}
return res;
}
int msort(vector<int>& nums, int L, int R) {
if (L >= R) return 0;
int mid = L + ((R - L) >> 1);
return msort(nums, L, mid) + msort(nums, mid + 1, R) + merge(nums, L, mid, R);
}
int smallSum(vector<int>& nums) {
if (nums.size() < 2) return 0;
return msort(nums, 0, nums.size() - 1);
}
int main() {
vector<int>nums; // 构造输入
int num;
do {
cin >> num;
nums.push_back(num);
} while (getchar() != '\n');
int l = 0, r = nums.size() - 1;
//msort(nums, 0, r);
int res = smallSum(nums);
cout << res << endl;
//for (int i = 0; i < nums.size(); i++) {
// cout << nums[i] << " ";
//}
cout << endl;
return 0;
}
3.3、归并排序应用2:统计逆序对
class Solution {
public:
int mergeSort(vector<int>& nums, vector<int>& tmp, int l, int r) {
if (l >= r) {
return 0;
}
int mid = (l + r) / 2;
int inv_count = mergeSort(nums, tmp, l, mid) + mergeSort(nums, tmp, mid + 1, r);
int i = l, j = mid + 1, pos = l;
while (i <= mid && j <= r) {
if (nums[i] <= nums[j]) {
tmp[pos] = nums[i];
++i;
inv_count += (j - (mid + 1));
}
else {
tmp[pos] = nums[j];
++j;
}
++pos;
}
for (int k = i; k <= mid; ++k) {
tmp[pos++] = nums[k];
inv_count += (j - (mid + 1));
}
for (int k = j; k <= r; ++k) {
tmp[pos++] = nums[k];
}
copy(tmp.begin() + l, tmp.begin() + r + 1, nums.begin() + l);
return inv_count;
}
int reversePairs(vector<int>& nums) {
int n = nums.size();
vector<int> tmp(n);
return mergeSort(nums, tmp, 0, n - 1);
}
};
4、堆排序,堆结构的应用
4.1优先队列,重排近似有序的数组,与最终位置相差不大于K,
void sortedArrDistancelessK(vector<int>& nums, int k) {
priority_queue<int, vector<int>, cmp> que;
int index = 0;
for (; index < min((int)nums.size(), k); index++) {
que.push(nums[index]);
}
int i = 0;
for (; index < (int)nums.size(); i++, index++) {
que.push(nums[index]);
nums[i] = que.top();
que.pop();
}
while (!que.empty()) {
nums[i++] = que.top();
que.pop();
}
}
5、给定一个二叉树的前序和中序遍历
判断这个树是否镜面自己对称,如果不对称就把这个树中的最大的节点的val返回,如果是对称的就把最大的节点的对应的节点的val返回,
输入3行,
第一行:树的节点个数
第二行:前序遍历
第3行:中序遍历
例:
3
1 3 4
3 1 4
输出:3
输入:
5
1 3 5 7 2
5 3 1 2 7
输出:
7
自己写的:但是没过!!!
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
#include<unordered_map>
#include<stack>
#include<queue>
using namespace std;
struct Node {
int val;
Node * left;
Node * right;
Node(int x) :val(x), left(nullptr), right(nullptr) {}
};
bool meetings(vector<vector<int>> & nums) {
sort(nums.begin(), nums.end());
int n = nums.size();
priority_queue<int, vector<int>, greater<int>>heap;
for (int i = 1; i < nums.size(); i++) {
if (nums[i][0] > heap.top()) {
heap.pop();
}
heap.push(nums[i][1]);
}
return heap.size() <= 1;
}
class Solution {
public:
Solution() {}
Node * buildTree(vector<int>& preorder, vector<int>& inorder) {
this->preorder = preorder;
for (int i = 0; i < inorder.size(); i++) {
dic[inorder[i]] = i;
}
return recur(0, 0, inorder.size() - 1);
}
private:
vector<int> preorder;
unordered_map<int, int> dic;
Node * recur(int root_ind, int left, int right) {
if (left > right) return nullptr;
Node * node = new Node(preorder[root_ind]);
int i = dic[preorder[root_ind]];
node->left = recur(root_ind + 1, left, i - 1);
node->right = recur(root_ind + (i - left) + 1, i + 1, right);
return node;
}
};
bool isSymTwo(Node * left, Node * right) {
if (!left && !right) return true;
if ((!left) || (!right) || (left->val != right->val)) return false;
return isSymTwo(left->left, right->right) && isSymTwo(left->right, right->left);
}
bool isSym(Node * root) {
if (!root) return true;
else
return isSymTwo(root->left, root->right);
}
vector<int> postorderTr(Node * root) {
vector<int> res;
if (!root) return res;
stack<Node *> st;
st.push(root);
while (!st.empty()) {
auto tem = st.top();
st.pop();
res.push_back(tem->val);
if (tem->left) st.push(tem->left);
if (tem->right) st.push(tem->left);
}
return res;
}
int main() {
int n;
cin >> n;
int ans = 0;
vector<int>preOrder(n);
vector<int>inOrder(n);
int res = 0;
for (int i = 0; i < n; i++) {
int tm;
cin >> tm;
preOrder[i] = tm;
}
for (int j = 0; j < n; j++) {
int m;
cin >> m;
inOrder[j] = m;
}
int ind = 0;
for (int i = 0; i < n; i++) {
if (res < preOrder[i]) {
res = preOrder[i];
ind = i;
}
}
Solution* solu = new Solution();
Node * root = solu->buildTree(preOrder, inOrder);
bool flag = isSym(root);
if (!flag) {
ans = res;
}
else {
vector<int>nums;
nums = postorderTr(root);
ans = nums[ind];
}
cout<<flag<<endl;
cout << ans << endl;
return 0;
}