0~9十個數,每個數只能使用一次,組成兩個三位數相加和為四位數的演算法

雲霏霏發表於2014-07-08

  這幾天上網,看到百度裡面有人問這一道題目,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個結果。說實話,我也沒想到會有這麼多。。。

 

 

相關文章