十道簡單演算法題

Java3y發表於2018-03-30

前言

最近在回顧以前使用C寫過的資料結構和演算法的東西,發現自己的演算法和資料結構是真的薄弱,現在用Java改寫一下,重溫一下。

只能說慢慢積累吧~下面的題目難度都是簡單的,演算法的大佬可直接忽略這篇文章了~入門或者演算法薄弱的同學可參考一下~

很多與排序相關的小演算法(合併陣列、獲取數字每位值的和),我都沒有寫下來了,因為只要會了歸併排序(合併陣列),會了桶排序(獲取數字每位的值),這些都不成問題了。如果還不太熟悉八大基礎排序的同學可看:【八大基礎排序總結

由於篇幅問題,每篇寫十道吧~

如果有錯的地方,或者有更好的實現,更恰當的理解方式希望大家不吝在評論區留言哦~大家多多交流

十道簡單演算法題

題目的總覽

  1. 1-n階乘之和
  2. 獲取二維陣列每列最小的值
  3. 求"1!+4!(2的平方)+9!(3的平方)+...+n的值
  4. 陣列對角線元素之和
  5. 列印楊輝三角形
  6. 猴子吃桃子問題
  7. 計算單詞的個數
  8. 判斷字母是否完全一樣
  9. 判斷一個數是不是2的某次方
  10. 判斷一個數字是不是ugly number

一、1-n階乘之和

1-n階乘之和怎麼算?

  • 1的階乘是1
  • 2的階乘是1*2
  • 3的階乘是1*2*3
  • 4的階乘是1*2*3*4
  • .........

現在我們要求這些階乘的和。思路:

  • 3階乘的和其實上就是2階乘的和+3的階乘
  • 4階乘的和其實上就是3階乘的和+4的階乘
  • .......


    /**
     * 1-n的階乘之和
     */
    public static void Factorial(int n) {

        //總和
        double sum = 0;

        //階乘值,初始化為1
        double factorial = 1;

        for (int i = 1; i <= n; i++) {

            factorial = factorial * i;


            sum = (int) (sum + factorial);

        }

        System.out.println("公眾號:Java3y" + "     " + sum);

    }
複製程式碼

二、獲取二維陣列每列最小的值

獲取二維陣列每列最小的值

思路:遍歷列,再遍歷列中行

我們一般運算元組都是從行開始,再到列的。這次要求的是每列的最小值,因此需要在內部for迴圈遍歷的是行


    /**
     * 求出二維陣列每列的最小值
     */
    public static void minArray() {


        //二維陣列
        int[][] arrays = {
            {23, 106, 8, 234},
            {25, 9, 73, 19},
            {56, 25, 67, 137}
        };


        //獲取列數
        int maxColLength = arrays[0].length;



        //使用一個陣列來裝載每列最小的值
        int[] minArray = new int[maxColLength];


        //控制列數
        for (int i = 0; i < maxColLength; i++) {

            //假設每列的第一個元素是最小的
            int min = arrays[0][i];

            //控制行數
            for (int j = 1; j < arrays.length; j++) {


                //找到最小值
                if (arrays[j][i] < min) {
                    min = arrays[j][i];
                }
            }

            //賦值給裝載每列最小的值的陣列
            minArray[i] = min;
        }


        System.out.println("公眾號:Java3y" + "     " + minArray);

    }


複製程式碼

三、求"1!+4!(2的平方)+9!(3的平方)+...+n的值

求"1!+4!(2的平方)+9!(3的平方)的值

思路:先求平方,後求階乘,最後相加即可~



    /**
     * 求"1!+4!(2的平方)+9!(3的平方)+...+n的值
     */
    public static void calculate() {

        double sum = 0;

        for (int i = 1; i <= 3; i++) {

            //得到平方數
            int square = i * i;

            //階乘值,從1開始
            double factorial = 1;

            //求階乘
            for (int j = 1; j <= square; j++) {
                factorial = factorial * j;
            }

            sum = sum + factorial;

        }

        System.out.println("公眾號:Java3y" + "     " + sum);
        
    }
複製程式碼

四、陣列對角線元素之和

陣列對角線元素之和

思路:

  • 只要行和列相等,即是對角線的元素

    /**
     * 陣列對角線之和
     */
    public static void arraySum() {

        int[][] arrays = {
                {23, 106, 8, 234},
                {25, 9, 73, 19},
                {56, 25, 67, 137},
                {33, 22, 11, 44},
        };

        //和
        int sum = 0;

        for (int i = 0; i < arrays.length; i++) {

            for (int j = 0; j < arrays[i].length; j++) {

                if (i == j) {

                    sum = sum + arrays[i][j];

                }
            }
        }


        System.out.println("公眾號:Java3y" + sum);
        
    }
複製程式碼

五、列印楊輝三角形

楊輝三角形

楊輝三角形長的是這個樣子:

十道簡單演算法題

ps:圖片來源網上,侵刪~

