1. 程式人生 > 實用技巧 >如何在頁面上實現一個圓形的可點選區域

如何在頁面上實現一個圓形的可點選區域

問題:

給定一組只包含'0' '1' 的字串,給定兩個正整數m和n,問,要使用m個'0' n個'1',能最多構成多少個給出字串組中的字串。

Example 1:
Input: strs = ["10","0001","111001","1","0"], m = 5, n = 3
Output: 4
Explanation: This are totally 4 strings can be formed by the using of 5 0s and 3 1s, which are "10","0001","1","0".

Example 2:
Input: strs = ["10","0","1"], m = 1, n = 1
Output: 2
Explanation: You could form "10", but then you'd have nothing left. Better form "0" and "1".
 
Constraints:
1 <= strs.length <= 600
1 <= strs[i].length <= 100
strs[i] consists only of digits '0' and '1'.
1 <= m, n <= 100

  

解法:DP(動態規劃)0-1 knapsack problem(0-1揹包問題)

1.確定【狀態】:

  • 可選擇的元素:前 i 個字串
  • 和:
    • m:m個 ' 0 '
    • n:n個 ' 1 '

2.確定【選擇】:

  • 選擇當前的字串strs[i]
  • 不選擇當前的字串strs[i]

3. dp[i][m][n]的含義:

前 i 個字串中,用m個'0' n個'1' 最多能組成的字串個數。

4. 狀態轉移:

dp[i][m][n]= OR {

  • 選擇 strs[i]:dp[i-1][m-strs[i].count('0')][n-strs[i].count('1')] + 1:=前 i-1 個元素中,用M個'0'N個'1'最多可組成的字串個數 + strs[i]自己一個
    。(M= m-strs[i].count('0'); N= n-strs[i].count('1'))
  • 不選擇 strs[i]:dp[i-1][m][n]:=前 i-1 個元素中,用m個'0'n個'1'最多可組成的字串個數。

}

5. base case:

  • dp[0][m][n]=0
  • dp[i][0][0]=0

程式碼參考:

 1 class Solution {
 2 public:
 3     //dp[i][m][n]:in first i strs, the max number of strs can be formed by m 0s and n 1s.
 4     //case_1.select strs[i]    : = dp[i-1][m-strs[i].count('0')][n-strs[i].count('1')]+1
5 //case_2.not select strs[i]: = dp[i-1][m][n] 6 //dp[i][m][n] = max(case_1, case_2) 7 //base: dp[0][m][n]=0 8 //dp[i][0][0]=0 9 int findMaxForm(vector<string>& strs, int m, int n) { 10 vector<vector<vector<int>>> dp(strs.size()+1, vector<vector<int>>(m+1, vector<int>(n+1, 0))); 11 for(int i=1; i<=strs.size(); i++) { 12 int cout_1 = count(strs[i-1].begin(), strs[i-1].end(), '1'); 13 int cout_0 = count(strs[i-1].begin(), strs[i-1].end(), '0'); 14 for(int M=0; M<=m; M++) { 15 for(int N=0; N<=n; N++) { 16 if(M-cout_0>=0 && N-cout_1>=0) { 17 dp[i][M][N] = max(dp[i-1][M-cout_0][N-cout_1]+1, dp[i-1][M][N]); 18 } else { 19 dp[i][M][N] = dp[i-1][M][N]; 20 } 21 } 22 } 23 } 24 return dp[strs.size()][m][n]; 25 } 26 };

♻️ 優化:空間複雜度:3維->2維

去掉 i

將 m和n 倒序遍歷。

理由參考:https://www.cnblogs.com/habibah-chang/p/13581649.html

程式碼參考:

 1 class Solution {
 2 public:
 3     //dp[i][m][n]:in first i strs, the max number of strs can be formed by m 0s and n 1s.
 4     //case_1.select strs[i]    : = dp[i-1][m-strs[i].count('0')][n-strs[i].count('1')]+1
 5     //case_2.not select strs[i]: = dp[i-1][m][n]
 6     //dp[i][m][n] = max(case_1, case_2)
 7     //base: dp[0][m][n]=0
 8     //dp[i][0][0]=0
 9     int findMaxForm(vector<string>& strs, int m, int n) {
10         vector<vector<int>> dp(m+1, vector<int>(n+1, 0));
11         for(int i=1; i<=strs.size(); i++) {
12             int cout_1 = count(strs[i-1].begin(), strs[i-1].end(), '1');
13             int cout_0 = count(strs[i-1].begin(), strs[i-1].end(), '0');
14             for(int M=m; M>=0; M--) {
15                 for(int N=n; N>=0; N--) {
16                     if(M-cout_0>=0 && N-cout_1>=0) {
17                         dp[M][N] = max(dp[M-cout_0][N-cout_1]+1, dp[M][N]);
18                     }
19                 }
20             }
21         }
22         return dp[m][n];
23     }
24 };