1.有數組penny,penny中所有的值都為正數且不重復。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定一個整數aim(小於等於1000)代表要找的錢數,求換錢有多少種方法。
給定數組penny及它的大小(小於等於50),同時給定一個整數aim,請返回有多少種方法可以湊成aim。
測試樣例:
[1,2,4],3,3
返回:2
penny[i]代表貨幣的面值。
f[n],n代表可以組成的面值。f[n]代表可以組成的方法。
f[0] 代表組成0,只有一種方法,就是不選任何貨幣,就可以組成0;
f[j] 代表組成j,有幾種方法,等於使用n-1個penny[i]的值的方法。循環累加到aim,最后就得到了組成aim的方法。
例如:
penny[i]=5,那么組成的數,是f[5],f[10],f[15] ,能被5整除的,都為前一個加上當前的值。
當所有面值的貨幣,都循環完成,就得到了所求值。
class Exchange { public: int countWays(vector<int> penny, int n, int aim) { int f[1000]; memset(f,0,sizeof(f)); f[0] = 1; for(int i = 0;i < n;++ i) for(int j = penny[i];j <= aim;++ j) f[j] += f[j - penny[i]]; return f[aim]; } };
2.有n級台階,一個人每次上一級或者兩級,問有多少種走完n級台階的方法。為了防止溢出,請將結果Mod 1000000007
給定一個正整數int n,請返回一個數,代表上樓的方式數。保證n小於等於100000。
#define Mod 1000000007 class GoUpstairs { public: int cnt[300030]; int countWays(int n) { cnt[0] = 1; for(int i = 1;i <= n;++ i) cnt[i] = ((i >= 1 ? cnt[i - 1] : 0) + (i >= 2 ? cnt[i - 2] : 0)) % Mod; return cnt[n]; } };
這個題可以是使用2個變量,循環交替的增加就可以了。就會占用連續內存了。
3.有一個矩陣map,它每個格子有一個權值。從左上角的格子開始每次只能向右或者向下走,最后到達右下角的位置,路徑上所有的數字累加起來就是路徑和,返回所有的路徑中最小的路徑和。
給定一個矩陣map及它的行數n和列數m,請返回最小路徑和。保證行列數均小於等於100.
測試樣例:
[[1,2,3],[1,1,1]],2,3
返回:4
class MinimumPath { public: int getMin(vector<vector<int> > map, int n, int m) { // write code here vector<vector<int> > dp(n,vector<int>(m)); dp[0][0] = map[0][0]; for(int i=1;i<n;i++){ dp[i][0] = map[i][0] + dp[i-1][0]; } for(int i=1;i<m;i++){ dp[0][i] = map[0][i] + dp[0][i-1]; } for(int i=1;i<n;i++){ for(int j=1;j<m;j++){ dp[i][j] = min(dp[i][j-1]+map[i][j],dp[i-1][j]+map[i][j]); } } return dp[n-1][m-1]; } };
4.這是一個經典的LIS(即最長上升子序列)問題,請設計一個盡量優的解法求出序列的最長上升子序列的長度。
給定一個序列A及它的長度n(長度小於等於500),請返回LIS的長度。
測試樣例:
[1,4,2,5,3],5
返回:3
int getNum(vector<int>a){ vector<int>dp(a.size()); if (a.size() < 1)return 0; if (a.size() == 1)return a[0]; int len = a.size(); dp[0] = 1; for (int i = 1; i < len; i++){ for (int j = 0; j < i; j++){ if (a[i]>a[j]){ dp[i] = max(dp[i], dp[j] + 1); } } }
int ans = 0; for(int i = 0; i < n; i++){ ans = max(ans, dp[i]); } return ans;
}
