512. Decode Ways
有一個消息包含A-Z
通過以下規則編碼
'A' -> 1
'B' -> 2
...
'Z' -> 26
現在給你一個加密過後的消息,問有幾種解碼的方式
提示:首先合法輸入f[0] = 1.遍歷s從1到n-1。如果當前字符不等於0那麼f[i]+=f[i-1],如果當前字符的前一個字符不爲0,並且兩者加起來是小於26的,那麼結果還要加上法f[i-2](此時爲結尾兩個數字結合的情況)。
答案:
class Solution {
public:
/**
* @param s: a string, encoded message
* @return: an integer, the number of ways decoding
*/
int numDecodings(string &s) {
if (s == "" || s[0] == '0')
return 0;
int n = s.size();
vector<int> f(n, 0);
f[0] = 1;
for (int i = 1; i < n; i++) {
if (s[i] != '0')
f[i] += f[i-1];
if (s[i-1] != '0' && stoi(s.substr(i-1, 2)) <= 26)
f[i] += i == 1 ? 1 : f[i-2];
if (!f[i])
return 0;
}
return f[n-1];
}
};
513. Perfect Squares
給一個正整數 n, 請問最少多少個完全平方數(比如1, 4, 9...)的和等於n。
提示:因爲1^1 = 1所以每個正整數都有解。
動態規劃, 設 f[i] 表示加和爲 i 的最少完全平方數的個數.
狀態轉移方程: f[i] = min{i, f[i - j * j] + 1} (j*j <= i)
邊界: f[i*i] = 1。
答案:時間複雜度O(N^3/2)
class Solution {
public:
/**
* @param n: a positive integer
* @return: An integer
*/
int numSquares(int n) {
// write your code here
vector<int> f(n + 1, 0x7fffffff);
f[0] = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j*j <= i; j++ ){
f[i] = min(f[i], f[i - j*j] + 1);
}
}
return f[n];
}
};
108. Palindrome Partitioning II
給定字符串 s
, 需要將它分割成一些子串, 使得每個子串都是迴文串.
最少需要分割幾次?
提示:首先將回文串分爲兩種,奇數與偶數,設置數組變量isPlin[i][j]表示i到j是否爲迴文串。
dp[i] = min{dp[j] + 1} (j < i 並且 s[j + 1], s[j + 2], ... , s[i] 是迴文串)
答案:
class Solution {
public:
/**
* @param s: A string
* @return: An integer
*/
int minCut(string &s) {
// write your code here
int n = s.size();
if (n == 0) {
return 0;
}
//Calculate isPalin
vector<vector<bool>> isPalin(n, vector<bool>(n, false));
int i, j, p;
for (p = 0; p < n; ++p) {
i = j = p;
while (i >= 0 && j < n && s[i] == s[j]) {
isPalin[i][j] = true;
--i;
++j;
}
}
for (p = 0; p < n-1; ++p) {
i = p;
j = p + 1;
while (i >= 0 && j < n && s[i] == s[j]) {
isPalin[i][j] = true;
--i;
++j;
}
}
//Caculate minCut
vector<int> f(n+1);
//vector<int> pi(n+1);
f[0] = 0;
for (i=1; i<=n; ++i) {
f[i] = INT_MAX;
for (j = 0; j < i; ++j) {
if (isPalin[j][i-1] && f[j] != INT_MAX && f[j] + 1 < f[i]) {
f[i] = f[j] + 1;
//pi[i] = j;
}
}
}
// print solution
/*i = n;
while (i != 0) {
// pi[i]~i-1
for (j = pi[i]; j < i; ++j) {
cout<<s[j];
}
cout<<""<<endl;
i = pi[i];
}*/
return f[n] - 1;
}
};
437. Copy Books
給定 n
本書, 第 i
本書的頁數爲 pages[i]
. 現在有 k
個人來複印這些書籍, 而每個人只能複印編號連續的一段的書, 比如一個人可以複印 pages[0], pages[1], pages[2]
, 但是不可以只複印 pages[0], pages[2], pages[3]
而不復印 pages[1]
.
所有人複印的速度是一樣的, 複印一頁需要花費一分鐘, 並且所有人同時開始複印. 怎樣分配這 k
個人的任務, 使得這 n
本書能夠被儘快複印完?
返回完成複印任務最少需要的分鐘數.
提示:f[k][i]爲k個抄寫員最少需要多少時間抄完前i本書。用二分法時間複雜度更低。如果k>n,相當於k=n。
答案:時間複雜度O(N^2K) 空間O(N)
class Solution {
public:
/**
* @param pages: an array of integers
* @param k: An integer
* @return: an integer
*/
int copyBooks(vector<int> &pages, int k) {
// write your code here
// write your code here
int n = pages.size();
if (n == 0) {
return 0;
}
if(k > n){
k = n;
}
int i, j, m, sum;
vector<vector<int>> f(2, vector<int>(n+1));
for (i = 0; i <= n; ++i) {
f[0][i] = INT_MAX;
}
f[0][0] = 0;
for (i = 1; i <= k; ++i) {
for (j = 0; j <= n; ++j) {
f[i&1][j] = INT_MAX;
sum = 0;
for (m = j; m >= 0; --m) {
if (f[!(i&1)][m] < INT_MAX) {
f[i&1][j] = min(f[i&1][j], max(sum, f[!(i&1)][m]));
}
if (m > 0) {
sum += pages[m - 1];
}
}
}
}
return f[k&1][n];
}
};