規律:

  • 每行的第一個和最後一個都是1
    • 進一步推算:第1列全部為1,第一行全都是1,當列數等於行數為1
  • 當前值等於頭上的值加頭上的左邊的值
  • 第一行一列,第二行兩列,第三行三列.......

十道簡單演算法題

程式碼實現:


    /**
     * 列印楊輝三角形
     */
    public static void PascalTriangle() {


        //列印十行的楊輝三角形
        int[][] arrays = new int[10][];


        //行數
        for (int i = 0; i < arrays.length; i++) {


            //初始化第二層的大小
            arrays[i] = new int[i + 1];

            //列數
            for (int j = 0; j <= i; j++) {

                //是第一列,第一行,行數等於列數,那麼通通為1
                if (i == 0 || j == 0 || j == i) {
                    arrays[i][j] = 1;
                } else {

                    //當前值等於頭上的值+頭上左邊的值
                    arrays[i][j] = arrays[i - 1][j] + arrays[i - 1][j - 1];
                }

            }
        }

        System.out.println("公眾號:Java3y" + "-------------------------------");

        for (int[] array : arrays) {
            for (int value : array) {
                System.out.print(value + "\t");
            }
            System.out.println();

        }


        System.out.println("公眾號:Java3y" + "-------------------------------");


    }
複製程式碼

結果:

十道簡單演算法題

六、猴子吃桃子問題

猴子摘下了n個桃子,當天吃掉一半多一個,第二天也是吃掉剩下桃子的一半多一個,到了第十天,桃子只剩下了1個。問:猴子第一天摘了多少個桃子

思路:

  • 假設當天有n個桃子,它是前一天桃子的一半少1個,f(n - 1) = f(n)/2 - 1,
  • 我們就可以推出當天桃子的個數:根據遞推公式:f(n) = 2 * f(n - 1) + 2

用遞迴和迴圈都可解決:

遞迴方式:


    /**
     * 猴子吃桃問題
     * @param x 天數
     */
    public static int monkeyQue(int x) {

        if (x <= 0) {
            return 0;

        } else if (x == 1) {
            return 1;

        } else {
            return 2 * monkeyQue(x - 1) + 2;
        }

    }
複製程式碼

迴圈方式:


        int x = 1;
        for (int i = 1; i <= 9; i++) {
            x = (x + 1) * 2;
		}
複製程式碼

結果:

十道簡單演算法題

七、計算單詞的個數

輸入一段字元,計算出裡面單詞的個數,單詞之間用空格隔開 ,一個空格隔開,就代表著一個單詞了

思路:

  • 把字元遍歷一遍,累計由空格串轉換為非空格串的次數,次數就是單詞的個數
  • 定義一個標誌性變數flag,0表示的是空格狀態,1表示的是非空格狀態

    /**
     * 輸入一段字元,計算出裡面單詞的個數
     *
     * @param str 一段文字
     */
    public static int countWord(String str) {


        // 0 表示空格狀態,1 表示非空格狀態
        int flag = 0;

        // 單詞次數
        int num = 0;


        for (int i = 0; i < str.length(); i++) {

            if (String.valueOf(str.charAt(i)).equals(" ") ) {
                flag = 0;
            } else if (flag == 0) {
                num++;
                flag = 1;
            }

        }

        return num ;

    }

複製程式碼

結果:

十道簡單演算法題

八、判斷字母是否完全一樣

給定兩個字串s和t,判斷這兩個字串中的字母是不是完全一樣(順序可以不一樣)

思路:

  • 遍歷這兩個字串,用每個字元減去'a',將其分別存入到陣列中去,隨後看這兩個陣列是否相等即可

要點:

  • 'c'-'a'=2即可計算出儲存的位置,如果有多個,則+1即可,後面我們來比較陣列大小

程式碼實現:




    /**
     * 給定兩個字串s和t,判斷這兩個字串中的字母是不是完全一樣(順序可以不一樣) 
     */
    public static void isAnagram() {

        //分別儲存字串的字元
        char[] array1 = new char[26];
        char[] array2 = new char[26];


        String s1 = "pleasefollowthewechatpublicnumber";
        String s2 = "pleowcnumberthewechatpubliasefoll";


        for (int i = 0; i < s1.length(); i++) {
            char value = s1.charAt(i);

            // 算出要儲存的位置
            int index = value - 'a';

            array1[index]++;
        }

        for (int i = 0; i < s2.length(); i++) {
            char value = s2.charAt(i);

            // 算出要儲存的位置
            int index = value - 'a';

            array2[index]++;
        }

        for (int i = 0; i < 26; i++) {
            if (array1[i] != array2[i]) {
                System.out.println("不相同");
                return;
            }
        }

        System.out.println("相同");

    }

複製程式碼

結果:

十道簡單演算法題

九、判斷一個數是不是2的某次方

判斷一個數是不是2的某次方

