题解 | #合唱队#
合唱队
https://www.nowcoder.com/practice/6d9d69e3898f45169a441632b325c7b4
package main
import (
"fmt"
)
func main() {
var n int
fmt.Scan(&n)
heights := make([]int, n)
for i := 0; i < n; i++ {
fmt.Scan(&heights[i])
}
// 计算从左到右的最长递增子序列
left := make([]int, n)
for i := 0; i < n; i++ {
left[i] = 1
for j := 0; j < i; j++ {
if heights[j] < heights[i] && left[j]+1 > left[i] {
left[i] = left[j] + 1
}
}
}
// 计算从右到左的最长递增子序列
right := make([]int, n)
for i := n - 1; i >= 0; i-- {
right[i] = 1
for j := n - 1; j > i; j-- {
if heights[j] < heights[i] && right[j]+1 > right[i] {
right[i] = right[j] + 1
}
}
}
// 找到最长的合唱队形长度
maxLen := 0
for i := 0; i < n; i++ {
if left[i]+right[i]-1 > maxLen {
maxLen = left[i] + right[i] - 1
}
}
// 计算需要出列的同学数
minOut := n - maxLen
fmt.Println(minOut)
}
以下是一个使用Golang实现的解决方案:
package main
import (
"fmt"
)
func main() {
var n int
fmt.Scan(&n)
heights := make([]int, n)
for i := 0; i < n; i++ {
fmt.Scan(&heights[i])
}
// 计算最长递子序列(LIS)
lis := longestIncreasingSubsequence(heights)
// 计算最长减子序列(LDS)
lds := longestDecreasingSubsequence(heights)
// 找到最长合唱队形的长度
maxLen := 0
for i := 0; i < n; i++ {
len := lis[i] + lds[i] - 1
if len > maxLen {
maxLen = len
}
}
// 计算需要出列的同学目
minOut := n - maxLen
fmt.Println(minOut)
}
// 计算最长递增子序列
func longestIncreasingSubsequence(numsint) []int {
n := len(nums)
lis := make([], n)
for i := 0; i < n; i++ {
lis[i] = 1
for j := 0; j < i; j++ {
if nums[i] > nums[j] && lis[j]+1 > lis[i] {
lis[i] = lis[j] + 1
}
}
return lis
}
// 计算最长递减子列
func longestDecreasingSubsequence(nums []int) []int {
n := len(nums)
lds := makeint, n)
for i := n - 1; i >= 0; i-- {
lds[i] = 1
for j := n - 1; j > i; j-- {
if nums[i] > nums[j] && lds[j]+1 > lds[i] {
lds[i] = lds[j] + 1
}
}
}
return lds
}
这个解方案使用动态规划的思想,分别计算最长递增子列(LIS)和最长递减子列(LDS)。然后通过遍历每个同学找到最长合唱队形的长度。最后,需要出列的同学数等于总人减去最长合队形的长度。