1. 程式人生 > 其它 >多執行緒之interrupt與優雅停止一個執行緒

多執行緒之interrupt與優雅停止一個執行緒

474. 一和零

題目連結:474. 一和零(中等)

給你一個二進位制字串陣列 strs 和兩個整數 mn

請你找出並返回 strs 的最大子集的長度,該子集中 最多m0n1

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y子集

示例 1:

輸入:strs = ["10", "0001", "111001", "1", "0"], m = 5, n = 3
輸出:4
解釋:最多有 5 個 0 和 3 個 1 的最大子集是 {"10","0001","1","0"} ,因此答案是 4 。
其他滿足題意但較小的子集包括 {"0001","1"} 和 {"10","1","0"} 。{"111001"} 不滿足題意,因為它含 4 個 1 ,大於 n 的值 3 。

示例 2:

輸入:strs = ["10", "0", "1"], m = 1, n = 1
輸出:2
解釋:最大的子集是 {"0", "1"} ,所以答案是 2 。

提示:

  • 1 <= strs.length <= 600

  • 1 <= strs[i].length <= 100

  • strs[i] 僅由 '0''1' 組成

  • 1 <= m, n <= 100

解題思路

該題可以轉為01揹包問題。將揹包看成有兩個口袋,一個口袋裝0,一個口袋裝1,而strs中每個物品的重量有兩個維度,一個重量維度是0的個數,另一個重量維度是1的個數。

  1. 確定dp陣列以及其下標的含義

    該題的dp陣列是一個二維陣列(是因為物品的重量有兩個維度,本質還是

    01揹包中的一維陣列,而不是01揹包中的二維陣列(此二維陣列有一維表示的是揹包的容量))。

    dp[i][j]表示最多有i0j1strs的最大子集的長度。

  2. 確定遞推公式

    • 當物品[i][j]裝不進揹包時,當前的dp[i][j] = 之前的dp[i][j]

    • 當物品[i][j]裝不進揹包時,可以選擇裝或不裝

      • 選擇不裝,當前的dp[i][j] = 之前的dp[i][j]

      • 選擇裝,當前的dp[i][j] = 之前的dp[i - 當前物品中0的個數][j - 當前物品中1的個數] + 1

    所以可以得到遞推公式: dp[i][j] = max (dp[i][j], dp[i - 當前物品中0的個數][j - 當前物品中1的個數] + 1)

  3. dp陣列的初始化

    一維01揹包類似。dp[0][0] = 0(揹包容量為0)。另外因為揹包問題中的物品價值都為正整數,必須保證取到最大值,所以其餘的dp[i][j]也都初始化為0

  4. 確定遍歷順序

    先遍歷物品,後遍歷揹包容量並且是從後向前遍歷。

C++

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        // 1.dp[i][j]表示最多有i個0和j個1的strs的最大子集的大小
        // 3.dp初始化:因為物品價值不會是負數,dp初始為0,保證遞推的時候dp[i][j]不會被初始值覆蓋。
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); // m是0的個數,n是1的個數
        // 首先遍歷物品,計算每個物品中0的個數和1的個數
        for(int k = 0; k < strs.size(); k++) {
            int zeroNum = 0, oneNum = 0;
            for (char c : strs[k]) {
                if (c == '0') {
                    zeroNum++;
                } else {
                    oneNum++;
                }
            }
            // 遍歷揹包容量(類似於一個揹包有兩個小包,第一個小包裝0,第二個小包裝1)
            for (int i = m; i >= zeroNum; i--) {
                for (int j = n; j >= oneNum; j--) {
                    // 2.遞推公式
                    dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
                }
            }
        }
        return dp[m][n];
    }
};

JavaScript

/**
 * @param {string[]} strs
 * @param {number} m
 * @param {number} n
 * @return {number}
 */
var findMaxForm = function(strs, m, n) {
    const dp = Array(m + 1);
    for (let i = 0; i < m + 1; i++) {
        dp[i] = Array(n + 1).fill(0);
    }
    // 遍歷物品
    for (const s of strs) {
        let zeroNum = 0,
            oneNum = 0;
        for (const c of s) {
            if (c === '0') {
                zeroNum++;
            } else {
                oneNum++;
            }
        }
        //遍歷揹包
        for (let i = m; i >= zeroNum; i--) {
            for (let j = n; j >= oneNum; j--) {
                dp[i][j] = Math.max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
            }
        }
    }
    return dp[m][n];
};
  • 時間複雜度:O(k*m*n),k是strs的大小,m是題目中要求的0的個數,n是題目要求的1的個數

  • 空間複雜度:O(m*n)