LeetCode #160 周賽題解(暴力 + 格雷碼 + DFS + 矩陣最小正方形剖分)

LeetCode #160 周賽


leetcode 題目不同於其他 oj 是黑盒測試,要提交完整可運行代碼,而是完善封裝好題目給出的函數即可

1237、找出給定方程的正整數解

題目:給出函數 f(x,y)f(x, y),和整數 zz。求所有滿足 f(x,y)=zf(x, y) = z(x,y)(x, y)

分析:由於 x,yx, y 範圍 1e31e3 ,直接暴力枚舉。

class Solution {
public:
    vector<vector<int>> findSolution(CustomFunction& customfunction, int z) {
        vector<vector<int>> v;
        for (int i = 1; i <= 1e3; i++) {
            for (int j = 1; j <= 1e3; j++) {
                if (customfunction.f(i, j) == z) {
                    v.push_back({i, j});
                }
            }
        }
        return v;
    }
};

1238、循環碼排列

題目: 給出 n,startn, start,要求輸出以 startstart 開頭的 02n110 到 2^{n-1}-1 的排列,且排列要滿足相鄰兩數的二進制表示相差一位

分析:格雷碼(循環二進制單位距離碼)是任意兩個相鄰數的代碼只有一位二進制數不同的編碼,。
在這裏插入圖片描述
①、通過模擬(上下鏡射加新位):

class Solution {
public:
    vector<int> circularPermutation(int n, int start) {
        vector<int> v = {0, 1}, res;
        for (int i = 2; i <= n; i++) {
            for (int j = v.size() - 1; j >= 0; j--) {
                v.push_back(v[j] + (1 << (i-1)));       
            }
        }
        int pos = find(v.begin(), v.end(), start) - v.begin();
        int m = v.size();
        while (m--) {
            res.push_back(v[pos]); pos = (pos + 1) % v.size();
        }    
        return res;
    }
};

在這裏插入圖片描述
②、通過分析二進制表示:

class Solution {
public:
    vector<int> circularPermutation(int n, int start) {
        vector<int> v, res;
        int pos;
        for (int i = 0; i < 1 << n; i++) {
            v.push_back(i ^ (i >> 1));
            if (v.back() == start) pos = i;
        }
        int m = v.size();
        while (m--) {
            res.push_back(v[pos]); pos = (pos + 1) % v.size();
        }
        return res;
    }
};

1239、串聯字符串的最大長度

題目:給一個字符串數組 arrarr,選擇數組 arrarr 的子序列組成新的字符串 ss,但 ss 種不能有重複字符,求 ss 最大長度。

分析:暴力 dfsdfs 每一位選或者不選,不過要加上剪枝:對於每一位,只有加上後沒有重複字符纔會繼續。

class Solution {
public:
    int dfs(vector<string>& arr, string str, int pos, int* vis) {
        if (pos == arr.size()) return str.size();
        int ans = dfs(arr, str, pos + 1, vis);    // 不選當前位置
        int tmp[30];
        for (int i = 0; i < 30; i++) tmp[i] = vis[i];	// 遞歸時會改變指針,所以要備份
        for (auto x : arr[pos]) {                 // 選當前位置,但不能有重複
            if (tmp[x - 'a'] == 1) return ans;
            else tmp[x - 'a'] = 1;
        }
        return max(dfs(arr, str + arr[pos], pos + 1, tmp), ans);	// 取最大
    }
    
    int maxLength(vector<string>& arr) {
        int vis[30] = {0};
        return dfs(arr, "", 0, vis);
    }
};

1240、鋪瓷磚

題目:給你 (n,m)(n, m) 矩陣,讓你分割成若干正方形,求最小分割數。 n,m<13n, m < 13

分析:矩陣最小正方形剖分

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章