2022-6-22 道路的最大总重要性,最长快乐字符串,为高尔夫比赛砍树,分割数组为连续子序列

1. 道路的最大总重要性

给你一个整数 n ,表示一个国家里的城市数目。城市编号为 0n - 1

给你一个二维整数数组 roads ,其中 roads[i] = [ai, bi] 表示城市 aibi 之间有一条 双向 道路。

你需要给每个城市安排一个从 1n 之间的整数值,且每个值只能被使用 一次 。道路的 重要性 定义为这条道路连接的两座城市数值 之和

请你返回在最优安排下,所有道路重要性 之和 最大 为多少。

Example 1

输入:n = 5, roads = [[0,1],[1,2],[2,3],[0,2],[1,3],[2,4]]
输出:43

Example 2

输入:n = 5, roads = [[0,3],[2,4],[1,3]]
输出:20

Constraints:

  • 2 <= n <= 5 * 10^4
  • 1 <= roads.length <= 5 * 10^4
  • roads[i].length == 2
  • 0 <= ai, bi <= n - 1
  • ai != bi
  • 没有重复道路。

代码 [贪心]

class Solution {
public:
    long long maximumImportance(int n, vector<vector<int>> &roads) {
        vector<int> nums(n, 0);
        for (auto &road:roads) ++nums[road[0]], ++nums[road[1]];
        sort(nums.begin(), nums.end());
        long long result = 0, cnt = 1;
        for (int num:nums) result += cnt++ * num;
        return result;
    }
};

2. 最长快乐字符串

A string s is called happy if it satisfies the following conditions:

  • s only contains the letters 'a', 'b', and 'c'.
  • s does not contain any of "aaa", "bbb", or "ccc" as a substring.
  • s contains at most a occurrences of the letter 'a'.
  • s contains at most b occurrences of the letter 'b'.
  • s contains at most c occurrences of the letter 'c'.

Given three integers a, b, and c, return the longest possible happy string. If there are multiple longest happy strings, return any of them. If there is no such string, return the empty string "".

A substring is a contiguous sequence of characters within a string.

Example 1

Input: a = 1, b = 1, c = 7
Output: "ccaccbcc"
Explanation: "ccbccacc" would also be a correct answer.

Example 2

Input: a = 7, b = 1, c = 0
Output: "aabaa"
Explanation: It is the only correct answer in this case.

Constraints:

  • 0 <= a, b, c <= 100
  • a + b + c > 0

代码 [贪心]

class Solution {
public:
    string longestDiverseString(int a, int b, int c) {
        string ans;
        vector<tuple<int, char>> arr = {{a, 'a'}, {b, 'b'}, {c, 'c'}};
        while (get<0>(arr[0]) || get<0>(arr[1]) || get<0>(arr[2])) {
            sort(arr.begin(), arr.end());
            auto&[cnt2, ch2]=arr[2];
            auto&[cnt1, ch1]=arr[1];
            if (ans.size() < 2 || ans.back() != ch2 || ans[ans.size() - 2] != ch2) {
                ans.push_back(ch2);
                --cnt2;
            } else if (cnt1 != 0) {
                ans.push_back(ch1);
                --cnt1;
            } else {
                return ans;
            }
        }
        return ans;
    }
};

3. 为高尔夫比赛砍树

You are asked to cut off all the trees in a forest for a golf event. The forest is represented as an m x n matrix. In this matrix:

  • 0 means the cell cannot be walked through.
  • 1 represents an empty cell that can be walked through.
  • A number greater than 1 represents a tree in a cell that can be walked through, and this number is the tree’s height.

In one step, you can walk in any of the four directions: north, east, south, and west. If you are standing in a cell with a tree, you can choose whether to cut it off.

You must cut off the trees in order from shortest to tallest. When you cut off a tree, the value at its cell becomes 1 (an empty cell).

Starting from the point (0, 0), return the minimum steps you need to walk to cut off all the trees. If you cannot cut off all the trees, return -1.

You are guaranteed that no two trees have the same height, and there is at least one tree needs to be cut off.

Example 1

