快排、归并、并查集、BFS、DFS、二分

void quick_sort(vector<int>& nums, int l, int r) {
	if (l >= r) return;
	int mid = nums[(l + r) >> 1];
	int i = l - 1, j = r + 1;
	while (i < j) {
		do ++i; while (nums[i] < mid); 
		// 这里一定不可以 = 
		// 因为存在一种情况,我们比较的 target 刚刚好是一个区间的最大值或者最小值
		// 不加 = 号的话,i 和 j 都总是会入侵到对方的区间
		// 加了之后,会存在 
		// 如果target刚好是最大值,i入侵不到
		// 如果target刚好是最大值,j入侵不到
		// 一般情况下:扫描完一次之后
		// i = j + 1 分别入侵了 大于target 和小于target 的区域
		// 或者是 i == j 都入侵了 target
		do --j; while (nums[j] > mid);
		if (i < j) {
			swap(nums[i], nums[j]);
		}
	}
	cout << i << " " << nums[i] << " "<< j << " " << nums[j] << " " << mid << endl;
	quick_sort(nums, l,j);
	quick_sort(nums, j + 1, r);
	// 这里:
	// 可以是 j 和 j + 1
	// 也可以是 i - 1 和 i
	// 因为在最后,i 是向左进入了他不应该进入的地区:nums[i] >= mid
	// j 是向左进入了 他不该进入的地区, 所以是: nums[j] <= mid
	// 所以 j 需要被左侧包含进去,i需要被右侧包含进去
	/*所有的可能:
		按照顺序排好了:
		find 6
		0 1 2 3 4
		5 8 9
		i   j
		j i

		没按照顺序排好了:
		find 8
		0 1 2 3 4
		5 9 8
		i   j
		i j
		5 8 9
		i j
		j i*/
}

void quick_sort1(vector<int>& nums, int l, int r) {
	if (l >= r) return;
	int temp = nums[l];
	int i = l, j = r;
	while (i < j) {
		while (i < j && nums[j] > temp) --j;
		if (i < j) nums[i++] = nums[j];
		while (i < j && nums[i] < temp) ++i;
		if (i < j) nums[j--] = nums[i];
	}
	nums[j] = temp; 
	cout << i << " " << nums[i] << " " << j << " " << nums[j] << " " << temp << endl;
	quick_sort1(nums, l, j);
	quick_sort1(nums, j + 1, r);
	// 这个和第一个就不同
	// 这个快排的终止条件一定是 i == j
	// 而且是把 目标值放在了 i == j的位置上
	// 这个也能像第一种快排方法一样理解
	// 当快排序完成时:中间会有一条分界线 左边<= target 右边>= target
	// 但是第二种快排,当i和j有一个入侵到对方时,另一个就不会入侵了,最多走到i == j的位置
	// 而且这时把 target 放到了这个位置
}

void merge_sort(vector<int>& nums, int l, int r, vector<int>& temp) {
	if (l >= r) return;
	
	// 分
	int mid = (l + r) >> 1;
	merge_sort(nums, l, mid, temp);
	merge_sort(nums, mid + 1, r, temp);

	// 治
	int k = 0, i = l, j = mid + 1;
	while (i <= mid && j <= r) {
		if (nums[i] <= nums[j]) temp[k++] = nums[i++];
		else temp[k++] = nums[j++];
	}

	while (i <= mid)temp[k++] = nums[i++];
	while (j <= r)temp[k++] = nums[j++];
	
	// 回
	for (int i = 0, j = l; j <= r;) nums[j++] = temp[i++];
}
int find_dj(int x, vector<int>& cla) {
	// 路径压缩
	if (x != cla[x]) cla[x] = find_dj(cla[x], cla);
	return cla[x];
}

int main(){
	vector<int> set = { 5, 3, 6, 1, 2, 6, 6};
	vector<pair<int, int>> operat = { {0, 1}, { 2, 3 }, { 4, 5 }, {0, 3}, {4, 6} };

	// 初始化集合
	vector<int> cla(set.size(), 0);
	for (int i = 0; i < cla.size(); ++i) cla[i] = i;

	// 合并集合
	for (auto single : operat) {
		cla[find_dj(single.first, cla)] = find_dj(single.second, cla);
	}

	// 最后一步可有可无
	for (int i = 0; i < cla.size(); ++i) cla[i] = find_dj(cla[i], cla);
	return 0;
}
void BFS(ListNode* root) {
	stack<ListNode*> stk;
	stk.push(root);
	while (!stk.empty()) {
		ListNode* tmp = stk.top();
		stk.pop();
		if (tmp != nullptr) {
			stk.push(tmp->left);
			stk.push(tmp->right);
		}
	}
}
// 模板二和模板一的区别在于
// 模板二可以记录当前遍历的深度
void BFS1(ListNode* root) {
	if (root == nullptr) return;
	deque<ListNode*> stk;
	stk.push_back(root);
	while (!stk.empty()) {
		int num = stk.size();
		for (int i = 0; i < num; ++i) {
			ListNode* tmp = stk.front();
			stk.pop_back();
			if (tmp != nullptr) {
				stk.push_back(tmp->left);
				stk.push_back(tmp->right);
			}
		}
	}
}
struct ListNode
{
	int val;
	ListNode* left;
	ListNode* right;
	ListNode() : val(0),left(nullptr), right(nullptr) {};
};

void PreorderTraversal(ListNode* root) {
	if (root != nullptr) {
		// 根处理
		PreorderTraversal(root->left);
		PreorderTraversal(root->right);
	}
}
int binary_search(vector<int>&nums, int target, int l, int r) {
	if (l >= r) return false;
	int mid = (l + r) >> 1;
	while (l <= r)
	{
		mid = (l + r) >> 1;
		if (target < nums[mid]) r = mid - 1;
		else if (target > nums[mid]) l = mid + 1;
		else return mid;
	}
	return -1;
}

int lower_bound(vector<int>&nums, int target, int l, int r) {
	if (l >= r) return false;
	int mid = (l + r) >> 1;
	while (l <= r)
	{
		mid = (l + r) >> 1;
		if (target < nums[mid]) r = mid - 1;
		else if (target > nums[mid]) l = mid + 1;
		else {
			if (mid > l && nums[mid - 1] == target) r = mid - 1;
			else return mid;
		};
	}
	return -1;
}

int bigger_bound(vector<int>&nums, int target, int l, int r) {
	if (l >= r) return false;
	int mid = (l + r) >> 1;
	while (l <= r)
	{
		mid = (l + r) >> 1;
		if (target < nums[mid]) r = mid - 1;
		else if (target > nums[mid]) l = mid + 1;
		else {
			if (mid < r && nums[mid + 1] == target) l = mid + 1;
			else return mid;
		};
	}
	return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值