矩阵中最大子矩阵之和

一、题目描述

获取二维数组中的最大子二维数组
要求:

  1. 以指定格式的文本文件形式输入数组。
  2. 数组由一维变为二维
  3. 给出单元测试/代码覆盖率的最终覆盖率的报告,撰写博客。

二、实现思路

不多bb,直接暴力破解。

三、实现代码

package maxsubmatrix

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// 暴力破解
func MaxSubmatrixSum(matrix [][]int) int {
	// 行和列数
	r := len(matrix)
	c := len(matrix[0])

	maxSubmatrix := 0

	for i := 0; i < r; i++ {
		for j := 0; j < c; j++ {
			for k := i; k < r; k++ {
				for l := j; l < c; l++ {
					sumSubmatrix := 0
					for m := i; m < k+1; m++ {
						for n := j; n < l+1; n++ {
							sumSubmatrix += matrix[m][n]
						}
					}
					if sumSubmatrix > maxSubmatrix {
						maxSubmatrix = sumSubmatrix
					}
				}
			}
		}
	}
	return maxSubmatrix
}

// 读取文件中的文本信息,构建二维数组
func ReadMatrix(fileName string) ([][]int, error) {
	// matrix保存构建好的矩阵
	var matrix []([]int)
	f, err := os.Open(fileName)
	if err != nil {
		fmt.Println("failed to read file")
		return matrix, err
	}
	scanner := bufio.NewScanner(f)
	scanner.Split(bufio.ScanLines)
	row := 0
	col := 0
	// 读取行
	if scanner.Scan() {
		row, err = strconv.Atoi(scanner.Text())
		if err != nil {
			fmt.Println("file formate error!")
			return matrix, err
		}
	}
	// 读取列
	if scanner.Scan() {
		col, err = strconv.Atoi(scanner.Text())
		if err != nil {
			fmt.Println("file formate error!")
			return matrix, err
		}
	}

	// 读取矩阵内容,构建二维矩阵
	for scanner.Scan() {
		line := scanner.Text()
		eles := strings.Split(line, " ")
		var arr []int
		for i := 0; i < len(eles); i++ {
			ele, err := strconv.Atoi(eles[i])
			if err != nil {
				fmt.Println("file format error")
				return matrix, err
			}
			arr = append(arr, ele)
		}
		matrix = append(matrix, arr)
	}
	// 如果读取的行和列与数据中的行与列不相等
	if row != len(matrix) || col != len(matrix[0]) {
		fmt.Println("File format error !")
		return matrix, err
	}
	return matrix, err
}

四、测试

使用golang自带的单元测试工具即可,使用方法在我的前面博客有讲:Golang单元测试、最大子数组、效能分析

1. 测试案例

对于这个最大子矩阵的题目,测试的案例有如下几个矩阵:
对于text1.txt:

3
3
1 5 2
5 4 9
6 2 3

text1.txt矩阵的最大子矩阵之和应该是37.
对于text2.txt:

3
3
1 2 3
3 4 5
2 4 5

text2.txt矩阵的最大子矩阵之和应该是29。
text3.txt如下:

4
4
1 6 -9 3
-4 9 3 6
3 -6 1 6
3 9 4 -5

text3.txt表示的矩阵的最大子矩阵之和是:30。
对于text4.txt,如下所示:

2
2
1 1
1 1

text4.txt最大子矩阵之和是:4。

2. 测试代码

测试代码如下:

package maxsubmatrix

import (
	"os"
	"testing"
)


func TestMatrix1(t *testing.T) {
	matrix, err := ReadMatrix("text1.txt")
	if err != nil {
		t.Error("failed to read matrix from file")
		os.Exit(-1)
	}

	max := MaxSubmatrixSum(matrix)
	t.Log(max)
}
func TestMatrix2(t *testing.T) {
	matrix, err := ReadMatrix("text2.txt")
	if err != nil {
		t.Error("failed to read matrix from file")
		os.Exit(-1)
	}

	max := MaxSubmatrixSum(matrix)
	t.Log(max)
}
func TestMatrix3(t *testing.T) {
	matrix, err := ReadMatrix("text3.txt")
	if err != nil {
		t.Error("failed to read matrix from file")
		os.Exit(-1)
	}

	max := MaxSubmatrixSum(matrix)
	t.Log(max)
}
func TestMatrix4(t *testing.T) {
	matrix, err := ReadMatrix("text4.txt")
	if err != nil {
		t.Error("failed to read matrix from file")
		os.Exit(-1)
	}

	max := MaxSubmatrixSum(matrix)
	t.Log(max)
}

3. 测试结果

然后输出命令,进行单元测试:

go test submatrix_test.go -v

可以在控制台看到测试结果:

根据结果,符合我们的预期。

五、Golang覆盖率测试

然后就是显示单元测试的覆盖率,对于这个题目来说,并没有分支很少,可以说就一个主分支,覆盖率没啥好测的。
对于覆盖率,golang也自带了工具可以测试。
直接输入命令,就可以测试覆盖率,并且还可以可视化出来.
输入下面命令,把覆盖率信息写入到一个cover.out文件中,

go test -coverprofile cover.out

在控制台中并且输出覆盖率信息:

由图可知,该代码覆盖率是79.2%。然后还可以以可视化的形式展示,在控制台输入下面代码:

go tool cover -html=cover.out -o cover.html

就会生成一个cover.html文件,打开该文件,如下图所示:


可以看到图中对每一行代码是否测试到都进行了分析,绿色表示覆盖了,红色表示没有覆盖。

六、参考资料

覆盖率:https://stackoverflow.com/questions/10516662/how-to-measure-test-coverage-in-go/27284510#27284510

posted on 2021-03-31 16:40  FreestyleCoding  阅读(224)  评论(5编辑  收藏  举报

导航