这个算法的效率已经很高了,徐少侠后来又写了一个一次循环的,但效率没有提高。我的思路也是把两次循环改为一次循环,效率上提高了20%左右。
其实这个性能优化就是扣细节了,算法上没有什么改进
对两处进行改进
1. 一开始就对A和B 加 384,这样就不需要每次计算都减384了,减少了不少减法运算
2. 一次循环
另外eaglet 在考虑,是否可以考虑类似图像有损压缩的算法,把这个这个矩阵利用类似正交余弦变化转换到频域,
再通过频率域的数值分布得到特殊值在A,B 范围内的有效区域,然后针对这些有效区域进行运算,这样可以大大降低
运算的次数。不过这个数学模型真的很难建。
static public int countSpecialNumbers(string[] field, int A, int B)
{
//一开始就对A和B 加 384,这样就不需要每次计算都减384了,减少了不少减法运算
A += '0' * 8;
B += '0' * 8;
int count = 0;
//因为加了一圈0以后整体行列数发生了变化
int cols = field[0].Length + 2;
//将原有一维字符串数组进行转换并增加0
string s = string.Concat(new string('0', cols + 1), String.Join("00", field), new string('0', cols + 1));
//int i;
//一次循环
//不循环外圈的0
for (int i = cols + 1; i < s.Length - cols - 1; i++)
{
int m = i % cols; //m 为 i 和 列宽取模,如果模为0 或者cols-1 则说明是外圈的0
if (m > 0 && m < cols - 1)
{
int number = s[i - cols - 1] + s[i - cols] + s[i - cols + 1] +
s[i - 1] + s[i + 1] +
s[i + cols - 1] + s[i + cols] + s[i + cols + 1];
if (number >= A && number <= B)
{
count++;
}
}
}
return count;
}
{
//一开始就对A和B 加 384,这样就不需要每次计算都减384了,减少了不少减法运算
A += '0' * 8;
B += '0' * 8;
int count = 0;
//因为加了一圈0以后整体行列数发生了变化
int cols = field[0].Length + 2;
//将原有一维字符串数组进行转换并增加0
string s = string.Concat(new string('0', cols + 1), String.Join("00", field), new string('0', cols + 1));
//int i;
//一次循环
//不循环外圈的0
for (int i = cols + 1; i < s.Length - cols - 1; i++)
{
int m = i % cols; //m 为 i 和 列宽取模,如果模为0 或者cols-1 则说明是外圈的0
if (m > 0 && m < cols - 1)
{
int number = s[i - cols - 1] + s[i - cols] + s[i - cols + 1] +
s[i - 1] + s[i + 1] +
s[i + cols - 1] + s[i + cols] + s[i + cols + 1];
if (number >= A && number <= B)
{
count++;
}
}
}
return count;
}
测试结果
eaglet 的原来的算法
5
9
3
0
0
26
用时917毫秒
徐少侠 的算法
5
9
3
0
0
26
用时554毫秒
eaglet改进的算法
5
9
3
0
0
26
用时459毫秒
改进后性能比徐少侠的提高了18%