1. 程式人生 > 其它 >針對規模有限的演算法題技巧----打表

針對規模有限的演算法題技巧----打表

技術標籤:leetcode-joy演算法

引入

比如我們要求某陣列中的每個數字的質數因子,比如 9 = 3 ∗ 3 9=3*3 9=33,但陣列中給的數是範圍是1-1000

我們可以設定一個求出1-1000的質數的表(放在靜態區),每個用例直接用這個表就行。

打表找規律

例題1:

小虎買蘋果,他有裝8個蘋果的袋子和裝6個蘋果的袋子,要求袋子最少,且用的袋子都滿了。

暴力法先把結果打出來,儘可能用8號袋裝,然後看剩餘結果能否用6號袋裝,不行,就把8號袋減去一個,再看能不能用6號袋裝…把每個值打印出來,找規律。

public class abc {
    static int mink;


    //tested
public static boolean issix(int num) { if(num%6==0) return true; else return false; } public static int buyapples(int apples) { if(apples==0) return -1; System.out.print(apples+":"); int n=apples/
8; while(n!=-1&&!issix(apples-n*8)) { n-=1; } if(n==-1) return -1; return n+(apples-n*8)/6; } //把1-100的蘋果打印出來 public static void main(String[] args) { for(int i=0;i<100;i++) { System.out.print(buyapples(i)
); System.out.println(); } } }

找規律!!

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-uuZwbiIv-1610760882019)(E1EE042FF86F48568660B49CC2B1F3F0)]

  1. 0返回-1
  2. 奇數返回-1
  3. 會發現從3以後,每個數字都對應4個apples的數量,且最後一個對應的apples數量就是8*i
    [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-wijdDVfR-1610760882022)(B34D31C97E2D4826A9F0412FAC77A8C7)]

O(1)完美解決該題,程式中試了全都一樣。數學原理是滿8的遞減2(不太重要),

 public static int buyapples2(int apples)
    {

        if(apples==6||apples==8)
            return 1;

        if(apples==12|apples==14||apples==16)
            return 2;
        if(apples<=13)
            return -1;
       if(apples==0||apples%2==1)
           return -1;
       if(apples%8==0)
           return apples/8;
       else
           return apples/8+1;
    }

例題2:

給定一個正整數N,表示有N份青草統一堆放在倉庫裡
有一隻牛和一隻羊,牛先吃,羊後吃,它倆輪流吃草
不管是牛還是羊,每一輪能吃的草量必須是:
1,4,16,64…(4的某次方)
誰最先把草吃完,誰獲勝
假設牛和羊都絕頂聰明,都想贏,都會做出理性的決定
根據唯一的引數N,返回誰會贏

eg分析:
草為1的時候,先手選1,先手贏
草為2的時候,先手選1,後手選1,後手贏
草為3的時候,先手選1,後手選1,先手選1,先手贏
草為4的時候,先手選4,先手贏
草為5的時候,先手選4,後手選1,後手贏;或者先手選1,後手選4,後手贏。
草為6的時候,先手選1,後手選4,先手選1,先手贏;或者先手選4,後手選1,先手贏。
看到這裡,基本可以確定,草的數目後確定後,對應唯一的結果,這也是“絕頂聰明”的意思,因此我們可以著手寫暴力法。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-J2m5BU76-1610760882027)(CD969934AF9E420A8101FE188A176256)]

從6開始 會發現 “先後先先後” 的規律 改寫成O(1)

public static String whowin2(int grass)
        {
            if(grass<5)
            {
                if(grass%2==0)
                    return"後手";
                if(grass%2==1)
                    return"先手";
            }
            int n=grass%5;
            if(n==1||n==3||n==4)
                return "先手";
            else
                return "後手";
            
        }

例題3:

定義一種數:可以表示成若干(數量>1)連續正數和的數
比如:
5 = 2+3,5就是這樣的數
12 = 3+4+5,12就是這樣的數
1不是這樣的數,因為要求數量大於1個、連續正數和
2 = 1 + 1,2也不是,因為等號右邊不是連續正數
給定一個引數N,返回是不是可以表示成若干連續正數和的數。

先手暴力解:

 public static boolean isthenum(int num)
        {
            for(int i=1;i<num;i++)
            {
                int sum=i;
                int j=i+1;
                while(true)
                {
                    sum+=j;
                    if(sum==num)
                        return true;
                    else if(sum>num)
                        break;
                    j+=1;
                }
            }
            return false;
        }

        public static void main(String[] args) {
            for(int i=1;i<=100;i++)
            {
                System.out.print(i+": ");
                System.out.print(isthenum(i)+"  ");
                if(i%10==0)
                    System.out.println();
            }
        }

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-feA8eBow-1610760882031)(E559AF8FA40D464FB0F59425FE9A8AA9)]

會發現:false很少:有1 ,2,4,8,16,32,64…2^n


        //tested
        //檢測n是否是2的次方
        public static boolean islog2ed(int n)
        {
            double l=n;
            double q=Math.log(l)/Math.log(2);
            if(q==(int)q)
            {
                return true;
            }
            return false;

        }
        public static boolean isthenum2(int num)
        {
            if(islog2ed(num))
                return true;
            return false;
        }