十道簡單算法題


前言

最近在回顧以前使用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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM