如何高效统计列表中最后一个'No'之后的'Yes'数量?
优化方案分析
你的需求是统计列表最后一个指定元素Y("No")之后的指定元素X("Yes")数量,原方案的思路没问题,但可以在效率、可读性和边界处理上优化,尤其适合大型列表:
1. 基础循环优化(最优性能)
原循环的偏移量计算可以简化,同时修复无"No"时的索引越界问题,并且用更高效的字符串比较:
List<string> MyList = new List<string> { "Yes", "No", "No", "No", "Yes", "Yes", "Yes", "No", "Yes", "No", "Yes", "Yes"}; int lastNoIndex = MyList.FindLastIndex(s => s == "No"); int count = 0; // 处理无"No"的情况,从列表开头开始统计 int startIndex = lastNoIndex == -1 ? 0 : lastNoIndex + 1; // 直接从目标起始索引遍历到末尾,避免每次循环的偏移量计算 for (int i = startIndex; i < MyList.Count; i++) { // 字符串常量用==更高效(CLR字符串驻留机制,直接引用比较) if (MyList[i] == "Yes") { count++; } } Console.WriteLine(count);
优化点说明:
FindLastIndex本身是从后往前遍历,找到第一个匹配项就停止,已经是O(n)的最优查找效率,无需额外调整。- 直接从
lastNoIndex +1开始遍历,避免了原方案中LastNo + i的重复加法操作,减少循环内计算量。 - 用
==替代Equals,对于字符串字面量,CLR会自动驻留,引用对比比值对比更快。 - 修复了无"No"时的索引越界问题,鲁棒性更强。
2. LINQ简洁实现(可读性优先)
如果追求代码简洁,LINQ的Skip+Count组合在List上的效率也很高(List支持直接索引访问,Skip不会产生额外内存分配):
List<string> MyList = new List<string> { "Yes", "No", "No", "No", "Yes", "Yes", "Yes", "No", "Yes", "No", "Yes", "Yes"}; int lastNoIndex = MyList.FindLastIndex(s => s == "No"); int startIndex = lastNoIndex == -1 ? 0 : lastNoIndex + 1; int count = MyList.Skip(startIndex).Count(s => s == "Yes"); Console.WriteLine(count);
注意:
LINQ会有非常轻微的额外开销(委托调用),但对于绝大多数大型列表场景,这种开销可以忽略,换来的是代码更简洁易读。
时间复杂度说明
所有优化方案的时间复杂度都是O(n),这是理论最优解:因为必须至少遍历到最后一个"No"的位置才能确定统计起点,不存在比O(n)更快的算法。
内容的提问来源于stack exchange,提问作者user20292388
相关产品推荐
相关产品推荐

