這幾天上網,看到百度里面有人問這一道題目,0~9十個數,組成如下加法式 *** + *** = ****,每個數字都只能使用一次,問一共多少中組合?
今天,就用C#語言來寫一下,解出這道題,其他語言算法相同,只是語法不同,這里由於時間關系,不再貼出代碼。
針對大家提出的優化建議,已經將優化方案寫出,下面是具體優化方案:
這里先講解一下思路,首先我們是程序員,不是數學家,我們是站在編程的角度思考問題。這里是兩個三位數相加,得到一個四位數,所有數字不能重復,最大的和應該為987 + 654 = 1641,就是說兩個三位數相加的結果不會超過2000.那么1一定在后面的四位數中, 那么最小的三位數是203,最大的三位數是987,確定循環的范圍,當然你非要用100到999也可以,不過就是效率低一些罷了。
通過循環,得到兩個三位數后,然后就是將兩個數相加,得到他們的和,驗證和是否為四位數、是否重復使用了數字。當然這兩個可以放到一起驗證,我的思路是,將兩個三位數和他們的和,拼成一個字符串,然后判斷0~9哪個數字不存在字符串中,只要有一個不存在,就不符合條件,只有0~9都存在,才是正確結果。
下面用代碼來實現一下,打開VS2010,新建一個控制台程序,打開Program.cs開始編寫代碼,全部代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestConsoleApp { class Program { static void Main(string[] args) { long start = DateTime.Now.Ticks; //實例化PrintNum類 PrintNum pNum = new PrintNum(); pNum.printNumbers(); long useTime = DateTime.Now.Ticks - start; Console.WriteLine("Time used:" + useTime / 10000 + "ms"); Console.Read(); } } public class PrintNum { public void printNumbers() { int result = 0; int lineNum = 1; for (int i = 203; i <= 987; i++) { for (int j = 203; j <= 987; j++) { result = i + j; if (isTrue(result, i, j)) { Console.Write(lineNum.ToString("00") + ": "); Console.Write(i + " + "); Console.Write(j + " = "); Console.Write(result + "\t"); //每行顯示三個 if (lineNum % 3 == 0) { Console.WriteLine(); } lineNum++; } } } } public bool isTrue(int result,int i,int j) { String str = "0123456789"; String s = result + "" + i + "" + j; for(int k = 0;k < str.Length;k++) { if (!s.Contains(str[k])) { return false; } } return true; } } }
這里寫了一個PrintNum類,將方法封裝到類里面,然后在main方法中實例化該類,調用方法輸出結果。結果如下:
這是常規寫法,代碼沒有經過優化,看到執行這個過程一共消耗了474ms.下面是經過優化的代碼:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TestConsoleApp { class Program { static void Main(string[] args) { long start = DateTime.Now.Ticks; //實例化PrintNum類 PrintNum pNum = new PrintNum(); pNum.printNumbers(); long useTime = DateTime.Now.Ticks - start; Console.WriteLine("Time used:" + useTime / 10000 + "ms"); Console.Read(); } } public class PrintNum { public void printNumbers() { int result = 0; int lineNum = 1; for (int i = 203; i <= 987; i++) { for (int j = 987; j >= 203; j--) { result = i + j;
if (result > 1000) { if (isTrue(result, i, j)) { Console.Write(lineNum.ToString("00") + ": "); Console.Write(i + " + "); Console.Write(j + " = "); Console.Write(result + "\t"); //每行顯示三個 if (lineNum % 3 == 0) { Console.WriteLine(); } lineNum++; } } else { break; } } } } public bool isTrue(int result,int i,int j) { String str = "0123456789"; String s = result + "" + i + "" + j; for(int k = 0;k < str.Length;k++) { if (!s.Contains(str[k])) { return false; } } return true; } } }
執行結果如圖:
執行共耗時315ms,一下減少了100多毫秒,當然我的電腦性能好,在性能差一點的電腦上面,差別就不是這么多了。優化的思路是,內循環從大到小,當兩個數相加小於1000及不是四位數時,退出本次循環。就是減少了循環次數。
是的,你沒看錯,前面的是序號,一共96個結果。說實話,我也沒想到會有這么多。。。