思路:

  • 除2取餘數,直至餘數不為0【針對2的倍數這種情況】,看是不是等於1就可以判斷是不是2的某次方了

    /**
     * 判斷是否是2的某次方
     */
    public static void isPowerOfTwo() {

        int num = 3;

        if (num == 0) {
            System.out.println("不是");
        }

        while (num % 2 == 0) {
            num = num / 2;
        }

        if (num == 1) {
            System.out.println("是");
        } else {
            System.out.println("不是");

        }

    }

複製程式碼

結果:

十道簡單演算法題

這題還有另一種解決方式,就是位運算:

  • 2的n次方都有一個特點,二進位制都是1000000
  • 如果 **2的n次方的二進位制-1和2的n次方二進位制做按位與運算,那麼得出的結果肯定是0 **

	if(num <= 0){
        System.out.println("不是");
    }
    else if(num == 1){
        System.out.println("是");
    }
    else{
        if( (num & (num-1) ) == 0){
            System.out.println("是");
        }
        else{
            System.out.println("不是");
        }
    }
複製程式碼

十、判斷一個數字是不是ugly number

判斷一個數字是不是ugly number(分解出來的質因數只有2、3、5這3個數字)

思路:

  • 如果是由2,3,5組成的,那麼這個數不斷除以2,3,5,最後得出的是1,這個數就是純粹用2,3,5組成的
    • 跟之前判斷該數是否2的某次方是一樣的思路~

程式碼:


    /**
     * 判斷一個數字是不是ugly number(分解出來的質因數只有2、3、5這3個數字)
     * @param num
     */
    public static void isUgly(int num) {
        if (num <= 0) {
            System.out.println("不是");
        } else {
            while (num % 2 == 0) {
                num = num / 2;
            }
            while (num % 3 == 0) {
                num = num / 3;
            }
            while (num % 5 == 0) {
                num = num / 5;
            }
            if (num == 1) {
                System.out.println("是");

            } else {
                System.out.println("是");

            }
        }
    }
複製程式碼

結果:

十道簡單演算法題

總結

沒錯,你沒看錯,簡單的小演算法也要總結!

其實我覺得這些比較簡單的演算法是有"套路"可言的,你如果知道它的套路,你就很容易想得出來,如果你不知道它的套路,那麼很可能就不會做了(沒思路)。

積累了一定的"套路"以後,我們就可以根據經驗來推斷,揣摩演算法題怎麼做了。

舉個很簡單的例子:

  • 乘法是在加法的基礎之上的,那乘法我們是怎麼學的?**背(積累)**出來的,9*9乘法表誰沒背過?比如看到2+2+2+2+2,會了乘法(套路)以後,誰還會慢慢加上去。看見了5個2,就直接得出2*5

  1. 1-n階乘之和
    • 求n的階乘就用1*2*3*4*...n,實際上就是一個迴圈的過程,求和就套個sum變數即可!
  2. 獲取二維陣列每列最小的值
    • 外層迴圈控制列數,內層迴圈控制行數,這就是遍歷每列的方法~
  3. 求"1!+4!(2的平方)+9!(3的平方)+...+n的值
    • 先求平方,再求階乘,最後套個sum變數
  4. 陣列對角線元素之和
    • 行和列的位置相等,即是對角線上的元素
  5. 列印楊輝三角形
    • 找出楊輝三角形的規律:第一行、第一列和列值等於行值時上的元素都是1,其餘的都是頭上的值加頭上的左邊的值
  6. 猴子吃桃子問題
    • 根據條件,我們可以推算出前一天桃子,進而推出當天桃子(規律)。猴子都是在相等的條件(剩下桃子的一半多一個),因此就應該想到迴圈或者遞迴
  7. 計算單詞的個數
    • 利用每個單詞間會有個空格的規律,用變數來記住這個狀態(字母與空格)的轉換,即可計算出單詞的個數!
  8. 判斷字母是否完全一樣
    • 將每個字母都分別裝載到陣列裡面去,'c-a'就是字母c陣列的位置了(也就是2)。由於字母出現的次數不唯一,因此我們比較的是陣列的值(如果出現了兩次,那麼值為2,如果出現了3次,那麼值為3)。只要用於裝載兩個陣列的值都吻合,那麼字母就是一樣!
  9. 判斷一個數是不是2的某次方
    • 最佳方案:2的某次方在二進位制都有個特點:10000(n個0)--->ps:程式設計師的整數~..........那麼比這個數少一位的二進位制肯定是01111,它倆做&運算,那麼肯定為0。用這個特性就非常好判斷該數是否是2的某次方了
    • 次方案:2的某次方的數不斷縮小(只要number % 2 == 0就可以縮小,每次number / 2),最後的商必然是1。
  10. 判斷一個數字是不是ugly number
    • 分解出來的質因數只有2、3、5這3個數字,這題其實就是判斷該數是否為2的某次方的升級版。將這個數不斷縮小(只要number%2||%3||%5==0,每次number / 2 | / 3 /5),最後的商必然是1

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y

相關文章