手写快排,堆排,归并排序

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;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是Java实现的堆排序代码: ```java public class HeapSort { public void sort(int[] arr) { int n = arr.length; // 从最后一个非叶子节点开始构建最大堆 for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i); // 依次将堆顶元素移到数组末尾,并重新构建最大堆 for (int i = n - 1; i >= 0; i--) { // 将堆顶元素与当前未排序部分的最后一个元素交换 int temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; // 重新构建最大堆 heapify(arr, i, 0); } } // 以根节点为i的子树为最大堆 void heapify(int[] arr, int n, int i) { int largest = i; int l = 2 * i + 1; // 左子节点 int r = 2 * i + 2; // 右子节点 // 如果左子节点比根节点大,则更新最大值 if (l < n && arr[l] > arr[largest]) largest = l; // 如果右子节点比最大值大,则更新最大值 if (r < n && arr[r] > arr[largest]) largest = r; // 如果最大值不是根节点,则交换根节点和最大值,并继续向下调整 if (largest != i) { int swap = arr[i]; arr[i] = arr[largest]; arr[largest] = swap; heapify(arr, n, largest); } } } ``` 在堆排序中,我们首先构建一个最大堆,然后依次将堆顶元素移到数组末尾,并重新构建最大堆。`heapify()`方法用于将以根节点为i的子树调整为最大堆,其中n表示当前堆的大小。在`heapify()`方法中,我们首先找到根节点、左子节点和右子节点中的最大值,如果最大值不是根节点,则交换根节点和最大值,并继续向下调整。在堆排序中,时间复杂度为O(nlogn),空间复杂度为O(1)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值