1.找到数组的中间位置(前缀和)
题目数据量很小,无脑暴力也能过。
func findMiddleIndex(nums []int) int {
pre := make([]int, len(nums))
pre[0] = nums[0]
for i := 1 ; i < len(nums) ; i++ {
pre[i] = pre[i - 1] + nums[i]
}
n := len(pre)
if pre[n - 1] - pre[0] == 0 {
return 0
}
for i := 1 ; i < len(pre) - 1 ; i++ {
if pre[n - 1] - pre[i] == pre[i - 1] {
return i
}
}
if pre[n - 2] == 0 {
return n - 1
}
return -1
}
2.找到所有的农场组 (dfs/bfs)
本质就是搜索手速题,需要把起点和终点存一下
func findFarmland(land [][]int) [][]int {
n := len(land)
m := len(land[0])
visited := make([][]bool, n)
for i := 0 ; i < len(visited) ; i++ {
visited[i] = make([]bool, m)
}
res := make([][]int, 0)
for i := 0 ; i < n ; i++ {
for j := 0 ; j < m ; j++ {
if !visited[i][j] && land[i][j] == 1 {
t := make([]int, 0)
t = append(t, i)
t = append(t, j)
getLand(visited, land, i, j, n, m, &t)
res = append(res, t)
}
}
}
return res
}
func getLand(visited [][]bool, land [][]int, x, y, n, m int, cur *[]int) {
if x < 0 || x >= n || y < 0 || y >= m || visited[x][y] || land[x][y] == 0 {
return
}
visited[x][y] = true
if (x == n - 1 && y == m - 1) || (x + 1 < n && land[x + 1][y] == 0 && y + 1 < m && land[x][y+ 1] == 0) ||
(x == n - 1 && y + 1 < m && land[x][y+ 1] == 0) || (y == m - 1 && x + 1 < n && land[x + 1][y] == 0) {
*cur = append(*cur, x, y)
}
getLand(visited, land, x, y + 1, n, m, cur)
getLand(visited, land, x - 1, y, n, m, cur)
getLand(visited, land, x + 1, y, n, m, cur)
getLand(visited, land, x, y - 1, n, m, cur)
}
3.树上的操作(模拟)
没搞过竞赛,不知道那些烧操作,就老老实实模拟吧,思路不难都能想到。
type LockingTree struct {
m map[int]*node
}
type node struct {
val int
parent *node
children []*node
locked int
user int
}
func Constructor(parent []int) LockingTree {
n := len(parent)
all := make([]*node, n)
m := make(map[int]*node)
for i := 0 ; i < n ; i++ {
all[i] = &node{
val: i,
parent: nil,
children: make([]*node, 0),
locked: -1,
user: -1,
}
m[i] = all[i]
}
for i := 1 ; i < n ; i++ {
all[parent[i]].children = append(all[parent[i]].children, all[i])
all[i].parent = all[parent[i]]
}
l := LockingTree{
m: m,
}
return l
}
func (this *LockingTree) Lock(num int, user int) bool {
if this.m[num].locked == -1 {
this.m[num].locked = 1
this.m[num].user = user
return true
}
return false
}
func (this *LockingTree) Unlock(num int, user int) bool {
if this.m[num].locked == 1 && this.m[num].user == user {
this.m[num].locked = -1
this.m[num].user = -1
return true
}
return false
}
func (this *LockingTree) Upgrade(num int, user int) bool {
// 当前节点没有上锁
// 没有任何上锁的祖先节点
cur := this.m[num]
for cur != nil {
if cur.locked == 1 {
return false
}
cur = cur.parent
}
hasLock := false
q := make([]*node, 0)
q = append(q, this.m[num])
needLock := make([]*node, 0)
for len(q) > 0 {
head := q[0]
q = q[1:]
if head.locked == 1 {
hasLock = true
needLock = append(needLock, head)
}
for i := 0 ; i < len(head.children) ; i++ {
q = append(q, head.children[i])
}
}
if !hasLock {
return false
}
this.Lock(num, user)
for i := 0 ; i < len(needLock) ; i++ {
this.Unlock(needLock[i].val, needLock[i].user)
}
return true
}
4.好子集的数目 (状压dp+快速幂)
好气,思路就差一点点,还是做得太少了...首先最重要的是1<=num[i]<=30,所以30以内的质数就10个,选或不选一共就1024个状态,所以考虑状压dp,2,3,5,7,11...29这里针对一个num[i]而已,例如6=23,则说明6对应的状态为000...0011=3.所以首先算一下1-30对应的状态,特别的例如4=22其本身就重复,则不参与讨论。接着统计1-30每个数出现了多少次记作num[i],遍历这30个数的状态,针对其中一个状态,需要与所有1024个状态相&,如果答案为0,则可以合并。某个状态j的子集数记作sub[j],当前数字i的状态k的子集数为num[i], sub[j + k] = (sub[j + k] + sub[j] * num[i] % mod) % mod,简单解释一下就是j状态的子集数为sub[j],当前的k&j=0,所以这两个集合可以合并,多出来的个数为sub[j]*num[i]。此外,1作为一个特殊的数字,需要进行单独讨论。显然,只包含1的子集可以添加到满足条件的任何一个子集中去,所以求出只包含1的子集的个数s(选1或者不选1一个2^(1的个数)),最后遍历所有的状态,求出所有满足条件的子集与s相乘就是最终答案。(大佬代码搬运工)
const mod int = 1e9 + 7
func numberOfGoodSubsets(nums []int) int {
num := make([]int, 31)
for i := 0 ; i < len(nums) ; i++ {
num[nums[i]]++
}
// 每一种状态下有多少个好子集
sub := make([]int, 1024)
// 1-30之间最多只有10个质数 考虑状态压缩表示
// 2 表示为00...001
// 首先将1-30质因数分解,比如6=2*3那6的状态就表示为00...0011=3
// 各个数字的状态4=2*2本身就重复所以直接为0
good := []int{0, 0, 1, 2, 0, 4, 3, 8, 0, 0, 5, 16, 0, 32, 9, 6, 0, 64, 0, 128, 0, 10, 17, 256, 0, 0, 33, 0, 0, 512, 7}
for i := 2 ; i <= 30 ; i++ {
if good[i] > 0 && num[i] > 0 {
// 当前数字的状态
k := good[i]
for j := 1023 ; j >= 0 ; j-- {
// 不重复的质数
if sub[j] > 0 && j & k == 0 {
sub[j + k] = (sub[j + k] + sub[j] * num[i] % mod) % mod
}
}
sub[k] += num[i]
}
}
res := 0
for i := 0 ; i < len(sub) ; i++ {
res = (res + sub[i]) % mod
}
return pow(2, num[1]) * res % mod
}
func pow(x int, n int) int {
if n == 0 {
return 1
}
if n == 1 {
return x
}
tem := pow(x, n >> 1)
res := tem * tem % mod
if n % 2 == 0 {
return res
} else {
return res * x % mod
}
}