分治

分治,字面上的解释是“分而治之”,

就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……

直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。

在计算机科学中,分治法就是运用分治思想的一种很重要的算法。

分治法是很多高效算法的基础,如排序算法(快速排序,归并排序)等等。


例1:二分查找

已知有序的序列,比如:2,3,3,5,9,9,9,12,12,13,15,22,22,22,22,25,25,23,91,95

有整数x,比如: x=23

要求找到一个刚好比x稍微大一点的元素位置

当数组较大的时候,需要二分查找加快速度。

解:

public class Main {
	// 含有begin, 不含end
	static int f(int[] a, int begin, int end, int x) {
		if (end - begin == 1) {// =1时代表只剩一个元素
			if (a[begin] > x)
				return begin;
			return end;
		}

		int k = (begin + end) / 2;// k在begin和end的中心点
		if (x >= a[k])// x大于a[k]时,就证明要找的那个刚大于x的数在中心点右边
			return f(a, k, end, x);// 原中心点成为begin
		return f(a, begin, k, x);// 否则就在中心点左边,原中心点成为end
	}

	// 求x应该插入的位置
	// return 刚好比x稍微大点的那个数的位置
	static int f(int[] a, int x) {
		// 当到达数组最后一个数时,发现还没找到,就不存在比x大的数
		if (x >= a[a.length - 1])
			return -1;
		return f(a, 0, a.length, x);// begin和end一开始是数组的开头和结尾
	}

	public static void main(String[] args) {
		int[] a = { 1, 5, 11, 24, 25, 32, 32, 33, 49, 66, 68, 69, 70, 75, 88, 102, 114, 119, 120, 135, 146, 221, 294,
				300, 302, 305, 333 };
		System.out.println(f(a, 32));// 查找稍大于32的数的下标,是7
	}
}


例2:最大序列和

数组中整数有正有负

求一连续子段,使得和最大化

例如:
2,4,-7,5,2,-1,2,-4,3
最大连续段:
5,2,-1,2

其最大和为8

解:

public class Main {

	static int fun(int[] a, int begin, int end) {
		if (end - begin == 1) {// 只有一个元素时
			if (a[begin] > 0)
				return a[begin];
			return 0;// 如果那个元素为负数,则返回0
		}
		int k = (begin + end) / 2;// 中点
		int t1 = fun(a, begin, k);// 中点到左端点的最大连续部分和
		int t2 = fun(a, k, end);// 中点到右端点的最大连续部分和

		// 经过中点的最大连续部分和
		int sum = 0;
		// 左部分
		int t3_a = 0;
		for (int i = k - 1; i >= begin; i--) {// 不包括k
			sum += a[i];
			if (sum > t3_a)
				t3_a = sum;
		}
		sum = 0;// 重置
		// 右部分
		int t3_b = 0;
		for (int i = k; i < end; i++) {
			sum += a[i];
			if (sum > t3_b)
				t3_b = sum;
		}
		int t3 = t3_a + t3_b;

		// 找出三者中最大那个,就是整个序列的最大连续部分和
		int max = 0;
		if (t1 > max)
			max = t1;
		if (t2 > max)
			max = t2;
		if (t3 > max)
			max = t3;

		return max;
	}

	static int work(int[] a) {
		return fun(a, 0, a.length);
	}

	public static void main(String[] args) {
		// 随便创建一个序列作为尝试,下面这个会输出:8
		System.out.println(work(new int[] { 2, 4, -7, 5, 2, -1, 2, -4, 3 }));
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值