一次不错的练习题1

  1. 找树左下角的值https://leetcode-cn.com/problems/find-bottom-left-tree-value/
    // 经典广搜
    class Solution {
    public:
        int findBottomLeftValue(TreeNode* root) {
            queue<TreeNode*> que;
            que.push(root);
            vector<int> cnt;
    
            while (!que.empty()) {
                cnt.clear();
                int len = que.size();
    
                while (len--) {
                    TreeNode* node = que.front();
                    cnt.push_back(node->val);
                    que.pop();
                    if (node->left) que.push(node->left);
                    if (node->right) que.push(node->right);
                }
            }
            return cnt[0];
        }
    };
  1. 课程表https://leetcode-cn.com/problems/course-schedule/
    // 拓扑排序模板题
    // dfs 所有节点分为三个状态 0 未访问 1 访问未回溯,2 访问且回溯
    // 如果dfs的节点访问到1,说明有环,返回false
    // 访问到节点v为2,当前节点不会影响v的拓扑结构 因此不用对齐做任何操作
    class Solution {
    public:
        bool canFinish(int num, vector<vector<int>>& prerequisites) {
            vector<vector<int>> edge(num);
            vector<int> indegree(num, 0);
            vector<int> vis(num, 0);
    
            for (auto& p : prerequisites) {
                edge[p[1]].push_back(p[0]);
                indegree[p[0]]++;
            }
    
            vector<int> cnt;
            for (int i = 0; i < num; i++) {
                if (indegree[i] == 0) {
                    if (!dfs(edge, i, vis, cnt)) {
                        return false;
                    }
                }
            }
            if (cnt.size() < num) return false;
            reverse(cnt.begin(), cnt.end());
            return true;
        }
    
        bool dfs(vector<vector<int>>& edge, int course, vector<int>& vis, vector<int>& cnt) {
            if (vis[course] == 2) return true;
            if (vis[course] == 1) return false;
    
            vis[course] = 1;
            for (int i = 0; i < edge[course].size(); i++) {
                if (!dfs(edge, edge[course][i], vis, cnt)) {
                    return false;
                }
            }
            vis[course] = 2;
            cnt.push_back(course);
            return true;
        }
    };
    
    
    // bfs 记录入度,每次弹出节点减少相邻节点的入度,取入度为0的节点加入队列
    class Solution {
    public:
        bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
            vector<int> indegree(numCourses, 0);
            vector<vector<int>> edge(numCourses);
    
            for (auto& pre: prerequisites) {
                edge[pre[1]].push_back(pre[0]);
                indegree[pre[0]]++;
            }
    
            queue<int> que;
            for (int i = 0; i < numCourses; i++) {
                if (indegree[i] == 0) {
                    que.push(i);
                }
            }
    
            int cnt = 0;
            while (!que.empty()) {
                int item = que.front();
                que.pop();
                cnt++;
    
                for (int i = 0; i < edge[item].size(); i++) {
                    if (--indegree[edge[item][i]] == 0) {
                        que.push(edge[item][i]);
                    }
                }
            }
    
            return cnt == numCourses;
        }
    };
  1. 查找和最小的K对数字https://leetcode-cn.com/problems/find-k-pairs-with-smallest-sums/
    // 类似于双指针
    class Solution {
    public:
        vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {
            if (nums1.empty() || nums2.empty() || k <= 0) return {};
    
            auto cmp = [&nums1, &nums2](pair<int, int> a, pair<int, int> b) {
                return nums1[a.first] + nums2[a.second] > nums1[b.first] + nums2[b.second];
            };
    
            vector<vector<int>> ans;
            priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pque(cmp);
            // 先在优先级队列里放入nums1[i] 和 nums2[0]组成的数,
            for (int i = 0; i < nums1.size() && i < k; i++) {
                pque.emplace(i, 0);
            }
    
            while (k-- && !pque.empty()) {
                // 当前出队的为最小的组合,a已经放入了,此时a可以匹配到的次小组合为[a, b + 1]
                auto& [a, b] = pque.top();
                ans.push_back({nums1[a], nums2[b]});
                if (b + 1 < nums2.size()) {
                    pque.emplace(a, b + 1);
                }
                pque.pop();
            }
            return ans;
        }
    };
  1. 装包裹的最小浪费空间https://leetcode-cn.com/problems/minimum-space-wasted-from-packaging/
    // 反向思考,遍历当前的供应商,二分计算当前箱子可以放入的包裹,如果可以放入全部的包裹计算结果
    class Solution {
    public:
        using ull = unsigned long long;
        static constexpr ull mod = 1e9 + 7;
        int minWastedSpace(vector<int>& packages, vector<vector<int>>& boxes) {
            sort(packages.begin(), packages.end());
            ull sum = accumulate(packages.begin(), packages.end(), 0LL);
            ull cnt, vis;
            ull ans = LLONG_MAX;
    
            for (auto& item : boxes) {
                cnt = vis = 0;
                sort(item.begin(), item.end());
                for (auto& box : item) {
                    auto p = upper_bound(packages.begin(), packages.end(), box) - packages.begin();
                    if (p < vis) continue;
                    else {
                        cnt += (p - vis) * box;
                        vis = p;
                    }
                    if (p == packages.size()) break;
                }
                if (vis == packages.size())
                    ans = min(ans, cnt - sum);
            }
            return ans == LLONG_MAX ? -1 : ans % mod;
        }
    };
posted @ 2021-11-26 11:53  Wang~ze君  阅读(24)  评论(0)    收藏  举报