字符串数组特定模式检测的现有实现优化问询
数组模式检测的优化方案
问题说明
给定字符串数组:
string[] arr = ["Off", "Off", "Off", "Duty", "Off", "Off", "Duty", "Duty", "Duty", "Duty", "Off", "Off", "Duty"];
需要检测数组中是否存在**至少两个"Off",紧跟一个"Duty",再紧跟至少两个"Off"**的模式。
原实现通过遍历数组找到"Duty"后,检查其前后各两位是否为"Off",代码如下:
for (int i = 0; i < roster.Length; i++) { if (roster[i] == "Duty") { if (i > 1 && i < roster.Length - 2) { if (roster[i-2] == "Off" && roster[i-1] == "Off" && roster[i+1] == "Off" && roster[i+2] == "Off") { return true; } } } }
以下是几种更优的实现方案:
方案1:滑动窗口遍历
直接检查连续5个元素是否匹配模式,逻辑更直观,且无需额外的边界判断:
for (int i = 0; i <= roster.Length - 5; i++) { if (roster[i] == "Off" && roster[i+1] == "Off" && roster[i+2] == "Duty" && roster[i+3] == "Off" && roster[i+4] == "Off") { return true; } } return false;
优势:遍历次数更少(最多遍历 数组长度-4 次),代码简洁,边界条件由循环条件自动保证,不会出现索引越界。
方案2:LINQ 简洁实现
如果追求代码简洁性,可以用LINQ的方式实现,适合小规模数组场景:
return roster .Select((_, index) => index) .Where(index => index >= 2 && index <= roster.Length - 3) .Any(index => roster[index-2] == "Off" && roster[index-1] == "Off" && roster[index] == "Duty" && roster[index+1] == "Off" && roster[index+2] == "Off");
优势:代码可读性高,一行链式调用完成检测;劣势:性能略低于纯循环,大数据量场景不推荐。
方案3:状态机遍历(适合复杂模式扩展)
如果后续需要扩展模式规则(比如调整Off的数量、增加其他状态),状态机方式只需要一次遍历,扩展性更强:
int preOffCount = 0; bool hasDuty = false; int postOffCount = 0; foreach (var item in roster) { if (!hasDuty) { if (item == "Off") { preOffCount++; } else if (item == "Duty") { hasDuty = true; postOffCount = 0; } else { // 遇到非Off/Duty的元素,重置前置计数 preOffCount = 0; } } else { if (item == "Off") { postOffCount++; // 满足前置至少2个Off、后置至少2个Off的条件 if (preOffCount >= 2 && postOffCount >= 2) { return true; } } else { // 遇到非Off元素,重置状态 hasDuty = false; preOffCount = item == "Off" ? 1 : 0; } } } return false;
优势:仅需一次遍历数组,性能最优;状态清晰,后续修改模式规则只需调整计数判断逻辑即可。
内容的提问来源于stack exchange,提问作者user3177651
相关产品推荐
相关产品推荐

