2023-11-15:用go语言,如果一个正方形矩阵上下对称并且左右对称,对称的意思是互为镜像, 那么称这个正方形矩阵叫做神奇矩阵, 比如 : 1 5 5 1 6 3 3 6 6 3 3 6 1 5

2023-11-15:用go语言,如果一个正方形矩阵上下对称并且左右对称,对称的意思是互为镜像,

那么称这个正方形矩阵叫做神奇矩阵,

比如 :

1 5 5 1

6 3 3 6

6 3 3 6

1 5 5 1

这个正方形矩阵就是神奇矩阵。

给定一个大矩阵n*m,返回其中神奇矩阵的数目。

1 <= n,m <= 1000。

来自左程云

答案2023-11-15:

go代码用灵捷3.5编写。

大体过程如下:

1.定义常量MAXN为1001,定义常量baser为491,定义常量basec为499。

2.定义数组powr和powc,分别计算baser和basec的幂次,用于后续计算哈希值。

3.定义数组arr1、arr2、arr3,分别存储原数组、上下对称数组、左右对称数组。

4.定义数组sum1、sum2、sum3,分别存储三个数组的前缀哈希和。

5.通过循环读取输入的n、m和矩阵元素,并顺便把元素存入arr1、arr2、arr3对应位置。

6.构建arr1、arr2、arr3的前缀哈希和,存入sum1、sum2、sum3中。

7.定义函数hash,用于计算矩阵中(a,b)到(c,d)范围内的哈希值。

8.定义函数ok,用于判断以(a,b)到(c,d)范围内的正方形是否为神奇矩阵。

9.定义函数number,用于统计大矩阵中神奇矩阵的数量。分别计算奇数长度和偶数长度的正方形数量,返回总数量。

10.在主函数中调用上述各个函数,输出最终结果。

11.总时间复杂度为$O(n^2 * logn)$,总额外空间复杂度为$O(n^2)$。

go完整代码如下:

package main

import (
	"fmt"
)

const MAXN int = 1001
const baser int = 491
const basec int = 499

var powr [MAXN]int64
var powc [MAXN]int64
var arr1 [MAXN][MAXN]int
var arr2 [MAXN][MAXN]int
var arr3 [MAXN][MAXN]int
var sum1 [MAXN][MAXN]int64
var sum2 [MAXN][MAXN]int64
var sum3 [MAXN][MAXN]int64
var n int
var m int

func init() {
	powr[0] = 1
	powc[0] = 1
	for i := 1; i < MAXN; i++ {
		powr[i] = powr[i-1] * int64(baser)
	}
	for i := 1; i < MAXN; i++ {
		powc[i] = powc[i-1] * int64(basec)
	}
}

func buildHash(arr *[MAXN][MAXN]int, sum *[MAXN][MAXN]int64) {
	for i := 1; i <= n; i++ {
		for j := 1; j <= m; j++ {
			sum[i][j] = sum[i][j-1]*int64(basec) + int64(arr[i][j])
		}
	}
	for i := 1; i <= n; i++ {
		for j := 1; j <= m; j++ {
			sum[i][j] += sum[i-1][j] * int64(baser)
		}
	}
}

func hash(sum *[MAXN][MAXN]int64, a int, b int, c int, d int) int64 {
	ans := sum[c][d] - sum[a-1][d]*powr[c-a+1] - sum[c][b-1]*powc[d-b+1] + sum[a-1][b-1]*powr[d-b+1]*powc[c-a+1]
	return ans
}

func number() int {
	ans := 0
	// 奇数长度,实点做中心
	for i := 1; i <= n; i++ {
		for j := 1; j <= m; j++ {
			l := 1
			r := min(min(i, n-i+1), min(j, m-j+1))
			find := 1
			var m int
			for l <= r {
				m = (l + r) / 2
				if ok(i-m+1, j-m+1, i+m-1, j+m-1) {
					find = m
					l = m + 1
				} else {
					r = m - 1
				}
			}
			ans += find
		}
	}
	// 偶数长度
	// 虚点做中心
	for i := 1; i < n; i++ {
		for j := 1; j < m; j++ {
			// 左上角点为代表
			l := 1
			r := min(min(i, j), min(n-i, m-j))
			find := 0
			var m int
			for l <= r {
				m = (l + r) / 2
				if ok(i-m+1, j-m+1, i+m, j+m) {
					find = m
					l = m + 1
				} else {
					r = m - 1
				}
			}
			ans += find
		}
	}
	return ans
}

func ok(a int, b int, c int, d int) bool {
	if a == c {
		return true
	}
	h1 := hash(&sum1, a, b, c, d)
	h2 := hash(&sum2, n-c+1, b, n-a+1, d)
	h3 := hash(&sum3, a, m-d+1, c, m-b+1)
	return h1 == h2 && h1 == h3
}

func min(x int, y int) int {
	if x < y {
		return x
	}
	return y
}

func main() {
	inputs := []int{5, 5,
		4, 2, 4, 4, 4,
		3, 1, 4, 4, 3,
		3, 5, 3, 3, 3,
		3, 1, 5, 3, 3,
		4, 2, 1, 2, 4}
	ii := 0

	n = inputs[ii]
	ii++
	m = inputs[ii]
	ii++
	for i := 1; i <= n; i++ {
		for j := 1; j <= m; j++ {
			arr1[i][j] = inputs[ii]
			ii++
			arr2[n-i+1][j] = arr1[i][j]
			arr3[i][m-j+1] = arr1[i][j]
		}
	}
	buildHash(&arr1, &sum1)
	buildHash(&arr2, &sum2)
	buildHash(&arr3, &sum3)
	fmt.Println(number())

}

在这里插入图片描述

posted @ 2023-11-15 17:11  福大大架构师每日一题  阅读(8)  评论(0编辑  收藏  举报