Skip to content

Latest commit

 

History

History
135 lines (109 loc) · 3.77 KB

File metadata and controls

135 lines (109 loc) · 3.77 KB

没参加。

2437. 有效时间的数目(go 的 continue label)

https://leetcode.cn/problems/number-of-valid-clock-times/solution/

这里灵佬使用 go 的 continue label 是否漂亮。

func count(time string, limit int) (ans int) {
next:
	for i := 0; i < limit; i++ {
		for j, c := range fmt.Sprintf("%02d", i) {  // 检验是否匹配
			if time[j] != '?' && byte(c) != time[j] {
				continue next
			}
		}
		ans++
	}
	return
}

func countTime(time string) int {
	return count(time[:2], 24) * count(time[3:], 60)
}

注意:

  • go 的 continue label 会触发循环的增量条件并且做判断

2439. 最小化数组中的最大值(二分/贪心)

https://leetcode.cn/problems/minimize-maximum-of-array/

见到“最大最小值”,我都想不到二分了。

class Solution {
public:
    int minimizeArrayValue(vector<int>& nums) {
        int n = nums.size();
        int maxv = *max_element(nums.begin(), nums.end());
        int l = 0, r = maxv;

        auto check = [&](int x) -> bool {
            long extra = 0;
            for (int i = n - 1; i > 0; -- i)
                extra = max(nums[i] - x + extra, 0L);
            return nums[0] + extra <= x;
        };

        while (l < r)
        {
            int mid = l + r >> 1;
            if (check(mid)) r = mid;
            else l = mid + 1;
        }
        return l;
    }
};

灵佬还有另一种贪心思路。

// nums[0] 决定下限
// nums[1] 若大于 nums[0] ,则可以匀一匀
// nums[2] 与 nums[1] 同理,前三个匀一匀

func minimizeArrayValue(nums []int) (ans int) {
	s := 0
	for i, x := range nums {
		s += x
		ans = max(ans, (s+i)/(i+1))  // 上取整
	}
	return
}

func max(a, b int) int { if b > a { return b }; return a }

2440. 创建价值相同的连通块(枚举+精妙dfs)

https://leetcode.cn/problems/create-components-with-same-value/

// 见到本题我想的是“如何切”
// 实际上,重点在于“能不能切为 x 块”,如何切不重要
// 于是我把自己局限在了如何搜索,切哪里,其实这不是重点
class Solution {
public:
    int componentValue(vector<int> &nums, vector<vector<int>> &edges) {
        vector<vector<int>> g(nums.size());
        for (auto &e : edges) {
            int x = e[0], y = e[1];
            g[x].push_back(y);
            g[y].push_back(x);
        }

        // 这个 dfs 讨论得很精妙
        // 如果子树恰好切成 target ,则返回 0 ,不参与子树之上的 sum
        int target;
        function<int(int, int)> dfs = [&](int x, int fa) {
            int sum = nums[x]; // 价值
            for (int y : g[x])
                if (y != fa) {
                    int res = dfs(y, x);
                    if (res < 0) return -1;  // 子树不能切成比 target 小
                    sum += res;
                }
            if (sum > target) return -1;
            return sum < target ? sum : 0;  // 恰好切成 target 则返回 0
        };

        int total = accumulate(nums.begin(), nums.end(), 0);
        int mx = *max_element(nums.begin(), nums.end());
        for (int i = total / mx;; --i)  // 尝试切成 i 块
            if (total % i == 0) {
                target = total / i;
                if (dfs(0, -1) == 0) return i - 1;  // 切成 i 则需要去掉 i-1 条边
            }
    }
};