分治策略

分治策略

递归与分治策略:

  • 是将规模比较大的问题可分割成规模较小的相同问题。问题不变,规模变小。 这自然导致递归过程的产生。
  • 分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
  • 递归:若一个函数直接地或间接(最好不用间接)地调用自己,则称这个函数是递归的函数。(简单地描述为 “自己调用自己”) .

分治法所能解决的问题-般具有以下四个特征:

  1. 该问题的规模缩小到 定的程度就可以容易地解决。
  2. 该问题可以分解为若干个规模较小的相同问题。
  3. 使用小规模的解 可以合并成,该问题原规模的解。
  4. 该问题所分解出的各个子规模是相互独立的。

分治法步骤:
在分治策略中递归地求解一 个问题, 在每层递归中应用如下三个步骤: .

  • 分解:将问题划分成一些子问题,子问题的形式与原问题一样,只是规模更小。
  • 解决:递归地求解子问题。如果子问题的规模足够小,则停止递归,直接求解。
  • 合并:将小规模的解组合成原规模问题的解。

1.求阶乘

普通求法

int fun(int n)
{
	int sum = 1;
	for (int i = 1; i <= n; ++i)
	{
		sum = sum * i;
	}
	return sum;
}// O(n) , S(1)

递归求法

int fac(int n)
{
	if (n <= 1)
		return 1;
	else
		return fac(n - 1) * n;
}
// O(n)   S(n)	  // o(n) 
// 1m 10m;

2.斐波那契数列

普通求法

int fun(int n)
{
	int a = 1, b = 1, c = 1;
	for (int i = 3; i <= n; ++i)
	{
		c = a + b;
		b = a;
		a = c;
	}
	return c;
}  // O(n). S(1)

递归求法

int fib(int n)
{
	if (n <= 2)
		return 1;
	else
		return fib(n - 1) + fib(n - 2);
}// O(2^n) // S(n)

改良方法

int fib(int n, int a, int b)
{
	if (n <= 2) return a;
	else
		return fib(n - 1, a + b, a);
}
int fib(int n)
{
	int a = 1, b = 1;
	return fib(n, a, b);
}
//O(n),S(n)

3.二分查找

普通求法

int BinaryFind(const vector<int>& ar, int val)
{
	int left = 0, right = ar.size() - 1;
	int pos = -1;
	while (left <= right)
	{
		int mid = (right - left) / 2 + left;
		//如果写成 int mid = (right + left)/2 ,则可能越界
		if (val < ar[mid])
		{
			right = mid - 1;
		}
		else if (val > ar[mid])
		{
			left = mid + 1;
		}
		else
		{
			//while (mid > left && ar[mid - 1] == val) --mid;  //left 找到最左边的相同值
			//while (mid < right && ar[mid + 1] == val) ++mid; // right 找到最右边的相同值
			if (mid > left && ar[mid - 1] == val)
			{
				right = mid - 1;
			}
			else
			{
				pos = mid;
				break;
			}
		}
	}
	return pos;
}

int main()
{
	std::vector<int> ar = { 12,23,34,45,56,67,78,89,90,100 };
	BinaryFind(ar,23);
    return 0;
}

在这里插入图片描述
递归求法

int BinaryFind(const vector<int>&arr,int low,int high,int val)
{
    if (low > high) return -1;

    int mid = (high - low) / 2 + low;

    if (val == arr[mid])
        return mid;
    else if (val < mid)
    {
        high = mid - 1;
        return BinaryFind(arr, low, high, val);
    }
    else
    {
        low = mid + 1;
        return BinaryFind(arr, low, high, val);
    }
}

4.快排

递归方法

int Parition(int* ar, int left, int right)
{
	assert(ar != nullptr);
	int tmp = ar[left];
	while (left < right)
	{
		while (left < right && ar[right] > tmp) --right;
		ar[left] = ar[right];
		while (left < right && ar[left] <= tmp) ++left;
		ar[right] = ar[left];
	}
	ar[left] = tmp;
	return left;
}

void QuickPass(int* ar, int left, int right)
{
	if (left < right)	// 
	{
		int pos = Parition(ar, left, right);
		QuickPass(ar, left, pos - 1);
		QuickPass(ar, pos + 1, right);
	}
}


int main()
{
	int ar[] = { 56,12,89,90,23,34,100,56,45,78,67 };
	int n = sizeof(ar) / sizeof(ar[0]);
	for (auto& x : ar) { cout << x << " "; }
	cout << endl;
	QuickSort(ar, n);
	for (auto& x : ar) { cout << x << " "; }

	return 0;
}

非递归方法

void NiceQuickPass(int* ar, int left, int right)
{
	std::queue<int> qu;
	qu.push(left); qu.push(right);
	while (!qu.empty())
	{
		left = qu.front(); qu.pop();
		right = qu.front(); qu.pop();
		int pos = Parition(ar, left, right);
		if (left < pos - 1)
		{
			qu.push(left);
			qu.push(pos - 1);
		}
		if (pos + 1 < right)
		{
			qu.push(pos + 1);
			qu.push(right);
		}
	}
}

void QuickSort(int* ar, int n)
{
	NiceQuickPass(ar, 0, n - 1);
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值