leetcode 2251 花期内花的数目(2023.9.28)

题目

给你一个下标从 0 开始的二维整数数组 flowers ,其中 flowers[i] = [starti, endi] 表示第 i 朵花的 花期 从 starti 到 endi (都 包含)。同时给你一个下标从 0 开始大小为 n 的整数数组 people ,people[i] 是第 i 个人来看花的时间。

请你返回一个大小为 n 的整数数组 answer ,其中 answer[i]是第 i 个人到达时在花期内花的 数目 。

1 <= flowers.length <= 5 * 1e4 flowers[i].length == 2 1 <= starti <= endi <= 1e9 1 <= people.length <= 5 * 1e4 1 <= people[i] <= 1e9

题解

这道题乍一看就是差分+前缀和,实际上我写完提交了才发现,区间的范围最大值是1e9,所以得考虑离散化的方案。

感谢房宝给的解法:因为已经提前知道了查询的内容,所以可以做离线,简单来说就是开一个map用来代替差分数组,map记为presum,然后开始处理区间之前,先初始化presum[person[i]] = 0 接下来是走正常的差分流程。 presum[l]++ presum[r + 1]–

最后按照key的大小来排序,求前缀和。因为已经初始化了presum[person[i]] = 0,所以求完前缀和之后presum[person[i]]就是答案。

func fullBloomFlowers(flowers [][]int, people []int) []int {
	max := 0
	for _, flower := range flowers {
		if flower[1] > max {
			max = flower[1]
		}
	}
	presum := make(map[int]int)

	for _, p := range people {
		presum[p] = 0
	}
	for _, flow := range flowers {
		if _, ok := presum[flow[0]]; ok {
			presum[flow[0]]++
		} else {
			presum[flow[0]] = 1
		}
	
		if _, ok := presum[flow[1] + 1]; ok {
			presum[flow[1] + 1]--
		} else {
			presum[flow[1] + 1] = -1
		}
	
	}
//	fmt.Println(presum)
	keys := make([]int, 0)
	for k, _ := range presum {
		keys = append(keys, k)
	}
	sort.Ints(keys)
	
	for i := 1; i < len(keys); i++{
		presum[keys[i]] = presum[keys[i]] + presum[keys[i - 1]] 
	}

//	fmt.Println(presum)
	res := make([]int, 0)
	for _, p := range people {
		res = append(res, presum[p])
	}
	return res
}

leetcode 947 移除最多的同行或同列石头 2023.09.27

题意

https://leetcode.cn/problems/most-stones-removed-with-same-row-or-column/

n 块石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。

如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。

给你一个长度为 n 的数组 stones ,其中 stones[i] = [xi, yi] 表示第 i 块石头的位置,返回 可以移除的石子 的最大数量。

 

示例 1:

输入:stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]] 输出:5 解释:一种移除 5 块石头的方法如下所示:

  1. 移除石头 [2,2] ,因为它和 [2,1] 同行。
  2. 移除石头 [2,1] ,因为它和 [0,1] 同列。
  3. 移除石头 [1,2] ,因为它和 [1,0] 同行。
  4. 移除石头 [1,0] ,因为它和 [0,0] 同列。
  5. 移除石头 [0,1] ,因为它和 [0,0] 同行。 石头 [0,0] 不能移除,因为它没有与另一块石头同行/列。 示例 2:

输入:stones = [[0,0],[0,2],[1,1],[2,0],[2,2]] 输出:3 解释:一种移除 3 块石头的方法如下所示:

  1. 移除石头 [2,2] ,因为它和 [2,0] 同行。
  2. 移除石头 [2,0] ,因为它和 [0,0] 同列。
  3. 移除石头 [0,2] ,因为它和 [0,0] 同行。 石头 [0,0] 和 [1,1] 不能移除,因为它们没有与另一块石头同行/列。 示例 3:

输入:stones = [[0,0]] 输出:0 解释:[0,0] 是平面上唯一一块石头,所以不可以移除它。

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/most-stones-removed-with-same-row-or-column 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1 <= stones.length <= 1000 0 <= xi, yi <= 1e4

题解

这道题是一个并查集的应用,但问题就在于,如何构建并查集?

主要目的是:让相同列或者相同行的石子处于同一个集合里。一开始思路是把每个石子的x和y放到同一个集合,但提交之后发现这行不通。一个反例就是 [1, 0], [0, 1] 这两个点是不同行且不同列的,如果单纯把x y放同一个集合的话,第一个点1 0一个集合,第二个点0 1一个集合,最终他们会组成一个集合。这就不对了。

这里学习了题解里最巧妙的地方:union(x + 10001, y),因为x和y的最大取值是1e4,所以让x+10001。这样就能保证,只要两个点的x值是相等的,它们+10001之后也相等,所以他们会落入同一个集合中。并且x的取值范围变成了10001~20001,与y不冲突,所以不会出现上面说的[0,1],[1,0]被加入同一个集合的情况。

另外,因为这道题的取值范围1e4,所以用map来代替并查集的数组会好一些。在本题中还收到另外的启发,集合的个数,可以记录下来。集合的个数=根的个数,一个元素成为了根,集合个数就+1,当一个元素被另外一个集合合并,它就不是根了,集合个数-1。

/*
 * @lc app=leetcode.cn id=2251 lang=golang
 *
 * [2251] 花期内花的数目
 */
package main

import (
	"fmt"
	"sort"
)

// @lc code=start
func fullBloomFlowers(flowers [][]int, people []int) []int {
	max := 0
	for _, flower := range flowers {
		if flower[1] > max {
			max = flower[1]
		}
	}
	presum := make(map[int]int)

	for _, p := range people {
		presum[p] = 0
	}
	for _, flow := range flowers {
		if _, ok := presum[flow[0]]; ok {
			presum[flow[0]]++
		} else {
			presum[flow[0]] = 1
		}
	
		if _, ok := presum[flow[1] + 1]; ok {
			presum[flow[1] + 1]--
		} else {
			presum[flow[1] + 1] = -1
		}
	
	}
//	fmt.Println(presum)
	keys := make([]int, 0)
	for k, _ := range presum {
		keys = append(keys, k)
	}
	sort.Ints(keys)
	
	for i := 1; i < len(keys); i++{
		presum[keys[i]] = presum[keys[i]] + presum[keys[i - 1]] 
	}

//	fmt.Println(presum)
	res := make([]int, 0)
	for _, p := range people {
		res = append(res, presum[p])
	}
	return res
}

// @lc code=end

func main() {
	flowers := [][]int{
		{1, 6},
		{3, 7},
		{9, 12},
		{4, 13},
	}
	people := []int{
		2, 3, 7, 11,
	}

	fmt.Println(fullBloomFlowers(flowers, people))
}