算法 之 分治 - 求解最大值和最小值

顾名思义,“分治”名字本身就已经给出了一种强有力的算法设计技术,它可以用来解决各类问题。在它最简单的形式里,一个分治算法把问题实例划分成若干子实例(多数情况是分成两个),并分别递归地解决每个子实例,然后把这些子实例的解组合起来,得到原问题实例的解。

 

为了阐明这个方法,考虑这样一个问题:在一个整数组A[1...n]中,同时寻找最大值和最小值。为了简化问题,不妨假定n是2的整数幂。一中直接的算法如下面所示,它返回一个数对(x,y),其中x是最小值,y是最大值:

x ← A[1]; y ← A[1]

for i ← 2 to n

    if A[i] < x then x ← A[i]

    if A[i] > y then y ← A[i]

end for

return (x,y)

 

显然,由以上方法执行的元素比较次数是2n-2。

 

下面我们来看一下用分治策略:将数组分割成两半,A[1...n/2]和A[(n/2)+1...n],在每一半中找到最大值和最小值,并返回这两个最小值中的最小值及这两个最大值的最大值。

 

过程  Min-Max

输入  n个整数元素的数组A[1...n],n为2的幂

输出  (x,y), A中的最大元素和最小元素

 

算法描述  minmax(low, high)

if high - low = 1 then

    if A[low] < A[high] then return (A[low], A[high])

    else return (A[high], A[low])

    end if

else

    mid ← (low + high)/2 

    (x1, y1 ) ← minmax(low, mid)

    (x2, y2 ) ← minmax(mid + 1, high)

    x ← min { x1, x2 }

    y ← min { y1, y2 }

    return (x, y)

end if

 

这个算法要注意一点,我们已经假定n是2的整数幂。不然的话,算法里面的递归调用会进入死循环...

下面是此算法的Java实现:

 

Pairs.java 这个类用来保存最大值和最小值:

public class Pairs
{
	private int minValue;
	private int maxValue;

	public Pairs(int minValue, int maxValue)
	{
		this.minValue = minValue;
		this.maxValue = maxValue;
	}
	
	public static Pairs valueOf(int minValue, int maxValue)
	{
		return new Pairs(minValue, maxValue);
	}
	
	public int getMaxValue()
	{
		return maxValue;
	}

	public int getMinValue()
	{
		return minValue;
	}
}

 

DivideAndConquer.java 包含实现 Min-max 算法的类:

public class DivideAndConquer
{
	public static Pairs minMax(int[] array, int low, int high)
	{
		if (high - low == 1)
		{
			int minValue = Math.min(array[low], array[high]);
			int maxValue = Math.max(array[low], array[high]);

			return Pairs.valueOf(minValue, maxValue);
		}

		int middle = (low + high) / 2;
		Pairs pairs1 = minMax(array, low, middle);
		Pairs pairs2 = minMax(array, middle + 1, high);

		return Pairs.valueOf(Math.min(pairs1.getMinValue(), pairs2.getMinValue()),
			Math.max(pairs1.getMaxValue(), pairs2.getMaxValue()));
	}
}

 

Program.java 包含程序的入口方法,这里面还对传入的数组进行了判断,是否为null或者数组长度为2的幂:

当然也可以不用设置low=0, high=array.length - 1,只要 (high - low + 1) 是2的幂就可以了

public class Program
{
	public static void main(String[] args)
	{
		int[] array = new int[] { 332, 566, 51, 70, 98, 19, 24, 637, 
			53456, 3321, -235, -34, 5, 45, 77, 36 };
		if (array == null || !isValidPower(array.length))
		{
			System.err.println("Invalid Array!");
			return;
		}
		
		Pairs pairs = DivideAndConquer.minMax(array, 0, array.length - 1);
		
		String message = String.format("Min Value: %d\nMax Value: %d",
			pairs.getMinValue(), pairs.getMaxValue());
		System.out.println(message);
	}

	// 这个方法判断传入的参数是否为2的幂(不包括0和负数)
	private static boolean isValidPower(int power)
	{
		if (power < 2)
			return false;
		
		while (power >= 2)
		{
			if (power % 2 != 0)
				return false;
			
			power /= 2;
		}

		return true;
	}
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值