`

编程之美-子数组的最大和(二维)

 
阅读更多
package beautyOfCoding;

import java.util.Arrays;
import java.util.Random;

public class MaxSubArraySum2 {

	/**
	 * 编程之美 子数组之和的最大值(二维)
	 */
	private static final int ROW = 5;
	private static final int COL = 6;
	private static final int MAX = 127;
	private boolean invalidInput = false;
	private static int[] source;	//[-127,127]共127*2+1个数
	static {
		int n = MAX * 2 + 1;
		source = new int[n];
		for (int i = 0; i < n; i++) {
			source[i] = i - MAX;
		}
	}

	public static void main(String[] args) {
		//生成指定行数和列数的数组。数组元素是[-127,127]范围内的随机数
		int[][] B = new int[ROW][COL];
		int n = MAX * 2 + 1;
		Random random = new Random();
		for (int i = 0; i < ROW; i++) {
			for (int j = 0; j < COL; j++) {
				int pos = random.nextInt(n);
				int num = source[pos];
				B[i][j] =  num;
			}
			System.out.println(Arrays.toString(B[i]));
		}
		
		/*int[][] B = {
				{0, -2, -7, 0},
				{9, 2, -6, 2},
				{-4, 1, -4, 1},
				{-1, 8, 0, -2}
		};*/
		
		//方法A-全枚举
		MaxSubArraySum2 test = new MaxSubArraySum2();
		int max = test.maxSubArraySumA(B);
		if (test.invalidInput) {
			System.out.println("invalid input");
		} else {
			System.out.println(max);
		}
		//方法B-部分和
		MaxSubArraySum2 test2 = new MaxSubArraySum2();
		int max2 = test2.maxSubArraySumB(B);
		if (test2.invalidInput) {
			System.out.println("invalid input");
		} else {
			System.out.println(max2);
		}
		//方法C-转化为一维
		MaxSubArraySum2 test3 = new MaxSubArraySum2();
		int max3 = test3.maxSubArraySumB(B);
		if (test3.invalidInput) {
			System.out.println("invalid input");
		} else {
			System.out.println(max3);
		}
	}

	/**
	 * 转化为一维。
	 */
	public int maxSubArraySumC(int[][] B) {
		int max = Integer.MIN_VALUE;
		if (B == null) {
			invalidInput = true;
		} else {
			int row = B.length;
			for (int a = 0; a < row; a++) {
				for (int c = a; c < row; c++) {
					int[] BC = this.getBC(B, a, c);
					int oneDimension = this.maxInOneDimensionalArray(BC);
					if (max < oneDimension) {
						max = oneDimension;
					}
				}
			}
		}
		return max;
	}
	
	/**
	 * maxSubArraySumC的辅助方法。得到第a行到第c行所代表的一维数组
	 */
	public int[] getBC(int[][] B,int a,int c){
		int col=B[0].length;
		int[] BC = new int[col];
		for(int i=0;i<col;i++){
			for(int j=a;j<=c;j++){
				BC[i] += B[j][i];
			}
		}
		return BC;
	}
	
	//子数组之和的最大值-一维
	public int maxInOneDimensionalArray(int[] a){
		//略去参数检查  
        int Start=0;  
        int All=0;  
        for(int i=0,len=a.length;i<len;i++){  
            All=this.maxNum(a[i],Start+a[i],All);  
            Start=this.maxNum(a[i],a[i]+Start);     //if start<0, start=a[i]  
        } 
        return All;
	}
	
	/**
	 * 用部分和的形式。其中辅助数组PS额外多一行多一列(默认初始化为0),方便计算“部分和”的“部分和”,需仔细体会
	 * PS[i][j] 表示元素(1,1)(对应原始数组B的B[0][0])和当前元素(i,j)为顶点对的子矩阵的部分和,部分和的计算如下:
	 * PS[i][j] = A[i][j]+PS[i-1][j]+PS[i][j-1]-PS[i-1][j-1]
	 */
	public int maxSubArraySumB(int[][] B) {
		int max = Integer.MIN_VALUE;
		if (B == null) {
			invalidInput = true;
		} else {
			int row = B.length;
			int col = B[0].length;
			int[][] PS = new int[row+1][col+1];
			for (int i = 0; i < row; i++) {
				for (int j = 0; j < col; j++) {
					PS[i+1][j+1] = PS[i][j+1] + PS[i+1][j ] - PS[i][j] + B[i][j];
				}
			}
			max = this.maxPSij(PS);
		}
		return max;
	}
	
	/**
	 * maxSubArraySumB的辅助方法
	 * 求“部分和”的“部分和”:求得(imin, imax, jmin, jmax)代表的矩形区域的和,即题目所求
	 */
	public int maxPSij(int[][] PS) {
		int max = Integer.MIN_VALUE;
		int row = PS.length;
		int col = PS[0].length;
		for (int i = 0; i < row; i++) {
			for (int j = 0; j < col; j++) {
				for (int m = i; m < row; m++) {
					for (int n = j; n < col; n++) {
						max = this.maxNum(max, PS[i][j], PS[m][n], 
								(PS[m][n] - PS[m][j] - PS[i][n] + PS[i][j]));
					}
				}
			}
		}
		return max;

	}

	/**
	 * 穷举法,求部分和也是用枚举,有六个for循环,复杂度相当高,不过可用于检验其他方法是否正确
	 */
	public int maxSubArraySumA(int[][] B) {
		int max = Integer.MIN_VALUE;
		if (B == null) {
			invalidInput = true;
		} else {
			int row = B.length;
			int col = B[0].length;
			for (int imin = 0; imin < row; imin++) {
				for (int imax = imin; imax < row; imax++) {
					for (int jmin = 0; jmin < col; jmin++) {
						for (int jmax = jmin; jmax < col; jmax++) {
							int tmpSum = sum(B, imin, imax, jmin, jmax);
							if (tmpSum > max) {
								max = tmpSum;
							}
						}
					}
				}
			}
		}
		return max;
	}
	
	/**
	 * maxSubArraySumA的辅助方法
	 * 枚举求得(imin, imax, jmin, jmax)代表的矩形区域的和
	 */
	public int sum(int[][] B, int imin, int imax, int jmin, int jmax) {
		int result = 0;
		for (int i = imin; i <= imax; i++) {
			for (int j = jmin; j <= jmax; j++) {
				result += B[i][j];
			}
		}
		return result;
	}

	/**
	 * 返回最大的数
	 */
	public int maxNum(int x, int... yy) {
		for (int y : yy) {
			if (x < y) {
				x = y;
			}
		}
		return x;
	}
	
}
分享到:
评论

相关推荐

    C语言二维数组编程练习

    本编程练习旨在加深对C语言中二维数组、指针和函数的理解,通过实际操作提升编程技能。下面我们将深入探讨这些知识点。 首先,二维数组在C语言中被声明为`类型名 数组名[行数][列数]`,例如`int arr[3][4]`创建了一...

    数据结构与算法 一维数组-二维数组-三维数组

    在本主题中,我们将深入探讨一维数组、二维数组和三维数组的概念,以及如何使用模板来实现这些数据结构。这些基础知识在编程中至关重要,尤其是在处理大量数据时。 一维数组是最基础的数据结构之一,它是一个有序的...

    C++ 数组 多维数组 -- 二维数组

    "C++ 数组 多维数组 -- 二维数组" 在计算机编程中,数组是一种重要的数据结构,它允许我们在一个变量名下存储多个值。今天,我们将学习 C++ 中的数组,包括一维数组和多维数组。 首先,让我们来了解数组的概念和...

    C语言第07章-一维数组和二维数组1完整.pptx

    C语言数组 ...数组可以分为一维数组和二维数组两种形式,一维数组是一组具有相同数据类型的数据的有序集合,二维数组是一组具有相同数据类型的数据的有序集合。数组元素的引用和初始化是数组的基本操作。

    嵌入式C语言培训-编程进阶-1数组

    3. **多维数组**:C语言支持多维数组,这在处理二维或三维数据时非常有用。例如,`int matrix[3][4]`定义了一个3行4列的二维数组,可以用来表示小型矩阵。多维数组的元素访问类似于一维数组,如`matrix[1][2]`表示第...

    动态二维数组 c#编程

    在C#编程中,动态二维数组是一种非常重要...以上就是关于C#编程中动态二维数组的基本知识,希望对你理解和使用动态二维数组有所帮助。在实际编程中,应根据具体需求选择合适的数据结构,以实现最优的性能和代码可读性。

    c语言基础-c语言编程基础之二维数组操作示例-三维形体的表面积.zip

    总结,理解并熟练运用C语言中的二维数组对于编程来说至关重要,它能帮助我们高效地处理和存储二维或更高维度的数据。通过实际的编程练习,如三维形体表面积的计算,可以更好地理解和掌握二维数组的操作技巧。

    读取二维数组所有数据_labview读取数组_

    在LabVIEW编程环境中,二维数组是一种常见的数据结构,用于存储多行多列的数据。本教程将深入探讨如何在LabVIEW中有效地读取二维数组的所有数据,这对于数据分析、处理和可视化至关重要。 首先,让我们理解二维数组...

    二维数组求最大数

    本实验的目标是在一个二维数组中找出最大数及其所在的行和列位置。这是一个经典的编程问题,旨在帮助学习者掌握二维数组的基本操作以及如何在数组中进行查找。 #### 二、基本概念 1. **二维数组**: 一种数据结构,...

    易语言学习进阶二维数组赋值

    二维数组在编程中是一种非常重要的数据结构,尤其在易语言中,它被广泛应用于各种算法和数据处理场景。本文将详细讲解易语言中二维数组的赋值方法,并通过实例源码帮助你深入理解这一概念。 二维数组,顾名思义,是...

    c语言基础-c语言编程基础之二维数组操作-两地调度.zip

    总的来说,二维数组是C语言中处理复杂数据结构的关键工具,尤其在解决涉及表格数据和矩阵运算的问题时,如“两地调度”。掌握二维数组的声明、初始化、访问、遍历以及动态分配,将有助于你编写高效且灵活的C语言程序...

    Q1064245.zip c#winform如何实现一维数组转二维数组并保存在某处

    在C#编程中,一维数组到二维数组的转换是一个常见的操作,特别是在处理表格数据或者在Windows Forms(WinForm)应用程序中创建控件布局时。本篇将详细讲解如何进行这种转换以及如何保存二维数组的数据。 首先,让...

    c语言基础-c语言编程基础之二维数组操作示例-相对名次.zip

    在C语言中,二维数组是数据结构的一种,它在内存中...总的来说,二维数组是C语言中一种强大的数据结构,理解和掌握其操作是提升C语言编程能力的重要一步。通过练习和实践,你可以更好地运用二维数组解决各种实际问题。

    matlab 三维数组-MATLAB数组基础实例教程下载

    - `magic(n)`:生成一个n阶的幻方数组,即n×n矩阵,每行、每列和两条对角线的数字之和相等。 2. 多维数组的创建与扩展: - 基于已有的二维数组扩展,例如: ```matlab a = [7 9 5; 6 1 9; 4 3 2]; a(:, :, 2)...

    Java编程一维数组转换成二维数组实例代码

    下面,我们将详细介绍Java编程一维数组转换成二维数组的实例代码和原理。 一维数组转换成二维数组的必要性 在实际编程中,我们经常需要将一维数组转换成二维数组,以便于进行矩阵运算或其他数据处理。例如,在机器...

    TIA博途-使用AT指令实现IO点位映射到二维数组中-全局FB库文件-V17版本-GF-二维数组IO点位映射.zip

    4. **二维数组**: 在编程中,二维数组是一个数组的数组,可以看作是一张表格,每行和每列对应特定的数据。在PLC编程中,二维数组常用于处理矩阵或表格形式的数据,如传感器阵列的读取或控制多路电机的状态。 5. **...

    CStringArray二维数组的定义和操作

    总结,`CStringArray`二维数组的定义和操作主要包括定义新类型、动态创建子数组并插入数据以及遍历和读取数据。在实际使用中,还需要考虑内存管理,确保在不再使用子数组时释放它们占用的内存。此外,对于更复杂的...

    两个二维数组相加,用成员函数重载运算符“+”和“-”

    ### 两个二维数组相加与相减:使用成员函数重载运算符“+”和“-” 在C++中,运算符重载是一种强大的特性,它允许程序员改变内置运算符的行为,使其适用于自定义类型(如类或结构)。本文将详细介绍如何通过成员...

    三维数组操作_labview三维数组_labview_三维数组_

    在LabVIEW编程环境中,三维数组是一种非常重要的数据结构,它能够有效地存储和处理大量多维数据。本篇文章将深入探讨如何在LabVIEW中创建、操作和应用三维数组,以实现如标题和描述所述的功能。 首先,让我们理解...

Global site tag (gtag.js) - Google Analytics