Weekly Contest 123

注册了比赛,被叫出去跟朋友喝酒了。幸亏这场没玩,要不要降分了,这几天喝酒喝的脑袋傻了,今天才补下这套题。调整下状态,准备回京务工了。

1. Add to Array-Form of Integer

解题思路:模拟下高精度加法即可。
实现代码

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

func reverseArr(a []int) {
	if len(a) == 0 {
		return
	}
	for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
		a[i], a[j] = a[j], a[i]
	}
}

func addToArrayForm(A []int, K int) []int {
	reverseArr(A)
	B := []int{}
	for K > 0 {
		B = append(B, K%10)
		K /= 10
	}
	C := make([]int, maxInt(len(A), len(B)))
	var a, b, c int
	for i := 0; i < len(C); i++ {
		a = 0
		if i < len(A) {
			a = A[i]
		}
		b = 0
		if i < len(B) {
			b = B[i]
		}
		C[i] = (a + b + c) % 10
		c = (a + b + c) / 10
	}
	if c > 0 {
		C = append(C, c)
	}
	reverseArr(C)
	return C
}
2. Satisfiability of Equality Equations

解题思路:由于相等关系具有传递性,因此我们可以利用并查集维护相等关系的集合。对于 a != b的情况, 如果 ab 原先是相等的, 则表示存在矛盾条件.
实现代码:

func initSet(p []int) {
	for i := range p {
		p[i] = -1
	}
}

func findSet(x int, p []int) int {
	if p[x] < 0 {
		return x
	}
	p[x] = findSet(p[x], p)
	return p[x]
}

func unionSet(x, y int, p []int) bool {
	p1 := findSet(x, p)
	p2 := findSet(y, p)
	if p1 == p2 {
		return true
	}
	p[p1] += p[p2]
	p[p2] = p1
	return false
}

func equationsPossible(equations []string) bool {
	if len(equations) == 0 {
		return true
	}
	p := make([]int, 40)
	initSet(p)
	for i := range equations {
		if equations[i][1] == '=' {
			unionSet(int(equations[i][0]-'a'), int(equations[i][3]-'a'), p)
		}
	}
	for i := range equations {
		if equations[i][1] == '!' {
			if findSet(int(equations[i][0]-'a'), p) == findSet(int(equations[i][3]-'a'), p) {
				return false
			}
		}
	}
	return true
}
3. Broken Calculator

解题思路: 不要写 bfs 肯定挂, 这题需要贪心来搞. 具体可以参考这篇文章 https://leetcode.com/articles/broken-calculator/
实现代码:

func brokenCalc(X int, Y int) int {

	if X >= Y {
		return X - Y
	}

	ans := 0
	for Y > X {
		if Y%2 == 0 {
			Y /= 2
		} else {
			Y++
		}
		ans++
	}
	return ans + X - Y
}
4. Subarrays with K Different Integers

解题思路: 求解对于每一个位置 iA[i]为结尾的不同数字恰好为 K 的方案数, 则总的方案数为 SUM(i). 对于每个位置 i , 存在 k 属于某个区间[l,r]使得 Ak ... Ai恰好存在 K个不同的数字; 另外对于 j > i, 则其对应的区间[lj, rj][li, ri]存在如下关系: li <= lj && ri <= rj && lj <= rj,因为[i+1, j]区间内可能引入了新的元素嘛。由此可以 lr 随着 i 的增大是单调递增的。因此,每次加入新的元素 A[i],只需要动态调整下 [li, ri] 即可,总的复杂度为O(N).
实现代码:

type Stat struct {
	cnt  int
	cmap map[int]int
}

func NewStat() *Stat {
	return &Stat{
		cnt:  0,
		cmap: map[int]int{},
	}
}

func (st *Stat) Add(x int) {

	if _, ok := st.cmap[x]; !ok {
		st.cmap[x] = 1
		st.cnt++
		return
	}

	st.cmap[x]++
}

func (st *Stat) Del(x int) {
	if _, ok := st.cmap[x]; !ok {
		return
	}
	st.cmap[x]--
	if st.cmap[x] == 0 {
		delete(st.cmap, x)
		st.cnt--
	}
}

func (st *Stat) Count() int {
	return st.cnt
}

func subarraysWithKDistinct(A []int, K int) int {

	if len(A) == 0 {
		return 0
	}

	var (
		res int
		l   int
		r   int
		st1 = NewStat()
		st2 = NewStat()
	)

	l, r = 0, 0
	for i := range A {

		st1.Add(A[i])
		st2.Add(A[i])

		for st1.Count() > K {
			st1.Del(A[l])
			l++
		}

		for st2.Count() >= K {
			st2.Del(A[r])
			r++
		}

		res += r - l
	}
	return res
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值