leetcode之947移除最多的同行或者同列石头Golang

题目描述

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

每次 move 操作都会移除一块所在行或者列上有其他石头存在的石头。

请你设计一个算法,计算最多能执行多少次 move 操作?

示例 1:

输入:stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
输出:5

示例 2:

输入:stones = [[0,0],[0,2],[1,1],[2,0],[2,2]]
输出:3

示例 3:

输入:stones = [[0,0]]
输出:0

提示:

  1. 1 <= stones.length <= 1000
  2. 0 <= stones[i][j] < 10000

算法描述

本题的解法就是利用并查集中的方式,同一个集合中的石头,某一个石头至少能够找到一个石头他们的横坐标或者纵坐标相等,所以如果我们消除同一个并查集中的石头的时候,一定能够消除到最后只剩下一个石头。

思路如下:

  • 首先获取第一块石头,作为一个单独的集合,然后遍历剩下的集合
    • 如果这个石头和前面的某个集合中的某个石头的横坐标或者纵坐标相等,那么就将这个石头加入那个集合,并且记录这个石头加入的所有的并查集的下标
      • 将同一个石头加入的所有的并查集合并成一个并查集
    • 如果这个石头和前面的任何一个并查集的所有石头的横坐标和纵坐标都不相等,那么就创建一个新的并查集,这个并查集就一个元素,也就是当前遍历到的石头
  • 用所有石头的数量减去并查集的数量,就是移除石头的数量,也就是移除的次数

代码

func removeStones(stones [][]int) int {
	if len(stones) == 0 {
		return 0
	}
	res := make([][][]int, 0)
	firstSet := make([][]int, 0)
	firstSet = append(firstSet, stones[0])
	res = append(res, firstSet)
	// 然后将后面的石头加入前面的集合中,如果不能加入任意集合,那么就创建新的集合
	for index := 1; index < len(stones); index++ {
		createFlag := true
		insertSetIndexs := make([]int, 0)
		for curIndex, curSet := range res {
			for _, curStone := range curSet {
				// 比较当前集合中石头与待选择石头的横纵坐标是否相等
				if stones[index][0] == curStone[0] || stones[index][1] == curStone[1] {
					res[curIndex] = append(res[curIndex], stones[index])
					createFlag = false
					insertSetIndexs = append(insertSetIndexs, curIndex)
					break
				}
			}
		}
		// 如果一个石头同时处于多个并查集中,那么这些并查集就可以合并成一个
		if !createFlag {
			for i := 1; i < len(insertSetIndexs); i++ {
				res[insertSetIndexs[0]] = append(res[insertSetIndexs[0]], res[insertSetIndexs[i]]...)
				res = append(res[:insertSetIndexs[i]], res[insertSetIndexs[i]+1:]...)
			}
		}
		if createFlag {
			newSet := make([][]int, 0)
			newSet = append(newSet, stones[index])
			res = append(res, newSet)
		}
	}
	return len(stones) - len(res)
}
posted @ 2020-10-27 23:39  胖胖咩  阅读(161)  评论(0)    收藏  举报