求最小子数组之二维篇

一、设计思路

求出该二维数组的所有子数组,先确定一个位置为起点,然后向右下方依次以此起点为始的所有子数组,

图1—顺序求子数组

具体如上图1,顺序求出子数组,然后和max值相比较,若比max值大,则将该子数组和赋给max,并保存其位置,对该子数组的位置,只需要保存其首尾位置即可,

图2—保存子数组位置

如上图2所示,得到了最大子数组和与其位置,输出即可。

二、代码

 1 package zishuzu;
 2
 3 import java.util.*;
 4
 5 public class zuixiaozishuzu {
 6
 7     public static void main(String[] args) {
 8         // TODO Auto-generated method stub
 9
10         int m,n,M,N,max,sum;
11         int i,i1,i2,j,j1,j2;
12         int shouL,shouR,weiL,weiR;
13         Scanner sc = new Scanner(System.in);
14         System.out.println("输入二维数组的行数和列数:");
15         m =    sc.nextInt();
16         n = sc.nextInt();
17         System.out.println("输入该二位数组的取值范围(保证第一个数小于第二个数):");
18         M = sc.nextInt();
19         N = sc.nextInt();
20
21         int[][] Shuzu = new int[m][n];
22         for(i = 0;i < m;i++)
23             for(j = 0;j < n;j++)
24             {
25                 Shuzu[i][j] = N + (int)(Math.random()*(M - N));
26             }
27         System.out.println("该随机二维数组为:");
28         for(i = 0;i < m;i++)
29             for(j = 0;j < n;j++)
30             {
31                 System.out.print(Shuzu[i][j]+"\t");
32                 if(j == n - 1)
33                 {
34                     System.out.print("\n");
35                 }
36             }
37
38         sum =0;
39         max = Shuzu[0][0];
40         shouL = 0;
41         shouR = 0;
42         weiL = 0;
43         weiR = 0;
44
45         for(i = 0;i < m;i++)
46         {
47             for(j = 0;j < n;j++)
48             {
49                 for(i1 = i;i1 < m;i1++)
50                 {
51                     for(j1 = j;j1 < n;j1++)
52                     {
53                         for(i2 = i;i2 <= i1;i2++)
54                         {
55                             for(j2 = j;j2 <= j1;j2++)
56                             {
57                                 sum = sum + Shuzu[i2][j2];
58                             }
59                         }
60                         if(max <= sum)
61                         {
62                             max = sum;
63                             shouL = i;
64                             shouR = j;
65                             weiL = i1;
66                             weiR = j1;
67                         }
68                         sum = 0;
69                     }
70                 }
71             }
72         }
73
74         System.out.println("最大子数组和为:");
75         System.out.println(max);
76         System.out.println("最大子数组为:");
77         for(i = shouL;i <= weiL;i++)
78             for(j = shouR;j <= weiR;j++)
79             {
80                 System.out.print(Shuzu[i][j] + "\t");
81                 if(j == weiR)
82                 {
83                     System.out.print("\n");
84                 }
85             }
86
87         sc.close();
88     }

三、实验结果

图3—结果1

图4—结果2

图5—结果3

四、开发过程

一个二维数组,当看到求最小子数组时,立马蹦出的想法就是求出这个二维数组的每一个子数组,虽然想法普通,时间复杂度高,却也不用考虑很多的特殊情况,出错的风险低了许多。

设计之初就是一个时间复杂度为n6的一个思路,第一层即最外层是关于起始位置的循环,第二层是关于终止位置的循环,最里层则是该子数组的自加求和,每层有两个for循环。

在一开始编写时,将循环时的值设为i,ii,iii,j,jj,jjj,运行时却失败了,花了两节课怎么也找不到错误,突然想起同伴的提醒:为什么不用i,i1,i2,j1,j1,j2,这样不是更容易看点,于是便将所有值该了过来,改到最后一个jjj值时,才发现,我是将“jjj”写成了“jj”,导致了程序的无限循环。

在研究错误的两节课里,经同伴提醒,想要减少时间复杂度,就是修改每层的for循环,减少一个,将i++写在for循环内,具体代码如下:

 1 i = 0;
 2         for(j = 0;j < n;j++)
 3         {
 4             i1 = i;
 5             for(j1 =j;j1 < n;j1++)
 6             {
 7                 i2 = i;
 8                 for(j2 = j;j2 <= j1;j2++)
 9                 {
10                     sum += Shuzu[i2][j2];
11                     if((j2 == j1)&&(i2 < i1))
12                     {
13                         i2++;
14                         j2 = j;
15                     }
16                     else if(j2 == j1&&i2 == i1)
17                     {
18                         break;
19                     }
20                 }
21                 if(max < sum)
22                 {
23                     max = sum;
24                     shouL = i;
25                     shouR = j;
26                     weiL = i1;
27                     weiR = j1;
28                 }
29                 sum = 0;
30                 if(j1 == n -1 && i1 < m -1)
31                 {
32                     i1++;
33                     j1 = j;
34                 }
35                 else if(j1 == n-1 && j1 == m - 1)
36                 {
37                     break;
38                 }
39             }
40             if(j == n - 1 && j < m - 1)
41             {
42                 i++;
43                 j = 0;
44             }
45             else if(j == n - 1 && j == m - 1)
46             {
47                 break;
48             }
49         }    

能运行出来,可检验时发现有的运算结果是错误的,所以就先用了第一种方法。
  这个程序还可以稍作改进,就是当存在最大子数组和相同的子数组时,将所有数组都输出,可以用数组来保存。

五、结对开发成员

刘双渤,刘洪阳

时间: 2024-08-26 03:49:04

求最小子数组之二维篇的相关文章

16.10.20 4th 1蛤蟆爬井 2一维数组 3二维数组

摘要 1蛤蟆爬井 2一维数组 3二维数组 例子 井深10米, 蛤蟆白天爬5m,晚上落4米,求几天爬出来. //思路,用循环语句来做,for因为是未知次数所以排除,while 先判断后运行排除, dowhile,先爬在判断所以可以 int gaodu = 0; int tianshu = 0; boolean tianse = true; do{ if(tainse){ //白天爬5米 gaodu+=5; //爬完后改黑天 tianse = false; //天数+1 tianshu +=1; }

c++ 依据输入动态声明数组(一维,二维)

较早的编译器是不同意这样做的,所以一些书籍比方以Tc解说的书本都说数组的下标不能是变量.在vc6.0下亦是如此. 只是在一些较新的编译器如dev c++已经支持了,例如以下代码不会报错 #include <stdio.h> #include <stdlib.h> int main() { int a; int i; scanf("%d",&a); int c[a]; for( i =0 ;i<a;i++) scanf("%d",

一维数组,二维数组,三维数组,数组与指针,结构体数组,通过改变指针类型改变访问数组的方式

 打印数组中的每个元素,打印每个元素的地址: #include <stdio.h> #include <stdlib.h> void main(void) { int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; for (int *p = a; p < a + 10;p++)  //指针类型决定4个字节 { printf("\n%p,%d", p, *p); } getchar(); } 指针数组 #inclu

指针数组和二维数组指针变量

指针数组 概念: 一个数组的元素值为指针则是指针数组. 指针数组是一组有序的指针的集合. 指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量. 指针数组说明的一般形式为: 类型说明符 *数组名[数组长度] 其中类型说明符为指针值所指向的变量的类型. 例如: int *pa[3] 表示pa是一个指针数组,它有三个数组元素,每个元素值都是一个指针,指向整型变量. 1.用一个指针数组来指向一个二维数组. 指针数组中的每个元素被赋予二维数组每一行的首地址,因此也可理解为指向一个一维数

poj 1195 二维树状数组 及二维树状数组模板

http://poj.org/problem?id=1195 求矩阵和的时候,下标弄错WA了一次... 求矩形(x1,y1) (x2,y2)的sum |sum=sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1) 二维树状数组讲解:http://blog.csdn.net/u011026968/article/details/38532117 二维树状数组模板: /*========================================

JavaScript - 一维数组、二维数组基础

<html> <head> <head> <body> <script language="javascript"> // 数组 var arr = ["wjp", 520, 'wcc', 13.14] ; for(var i=0; i<arr.length; i++){ alert(arr[i]); } // 数组为空undefined var arr2 = ["wjp",,51

java数组(一维数组,二维数组)

数组初始化: 1,动态初始化:数组定义与为数组分配空间和赋值的操作分开进行 2,静态初始化:在定义数组的同时就为数组元素分配空间并赋值 3,默认初始化:数组是引用类型,它的元素相当于类的成员变量,因此,数组分配空间之后 每个元素也被按照成员的规则被隐士的初始化值 ------------------------------------------------. 一维数组: package day06; import java.util.Date; /*** * 数组演示 * 数组的声明: * t

C#一维数组,二维数组,多维数组

所谓的数组,就是相同数据类型的元素的元素按一定顺数排列的集合,就是把有限个类型相同的变量用一名字命名,然后用编号区分他们的变量的集合,这个名字成为数组名,编号称为下标.组成数组的各个变量成为数组的分量,也称为数组的元素,有时也称为下标变量,数组是在程序设计中,为了处理方便,把具有相同类型的若干变量按有序的形式组织起来的一种形式.这些按序排列的同类数据元素的集合成为数组. 数组又分为一维数组,二维数组,多维数组 一维数组用一个整数来索引,多维数组用两个或多个整数来索引. 一.数据类型[] 变量名

直观理解C语言中指向一位数组与二维数组的指针

一维数组和指针: 对于一位数组和指针是很好理解的: 一维数组名: 对于这样的一维数组:int a[5];  a作为数组名就是我们数组的首地址, a是一个地址常量 . 首先说说常量和变量的关系, 对于变量来说, 用箱子去比喻再好不过了, 声明一个变量就声明一个箱子,比如我们开辟出一个苹果类型的箱子, 给这个变量赋值就是把盛放苹果的箱子中放入一个实实在在的苹果, 这就是变量的赋值.  而对于数组来说, 就是一组类型相同的箱子中,一组苹果箱子, 可以放入不同的苹果. 一维数组空间: 变量被声明后, 我