2022-01-12:给定一个正数数组arr,长度为n,下标0~n-1, arr中的0n-1位置不需要达标,它们分别是最左最右的位置, 中间位置i需要达标,达标的条件是 : arr[i-1] >
Posted 福大大架构师每日一题
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022-01-12:给定一个正数数组arr,长度为n,下标0~n-1, arr中的0n-1位置不需要达标,它们分别是最左最右的位置, 中间位置i需要达标,达标的条件是 : arr[i-1] >相关的知识,希望对你有一定的参考价值。
2022-01-12:给定一个正数数组arr,长度为n,下标0~n-1,
arr中的0、n-1位置不需要达标,它们分别是最左、最右的位置,
中间位置i需要达标,达标的条件是 : arr[i-1] > arr[i] 或者 arr[i+1] > arr[i]哪个都可以。
你每一步可以进行如下操作:对任何位置的数让其-1,
你的目的是让arr[1~n-2]都达标,这时arr称之为yeah!数组。
返回至少要多少步可以让arr变成yeah!数组。
数据规模 : 数组长度 <= 10000,数组中的值<=500。
来自360面试。
答案2022-01-12:
方法一、动态规划。
方法二、贪心。
时间复杂度:O(N)。
空间复杂度:O(N)。
代码用golang编写。代码如下:
package main
import (
"fmt"
"math"
)
func main()
if true
arr := []int3, 2, 1, 2, 4, 4
ret := minCost1(arr)
fmt.Println(ret)
if true
arr := []int3, 2, 1, 2, 4, 4
ret := yeah(arr)
fmt.Println(ret)
const INVALID = math.MaxInt64
// 递归方法,已经把尝试写出
func minCost1(arr []int) int
if len(arr) < 3
return 0
min := INVALID
for _, num := range arr
min = getMin(min, num)
for i := 0; i < len(arr); i++
arr[i] += len(arr) - min
return process1(arr, 1, arr[0], true)
// 当前来到index位置,值arr[index]
// pre : 前一个位置的值,可能减掉了一些,所以不能用arr[index-1]
// preOk : 前一个位置的值,是否被它左边的数变有效了
// 返回 : 让arr都变有效,最小代价是什么?
func process1(arr []int, index, pre int, preOk bool) int
if index == len(arr)-1 // 已经来到最后一个数了
if preOk || pre < arr[index]
return 0
else
return INVALID
//return preOk || pre < arr[index] ? 0 : INVALID;
// 当前index,不是最后一个数!
ans := INVALID
if preOk
for cur := arr[index]; cur >= 0; cur--
next := process1(arr, index+1, cur, cur < pre)
if next != INVALID
ans = getMin(ans, arr[index]-cur+next)
else
for cur := arr[index]; cur > pre; cur--
next := process1(arr, index+1, cur, false)
if next != INVALID
ans = getMin(ans, arr[index]-cur+next)
return ans
// 最终的最优解,贪心
// 时间复杂度O(N)
// 请注意,重点看上面的方法
// 这个最优解容易理解,但让你学到的东西不是很多
func yeah(arr []int) int
if len(arr) < 3
return 0
n := len(arr)
nums := make([]int, n+2)
nums[0] = math.MaxInt64
nums[n+1] = math.MaxInt64
for i := 0; i < len(arr); i++
nums[i+1] = arr[i]
leftCost := make([]int, n+2)
pre := nums[0]
change := 0
for i := 1; i <= n; i++
change = getMin(pre-1, nums[i])
leftCost[i] = nums[i] - change + leftCost[i-1]
pre = change
rightCost := make([]int, n+2)
pre = nums[n+1]
for i := n; i >= 1; i--
change = getMin(pre-1, nums[i])
rightCost[i] = nums[i] - change + rightCost[i+1]
pre = change
ans := math.MaxInt64
for i := 1; i <= n; i++
ans = getMin(ans, leftCost[i]+rightCost[i+1])
return ans
func getMin(a, b int) int
if a < b
return a
else
return b
执行结果如下:
以上是关于2022-01-12:给定一个正数数组arr,长度为n,下标0~n-1, arr中的0n-1位置不需要达标,它们分别是最左最右的位置, 中间位置i需要达标,达标的条件是 : arr[i-1] >的主要内容,如果未能解决你的问题,请参考以下文章
[程序员代码面试指南]数组和矩阵问题-未排序正数数组中累加和为给定值的最长子数组长度
2021-05-01:给定一个有序数组arr,代表坐落在X轴上的点。给定一个正数K,代表绳子的长度。返回绳子最多压中几个点?即使绳子边缘处盖住点也算盖住。
2022-05-20:给定一个正数数组arr,长度为N,依次代表N个任务的难度,给定一个正数k, 你只能从0任务开始,依次处理到N-1号任务结束,就是一定要从左往右处理任务, 只不过,难度差距绝对值不
2022-05-21:给定一个数组arr,长度为n, 表示n个服务员,每个人服务一个人的时间。 给定一个正数m,表示有m个人等位。 如果你是刚来的人,请问你需要等多久? 假设:m远远大于n,比如n<=
2021-08-28:给定一个正数数组arr,长度一定大于6(>=7),一定要选3个数字做分割点,从而分出4个部分,并且每部分都有数,分割点的数字直接删除,不属于任何4个部分中的任何一个。 返回有没有