偶尔看到的,题目大致如下:
有一个数,abcdefghi,每个字母分别代表了1到9之间的数字(数字不重复),而且该数有一个特性,a能被1整除,ab能被2整除,...abcdefghi能被9整除,求该数。
反正我是不知道小学方法该怎么求,看到这题目,第一反应就是,循环一下就好了——确实最简单的方法,不过要写的循环太多,也容易出错。
再一分析,这不是个递归的过程么,即该数能被本身长度所整除。试了一下,果然出结果了。
代码如下,为了写起来方便,加了两个扩展方法。
namespace ConsoleApplication1 { static class Program { static int total = 0;//看看递归了多少次 const int LENGTH_OF_NUMBER = 9; static void Main(string[] args) { string[] list = new string[] { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; Console.WriteLine("结果是:{0},共运算:{1}次",GetNumber("",list),total); Console.ReadKey(); } /// <summary> /// 递归取得正确的数 /// </summary> /// <param name="str">当前的字符串</param> /// <param name="list">剩余可用的字符列表</param> /// <returns>错误返回空字符串,无错但是可以继续,则返回下一个字符,成功则返回结果</returns> static string GetNumber(string str, IEnumerable<string> list) { total++; if (str.Length > 0) { //如果当前条件都不满足,后续的就没必要继续了 if (!str.CanDivBy(str.Length)) return ""; else if (str.Length == LENGTH_OF_NUMBER) //得到符合的数了,也就没必要继续了 return str; } foreach (var v in list) { string tmp = GetNumber(str + v, list.NewList(v)); if (tmp.Length != LENGTH_OF_NUMBER) continue; else { return tmp; } } return ""; } /// <summary> /// 是否能被某个整数整除 /// </summary> /// <param name="val_str"></param> /// <param name="div"></param> /// <returns>是否可以被整除</returns> public static bool CanDivBy(this string val_str, int div) { long val; if (!long.TryParse(val_str, out val)) return false; return (val * 1.0 / div - val / div) == 0; } /// <summary> /// 根据当前列表,生成一个不包含指定数的新列表 /// </summary> /// <param name="old_list"></param> /// <param name="val"></param> /// <returns></returns> public static IEnumerable<string> NewList(this IEnumerable<string> old_list, string val) { int v = int.Parse(val); return from a in old_list where int.Parse(a) != v select a; } } }
结果是:381654729,共运算:523次
比我想像的次数少一些。
请无视代码中混乱的命名,纯粹一时兴起验证一下。
题目还可以改一下,即可以加上0,变成abcdefghij可以被10整除,只要把长度改成10,数组里加个0就好了