这场AK了,题目比较水...
1.检查字符串是否为数组前缀 (简单模拟略)
2.移除石子使总数最小 (贪心+优先队列)
贪心的移除当前能减少最多的石子,有优先队列模拟该过程。
type IntHeap []int // 定义一个类型
func (h IntHeap) Len() int { return len(h) } // 绑定len方法,返回长度
func (h IntHeap) Less(i, j int) bool { // 绑定less方法
return h[i] > h[j] // 如果h[i]<h[j]生成的就是小根堆,如果h[i]>h[j]生成的就是大根堆
}
func (h IntHeap) Swap(i, j int) { // 绑定swap方法,交换两个元素位置
h[i], h[j] = h[j], h[i]
}
func (h *IntHeap) Pop() interface{} { // 绑定pop方法,从最后拿出一个元素并返回
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
func (h *IntHeap) Push(x interface{}) { // 绑定push方法,插入新元素
*h = append(*h, x.(int))
}
func minStoneSum(piles []int, k int) int {
h := &IntHeap{}
for i := 0 ; i < len(piles) ; i++ {
heap.Push(h, piles[i])
}
for k > 0 {
val, _ := heap.Pop(h).(int)
t := val / 2
heap.Push(h, val - t)
k--
}
res := 0
for h.Len() > 0 {
v, _ := heap.Pop(h).(int)
res += v
}
return res
}
3.使字符串平衡的最小交换次数 (前缀和)
首先需要知道一个合法的只包含一种括号类型的字符串,在该串的任何一个位置,左括号的数量一定大于等于右括号的数量,所以预先处理出每个位置的左括号和右括号的前缀和,如果当前位置的右括号数量大于左括号的数量,则需要进行一次交换。
func minSwaps(s string) int {
left := make([]int, len(s))
right := make([]int, len(s))
if s[0] == '[' {
left[0] = 1
} else {
right[0] = 1
}
for i := 1 ; i < len(s) ; i++ {
left[i] += left[i - 1]
right[i] += right[i - 1]
if s[i] == '[' {
left[i]++
} else {
right[i]++
}
}
delta := 0
for i := 0 ; i < len(s) ; i++ {
if left[i] + delta < right[i] - delta {
delta++
}
}
return delta
}
4.找出到每个位置为止最长的有效障碍赛跑路线(dp+二分)
该题为最长上升子序列的模型,但是需要注意数据量,要用nlogn的解法才能过。
func longestObstacleCourseAtEachPosition(obstacles []int) []int {
arr := make([]int, 0)
res := make([]int, len(obstacles))
for i := 0 ; i < len(obstacles) ; i++ {
if len(arr) == 0 {
arr = append(arr, obstacles[i])
res[i] = 1
} else if obstacles[i] >= arr[len(arr) - 1] {
arr = append(arr, obstacles[i])
res[i] = len(arr)
} else {
l := 0
r := len(arr) - 1
for l <= r {
mid := (l + r) / 2
if obstacles[i] >= arr[mid] {
l = mid + 1
} else {
r = mid - 1
}
}
arr[l] = obstacles[i]
res[i] = l + 1
}
}
return res
}