混元算法 -------------分治

接下来我谈谈我对分治算法的理解。
分治:就是把一个任务分为和原任务形式相同但规模更小的几个任务(通常是两个任务)分别完成,或只需要完成其中一部分。然后再处理这几部分的结果来实现整个任务的完成。其实它大部分最好和递归一起使用。
概念很好理解,但是关键还是老话,思想很重要。比如我们常见的称硬币问题,16枚硬币有一枚假的,假的比真的轻,有一个天平问最少称几次可以找到假币。当然我们可以用穷举的思想,两个两个的称,但是也可以用分治的思想,平均一分8个8个称,哪边轻那假币肯定就在那8个里,就变成了在8个硬币找假币,然后再一分……,这看起来有些像二分查找,本来很多算法都有相似之处,这是一个简单的例子,接下来看一个分治的经典问题“归并排序”。
归并排序是我们学过的排序算法里面第一个突破时间复杂度为O(n^2)的排序算法,像其他的冒泡排序,选择排序,直接排序等时间复杂度都是n的平方,而归并排序的时间复杂度为N*logN。
归并排序就是我们想把一个无序序列分为两部分,分别吧这两部分排好序然后归并到一起成为一个有序序列,这听起来好像没有改善多少,但是我们分为的两部分可以递归继续分直到只有一个元素,这样就可以大大降低时间复杂度。直接上代码:

#include<iostream>
using namespace std;

int a[100];
int b[100];

void Merge(int a[], int s, int m, int e, int tmp[])
{
	int pb = 0;
	int p1 = s;
	int p2 = m+1;
	while ((p1 <= m) && (p2 <= e))
	{
		if (a[p1] > a[p2])
			tmp[pb++] = a[p2++];
		else
			tmp[pb++] = a[p1++];
	}
	while (p1 <= m)
	{
		tmp[pb++] = a[p1++];
	}
	while (p2 <= e)
	{
		tmp[pb++] = a[p2++];
	}
	for (int i = 0; i < e - s + 1; i++)
	{
		a[s+i] = tmp[i];
	}
}

void MergeSort(int a[], int s, int e, int tmp[])
{
	if(s < e)
	{
		int m = s + (e - s) / 2;
		MergeSort(a, s, m, tmp);
		MergeSort(a, m + 1, e, tmp);
		Merge(a, s, m, e, tmp);
	}
}

int main()
{
	int N;
	cin >> N;
	for(int i = 0;i<N;i++)
		cin >> a[i];
	MergeSort(a,0,N-1,b);
	for (int i = 0; i < N; i++)
	{
		cout << a[i]<<" ";
	}
	return 0;
}

至于为什么时间复杂度为NlogN,看下图:
在这里插入图片描述
还有就是快速排序也用了分治的思想。
快速排序就是在一个待排序的数组中,使右半部分的所有数都大于左边的所有数(也不一定一定是对半分的),我们一般都是以首元素为分界线,比首元素大的都在右边,比首元素小的都在左边,然后再用递归继续对两边的进行相同操作,最后只剩一个元素时就已排好序。具体的怎么进行分类呢?我们可以这样:
在数组中选择一个基准点(一般为首元素)
分别从数组的两端扫描数组,设两个指示标志
从后半部分开始,如果发现有元素比该基准点的值小,就交换位置
然后从前半部分开始扫描,发现有元素大于基准点的值,继续交换位置
如此往复循环,然后把基准点的值放到和end位置,排序完成
以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了。
同理这个排序的时间复杂度和归并排序一样,都是N
logN。所以归并的思想还是很重要的。
上代码:

#include<iostream>
using namespace std;

int a[100];

void Swap(int& a, int& b)
{
	int tmp;
	tmp = a;
	a = b;
	b = tmp;
}

void QuickSort(int a[], int s, int e)
{
	if (s >= e)  return;
	int k = a[s];
	int i = s, j = e;
	while (i != j)
	{
		while ((i < j) && (k <= a[j]))
			j--;
		Swap(a[i], a[j]);
		while ((i < j) && (k >= a[i]))
			i++;
		Swap(a[i], a[j]);
	}
	QuickSort(a, s, i - 1);
	QuickSort(a,i + 1,e);
}

int main()
{
	int N;
	cin >> N;
	for (int i = 0; i < N; i++)
		cin >> a[i];
	QuickSort(a, 0, N - 1);
	for (int i = 0; i < N; i++)
		cout << a[i]<<" ";
	return 0;
}

像C++中STL中自带的sort()排序函数内部也是用的快速排序,而且这个排序是很多学校和公司都比较爱考的。
这就是我对分治的一些小小的理解,有大佬有更好的见解也可以一起讨论啊!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
This error message typically occurs when the OpenSSL library is not installed or is not properly linked to the Ruby installation. To resolve this error, you can try the following solutions: 1. Install OpenSSL library: On Linux or macOS, use the system package manager to install OpenSSL. For example, on Ubuntu or Debian, run: ``` sudo apt-get install libssl-dev ``` On macOS, you can install OpenSSL using Homebrew: ``` brew install openssl ``` On Windows, download and install the OpenSSL library from the official website. 2. Reinstall Ruby with OpenSSL support: If you installed Ruby from source, make sure to enable OpenSSL support by passing the `--with-openssl-dir` flag to the `configure` script. For example: ``` ./configure --with-openssl-dir=/usr/local/opt/openssl ``` If you installed Ruby using a package manager like Homebrew, try reinstalling it with OpenSSL support: ``` brew reinstall ruby --with-openssl ``` 3. Set the OpenSSL library path: If you have installed OpenSSL in a non-standard location, you may need to set the `LD_LIBRARY_PATH` environment variable to the path where OpenSSL libraries are located. For example: ``` export LD_LIBRARY_PATH=/usr/local/opt/openssl/lib ``` 4. Use a Ruby version manager: Consider using a Ruby version manager like RVM or rbenv, which can manage multiple Ruby installations and their dependencies, including OpenSSL. This can help avoid conflicts between different Ruby versions and system libraries. After trying one or more of these solutions, try running your Ruby program again. If the error persists, you may need to seek further assistance or consult the documentation for your specific environment.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值