Input: forest = [[1,2,3],[0,0,4],[7,6,5]]
Output: 6

Example 2

Input: forest = [[1,2,3],[0,0,0],[7,6,5]]
Output: -1

Constraints:

  • m == forest.length
  • n == forest[i].length
  • 1 <= m, n <= 50
  • 0 <= forest[i][j] <= 10^9

代码 1 [排序+BFS 超时]

class Solution {
private:
    static constexpr pair<int, int> DIR[4]{{-1, 0}, {1,  0}, {0,  -1}, {0,  1}};
    bool visited[50][50];

    int bfs(const vector<vector<int>> &forest, int x0, int y0, int x1, int y1) {
        memset(visited, 0, sizeof visited);
        auto check = [&](int x, int y) {
            return x >= 0 && y >= 0 && x < forest.size() && y < forest[0].size() && forest[x][y] != 0 && !visited[x][y];
        };
        queue<pair<int, int>> q;
        int path = 0;
        q.emplace(x0, y0);
        while (!q.empty()) {
            int size = q.size();
            while (size--) {
                auto[xc, yc]=q.front();
                visited[xc][yc] = true;
                q.pop();
                if (xc == x1 && yc == y1) return path;
                for (int i = 0; i < 4; ++i) {
                    auto[dx, dy]=DIR[i];
                    if (check(xc + dx, yc + dy)) q.emplace(xc + dx, yc + dy);
                }
            }
            path++;
        }
        return -1;
    }

public:
    int cutOffTree(const vector<vector<int>> &forest) {
        vector<int> tree;
        for (int i = 0; i < forest.size(); ++i) {
            for (int j = 0; j < forest[0].size(); ++j) {
                if (forest[i][j] > 1) tree.push_back((i << 6) | j);
            }
        }
        sort(tree.begin(), tree.end(), [&](int lo, int hi) {
            return forest[lo >> 6][lo & 63] < forest[hi >> 6][hi & 63];
        });
        int p0 = 0, cnt = 0;
        for (auto pn:tree) {
            int cost = bfs(forest, p0 >> 6, p0 & 63, pn >> 6, pn & 63);
            if (cost == -1) return -1;
            cnt += cost;
            p0 = pn;
        }
        return cnt;
    }
};

4. 分割数组为连续子序列

给你一个按升序排序的整数数组 num(可能包含重复数字),请你将它们分割成一个或多个长度至少为 3 的子序列,其中每个子序列都由连续整数组成。

如果可以完成上述分割,则返回 true ;否则,返回 false

Example 1

输入: [1,2,3,3,4,5]
输出: True
解释:
你可以分割出这样两个连续子序列 : 
1, 2, 3
3, 4, 5

Constraints:

  • 1 <= nums.length <= 10000

代码 1 [哈希]

class Solution {
private:
    using pue = priority_queue<int, vector<int>, greater<>>;
public:
    bool isPossible(vector<int> &nums) {
        unordered_map<int, pue> mp;
        for (auto x:nums) {
            if (!mp.count(x)) mp[x] = pue();
            if (mp.count(x - 1)) {
                int prevLength = mp[x - 1].top();
                mp[x - 1].pop();
                if (mp[x - 1].empty()) mp.erase(x - 1);
                mp[x].push(prevLength + 1);
            } else {
                mp[x].push(1);
            }
        }
        return all_of(mp.begin(), mp.end(), [](const pair<int, pue> &val) {
            return val.second.top() >= 3;
        });
    }
};

代码 2 [贪心]

class Solution {
public:
    bool isPossible(vector<int> &nums) {
        unordered_map<int, int> countMap, endMap;
        for (auto x:nums) ++countMap[x];
        for (auto x:nums) {
            if (countMap[x]-- > 0) {
                if (endMap[x - 1] > 0) {
                    --endMap[x - 1], ++endMap[x];
                } else {
                    if (countMap[x + 1] > 0 && countMap[x + 2] > 0) {
                        --countMap[x + 1], --countMap[x + 2], ++endMap[x + 2];
                    } else {
                        return false;
                    }
                }
            }
        }
        return true;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值