針對規模有限的演算法題技巧----打表
技術標籤:leetcode-joy演算法
引入
比如我們要求某陣列中的每個數字的質數因子,比如 9 = 3 ∗ 3 9=3*3 9=3∗3,但陣列中給的數是範圍是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();
}
}
}
找規律!!
- 0返回-1
- 奇數返回-1
- 會發現從3以後,每個數字都對應4個apples的數量,且最後一個對應的apples數量就是8*i
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,先手贏。
看到這裡,基本可以確定,草的數目後確定後,對應唯一的結果,這也是“絕頂聰明”的意思,因此我們可以著手寫暴力法。
從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();
}
}
會發現: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;
}