面試題記1

希望各位看客們能積極提供答案

1)125874和它的兩倍251748,包含着同樣的數字,只是順序不同。找出最小的正整數x,使得2x,3x,4x,5x,和6x都包含有相同的數字。

2)求100!各位數之和

3)是用從1到9所有數字,將其任意的連接起來,使之組成十進制數,會得到不同的集合。{2,5,47,89,631}就是比較有趣的集合,它的所有數都屬於質數,請問滿足1-9都是用且只是用一次,而所有數都是質數的集合有多少個?

4)求滿足x+y,x-y,x+z,x-z,y+z,y-z都是完全平方數,且x>y>z>0的最小x+y+z

5)perter有九個4面(金字塔形)骰子每個分別標1,2,3,4,colin有六個六面骰子,每個分別標1,2,3,4,5,6,perter和colin搖骰子,然後比較他們得到的總和,總和最高的獲勝,如果相等的話則是平局。請問perter贏colin的概率是多少,結果以7位小數0.abcdefg的形式給出。


解答(面試的時候都沒想出來,目前就想出一個來,以後慢慢補充答案吧,感覺這些題是給學數學的人做的,鄙人數學一直很爛,所以沒辦法,唉。)

2)其實這個考的是大數的乘法,100!這個數在任何語言裏都無法找到可以容納它的類型,所以只能自己定義結構來做了,(其實面試的時候也想到了解法,但是感覺不夠好結果沒寫,後來也沒想到更好的,悲催,而且感覺自己寫代碼的能力還不夠強,在60分鐘的時間裏很難將代碼調試通過,後來就放棄了。事實後面證明完成這個代碼還是花了一個上午的時間的。寫代碼能力有待加強啊。奮鬥

其實這裏用到的主要思想在大學的課程裏是有的,就是計算機組成原理裏的串行進位鏈,這裏只要用數組(或者其他結構,比如鏈表,隊列都可以,我用java實現的,但是爲了能更簡單的轉化爲C的代碼,這裏就採用了數組來實現)保存計算的中間結果的各個位,數組下標從小到大對應保存中間結果的從低到高位來保存,計算方法用例子來說明吧:

比如a=123456789,b=123456789123456789,那麼用數組A={1,2,3,4,5,6,7,8,9.-1-1.....}保存a,B={1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,-1,-1.-1.....}保存b(這裏後面的數最好初始化爲一個特殊值,我用的-1,這個特殊值是爲運算時預設的循環停止條件,後面代碼裏可以看到。)那麼做第一次乘法運算的時候就用A[0]乘以B的每個元素,期間要注意保存進位的值。這樣就可以得到一箇中間結果用res數組保存,我們另外再申請一個足夠大的數組result用來保存最後的結果,第一次運算的時候將中間結果res拷貝到result保存,再將res清空,留待下次使用。第二次乘法的時候也就是A[1] * B我們又可以得到一箇中間結果同樣存放在res中,然後我們要做的就是上一次的中間結果和這一次的中間結果的加法運算,但是做加法之前我們要對第二次中間結果做一個移位操作,因爲第二次的A[1]是相當於實際運算中的十位位置上的數,所以要將中間結果乘以10然後再做加法運算,加法運算得到的中間結果同樣保存在result中留給下一輪加法運算,然後同樣要清空res留作下輪乘法運算保存中間結果時使用,第三輪就是百位上的乘法了,也就是A[2] * B,得到的結果同樣要做移位,只是移位的位數由上次的移動一位變成了兩位,因爲這是百位上的乘法,也就是10的平方,所以要移動兩位,後面的格輪運算與之前的分析一樣。這裏要注意的是要自己先估算好做運算的兩個數的大概大小,這樣方便你預設運算中用到的數組的大小。這種方法可以計算任意大小的兩個整數的乘法運算,只要你機器的內存夠用就行。

下面是詳細的實現代碼:

public class Mytest
{
    public static void main(String[] args)
    {
        int i = 0;
        int [] result = test();
        Stack<Integer> s = new Stack<Integer>();
        while(result[i] != -1)
        {
            s.push(result[i++]);
        }
        System.out.println(s.size());
        while(!s.empty())
        {
            System.out.print(s.pop());
        }
    }
    private static int [] test()
    {
        int [] result = new int [200];
        result[0] = 1;
        for(int i = 1; i < 200; i++)
        {
            result[i] = -1;
        }
        for(int i = 1;i <= 100; i++)
        {
            result = bigNumberMutiply(result,numToArray(i));
        }
        int i = 0;
        int sum = 0;
        while(result[i] != -1)
        {
            sum += result[i++];
        }
        System.out.println(sum);
        return result;
    }
    private static int [] bigNumberMutiply(int [] a,int [] b)
    {
        int i = 0, j = 0;
        int carryValue = 0;
        int [] result  = new int [200];
        int [] tempRes  = new int [200];
        
        for(int n = 1; n < 200; n++)
        {
            result[n] = -1;
            tempRes[n] = -1;
        }
        while(b[j] != -1)
        {
            while(a[i] != -1)
            {
                int temp = b[j] * a[i] + carryValue;
                result[i] = temp % 10;
                carryValue = temp / 10;
                i++;
                if(carryValue != 0 && a[i] == -1)
                {
                    result[i] = carryValue;
                    break;
                }
            }
            i = 0;
            carryValue = 0;
            if(j == 0)
            {
                int n = 0;
                while(result[n] != -1)
                {
                    tempRes[n] = result[n];
                    n++;
                }
            }
            else
            {
                result = leftShiftNum(result,j);
                tempRes = add(result, tempRes);
            }
            resetArray(result);
            j++;
        }
        return tempRes;
    }
    private static int [] resetArray(int [] a)
    {
        for(int i = 0; i < a.length; i++)
        {
            a[i] = -1;
        }
        return a;
    }
//將數組保存的中間結果左移n位,相當於將這個大數乘以10的n次方
    private static int [] leftShiftNum(int [] a,int n)
    {
        if(n == 0)
            return a;
        int i = 0;
        while(a[i] != -1)
        {
            i++;
        }
        while(i >= 0)
        {
            a[i+n] = a[i];
            i--;
        }
        for(i = 0; i < n; i++)
        {
            a[i] = 0;
        }
        return a;
    }
//將一個整形的數轉換成數組保存
    private static int [] numToArray(int n)
    {
        int [] a = new int[100];//數組的大小取決於n的大小,這裏設置的這個值可以容納一般的需要
        for(int i = 1; i < a.length; i++)
        {
            a[i] = -1;
        }
        int i = 0;
        while(n != 0)
        {
            a[i++] = n % 10;
            n = n / 10;
        }
        return a;
    }
//以串行進位鏈的方式模擬兩個大數的相加
    private static int [] add(int [] a,int [] b)
    {
        int i = 0;
        int [] c = new int[a.length];
        int carryValue = 0;//用於保存計算過程中的進位值,如9+9=18,需要進位,進位值爲1
        resetArray(c);//用於保存最後加法結果的數組
        while(a[i] != -1 && b[i] != -1)//如果還沒運算到任何一個數的最高位則繼續下一位的加法運算
        {
            
            int temp = a[i] + b[i] + carryValue;
            if(temp < 10)
            {
                c[i] = temp;
                carryValue = 0;
            }
            else
            {
                c[i] = temp % 10;
                carryValue = temp/10;
            }
            i++;
        }
        if(a[i] == -1)//如果運算時a的最高位先到,比如a=12,b=1234,則上述循環後還需單獨處理b千位和百位 (1)
        {//如果b的高位還有值未處理,或者a的最高位運算後有進位值(可以嘗試一下a=1,b=9999這種特殊情況就會明白了)
            while(b[i] != -1 || carryValue != 0)
            {
                if(b[i] == -1)
                {
                    c[i] = carryValue;
                    carryValue = 0;
                }
                else
                {
                    int temp = b[i] + carryValue;
                    if(temp < 10)
                    {
                        c[i] = temp;
                        carryValue = 0;
                    }
                    else
                    {
                        c[i] = temp%10;
                        carryValue = temp/10;
                    }
                }
                i++;
            }
        }
        if(b[i] == -1)//同(1)
        {
            while(a[i] != -1 || carryValue != 0)
            {
                if(a[i] == -1)
                {
                    c[i] = carryValue;
                    carryValue = 0;
                }
                else
                {
                    int temp = a[i] + carryValue;
                    if(temp < 10)
                    {
                        c[i] = temp;
                        carryValue = 0;
                    }
                    else
                    {
                        c[i] = temp%10;
                        carryValue = temp/10;
                    }
                }
                i++;
            }
        }
        return c;
    }
}

這個題的最後結果是:100!長度爲158位,

值爲:

93326215443944152681699238856266700490715968264381621468592963895217599

993229915608941463976156518286253697920827223758251185210916864000000

000000000000000000,

各位數之和爲:648

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章