今天分享一下枚举思想,这种思想也常是码畜,码奴常用的手段,经常遭到码农以上级别的鄙视,枚举思想可以说是在被逼无奈时最后的狂吼。
一: 思想
有时我们解决某个问题时找不到一点规律,此时我们很迷茫,很痛苦,很蛋疼,突然我们灵光一现,发现候选答案的问题规模在百万之内,
此时我们就想到了从候选答案中逐一比较,一直找到正确解为止。
二: 条件
前面也说了,枚举是我们在无奈之后的最后一击,那么使用枚举时我们应该尽量遵守下面的两个条件。
① 地球人都不能给我找出此问题的潜在规律。
② 候选答案的集合是一个计算机必须能够承受的。
三:举例
下面是一个填写数字的模板,其中每个字都代表数字中的”0~9“,那么要求我们输入的数字能够满足此模板。
思路:首先拿到这个题,蛋还是比较疼的,因为找不到好的解题思路,仔细想想这属于查找类型的问题,常用的查找也就5种,能适合
该问题的查找也就”顺序查找“和”二分查找“,然后仔细看看问题规模最多也就105=100000,其实根据“二分"的思想在这个问题
中并不合适,最后只能用“顺序查找“了。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace Meiju 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 int count = 0; 13 14 //“算”字的取值范围 15 for (int i1 = 1; i1 < 10; i1++) 16 { 17 //“法”字的取值范围 18 for (int i2 = 0; i2 < 10; i2++) 19 { 20 //“洗”字的取值范围 21 for (int i3 = 0; i3 < 10; i3++) 22 { 23 //"脑"字的取值范围 24 for (int i4 = 0; i4 < 10; i4++) 25 { 26 //"题"字的取值范围 27 for (int i5 = 1; i5 < 10; i5++) 28 { 29 count++; 30 31 //一个猜想值 32 var guess = (i1 * 10000 + i2 * 1000 + i3 * 100 + i4 * 10 + i5) * i1; 33 34 //最终结果值 35 var result = i5 * 100000 + i5 * 10000 + i5 * 1000 + i5 * 100 + i5 * 10 + i5; 36 37 if (guess == result) 38 { 39 Console.WriteLine("\n\n不简单啊,费了我 {0}次,才tmd的找出来\n\n", count); 40 41 Console.WriteLine("\t{0}\t{1}\t{2}\t{3}\t{4}", i1, i2, i3, i4, i5); 42 Console.WriteLine("\n\n\tX\t\t\t\t{0}", i1); 43 Console.WriteLine("—————————————————————————————"); 44 Console.WriteLine("\n{0}\t{1}\t{2}\t{3}\t{4}\t{5}", i5, i5, i5, i5, i5, i5); 45 46 Console.Read(); 47 } 48 49 Console.WriteLine("第{0}搜索", count); 50 51 } 52 } 53 } 54 } 55 } 56 57 Console.Read(); 58 } 59 } 60 }
最后我们还是解决了问题,发现其中的时间复杂度达到了O(n5),这个复杂度理论上是让人不能接收的,还好我们的n在10以内,
n的每一次的自增对cpu来说都是莫大的伤害。
__________________________________________________________________________________________________
感谢一楼同学的提醒,你的眼睛很犀利,将O(n5)降低到O(n2),这是非常不错的,为你鼓掌一下。
现将你的想法用code实现一下。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication1 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 //商 13 int[] resultArr = { 111111, 222222, 333333, 444444, 555555, 666666, 777777, 888888, 999999 }; 14 15 //除数 16 int[] numArr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 17 18 int count = 0; 19 20 for (int i = 0; i < resultArr.Count(); i++) 21 { 22 for (int j = 0; j < numArr.Count(); j++) 23 { 24 count++; 25 26 var result = resultArr[i].ToString(); 27 28 var num = numArr[j].ToString(); 29 30 var origin = (resultArr[i] / numArr[j]).ToString(); 31 32 if (origin.LastOrDefault() == result.FirstOrDefault() 33 && origin.FirstOrDefault() == num.FirstOrDefault() 34 && result.Length - 1 == origin.Length) 35 { 36 Console.WriteLine("\n\n费了{0} 次,tmd找出来了", count); 37 Console.WriteLine("\n\n感谢一楼同学的回答。现在的时间复杂度已经降低到O(n2),相比之前方案已经是秒杀级别\n"); 38 39 Console.WriteLine("\t{0}\t{1}\t{2}\t{3}\t{4}", origin.ElementAt(0), origin.ElementAt(1), origin.ElementAt(2), origin.ElementAt(3), origin.ElementAt(4)); 40 Console.WriteLine("\n\n\tX\t\t\t\t{0}", num); 41 Console.WriteLine("—————————————————————————————"); 42 Console.WriteLine("\n{0}\t{1}\t{2}\t{3}\t{4}\t{5}", result.ElementAt(0), result.ElementAt(0), result.ElementAt(0), result.ElementAt(0), result.ElementAt(0), result.ElementAt(0)); 43 44 Console.Read(); 45 } 46 Console.WriteLine("第{0}搜索", count); 47 } 48 } 49 Console.WriteLine("无解"); 50 Console.Read(); 51 } 52 } 53 }