赛后总结:数学分析能力还是太差,这点抓紧拾起数学一些相关的知识点,新的一年希望有所突破吧。D 题赛后才想明白,如果这块知识点熟悉的话,也是一道纯秒题。新的一年在工作的同时,不断提升自己的算法能力吧。加油吧,老人。
1. String Without AAA or BBB
解题思路:构造即可
func strWithout3a3b(A int, B int) string {
if A == 0 && B == 0 {
return ""
}
var res []byte
for i := 0; i < minInt(A, B); i++ {
if A > B && i < A-B {
res = append(res, 'a')
res = append(res, 'a')
res = append(res, 'b')
} else if B > A && i < B-A {
res = append(res, 'b')
res = append(res, 'b')
res = append(res, 'a')
} else {
res = append(res, 'a')
res = append(res, 'b')
}
}
if A > B {
for i := 0; i < A-2*B; i++ {
res = append(res, 'a')
}
} else if B > A {
for i := 0; i < B-2*A; i++ {
res = append(res, 'b')
}
}
return string(res)
}
2. Time Based Key-Value Store
解题思路:由于 set 操作是严格按照 timestamp 升序进行的,因此我们只需要按照 key 分类存储,get 时候二分查找即可。这道题熟悉了 go 中 sort.Search 的用法,比赛的时候卡了一下。。。
type Node struct {
timestamp int
val string
}
type TimeMap struct {
db map[string][]Node
is map[string]struct{}
}
/** Initialize your data structure here. */
func Constructor() TimeMap {
return TimeMap{
db: map[string][]Node{},
is: map[string]struct{}{},
}
}
func (this *TimeMap) Set(key string, value string, timestamp int) {
this.db[key] = append(this.db[key], Node{timestamp, value})
this.is[key] = struct{}{}
}
func (this *TimeMap) Get(key string, timestamp int) string {
if _, ok := this.is[key]; !ok {
return ""
}
if this.db[key][0].timestamp > timestamp {
return ""
}
// 加深了 golang 中 对 sort.Search 二分查找的使用
// 返回最小的满足条件的 idx
idx := sort.Search(len(this.db[key]), func(i int) bool {
return this.db[key][i].timestamp > timestamp
})
idx--
return this.db[key][idx].val
}
3. Minimum Cost For Tickets
解题思路:简单动态规划。
const (
inf = 0x3f3f3f3f
maxn = 400
)
func minInt(a, b int) int {
if a < b {
return a
}
return b
}
func mincostTickets(days []int, costs []int) int {
n := len(days)
if n == 0 {
return 0
}
dp := [maxn][3]int{}
dp[0][0] = costs[0]
dp[0][1] = costs[1]
dp[0][2] = costs[2]
for i := 1; i < n; i++ {
dp[i][0] = costs[0] + minInt(minInt(dp[i-1][0], dp[i-1][1]), dp[i-1][2])
j := i
for j >= 0 && days[j] >= days[i]-6 {
j--
}
if j < 0 {
dp[i][1] = costs[1]
} else {
dp[i][1] = costs[1] + minInt(minInt(dp[j][0], dp[j][1]), dp[j][2])
}
j = i
for j >= 0 && days[j] >= days[i]-29 {
j--
}
if j < 0 {
dp[i][2] = costs[2]
} else {
dp[i][2] = costs[2] + minInt(minInt(dp[j][0], dp[j][1]), dp[j][2])
}
}
return minInt(minInt(dp[n-1][0], dp[n-1][1]), dp[n-1][2])
}
4. Triples with Bitwise AND Equal To Zero
解题思路:这题赛后才想明白的,果真是弱。。。这题直接求 A[i] & A[j] & A[k] = 0
的方案数比较困难,我们尝试换种思路。三元组的总方案数为 n^3
,求解 A[i] & A[j] & A[j] > 0
的方案数比较容易。题目中输入元素的取值范围为 0 <= A[i] < 2^16
,因此对于 A[i] & A[j] & A[k] > 0
的结果肯定在[1,(1<<16)-1]
区间内。假设 Bi
表示 A[i] & A[j] & A[j]
结果的第i
位为1
的方案数,容易知道对于 A[i] & A[j] & A[k] > 0
的结果必然属于集合|B1 U B2 U ... B15|
。因此,对于指定的输入元素集合,只需要求解出|B1 U B2 U ... B15|
的方案数,然后总方案数减去其方案数即可。对于|B1 U B2 ... U B15|
方案数的求解采用容斥原理即可。
func countTriplets(A []int) int {
if len(A) == 0 {
return 0
}
n := len(A)
ans := n * n * n
for i := 1; i < (1 << 16); i++ {
sign := 1
x := i
for x > 0 {
x &= (x - 1)
sign *= -1
}
cnt := 0
for j := 0; j < n; j++ {
if A[j]&i == i {
cnt++
}
}
ans += sign * cnt * cnt * cnt
}
return ans
}