2022-01-12:给定一个正数数组arr,长度为n,下标0~n-1, arr中的0、n-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 := []int{3, 2, 1, 2, 4, 4}
ret := minCost1(arr)
fmt.Println(ret)
}
if true {
arr := []int{3, 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中的0、n-1位置不需要达标,它们分别是最左、最右的位置, 中间位置i需要达标,达标的条件是 : arr[i-1] >的更多相关文章
- LeetCode竞赛题:K 次取反后最大化的数组和(给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。)
给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次.(我们可以多次选择同一个索引 i.) 以这种方式修改数组后 ...
- (016)给定一个有序数组(递增),敲代码构建一棵具有最小高度的二叉树(keep it up)
给定一个有序数组(递增),敲代码构建一棵具有最小高度的二叉树. 因为数组是递增有序的.每次都在中间创建结点,类似二分查找的方法来间最小树. struct TreeNode { int data; Tr ...
- 作业帮:给定一个整数数组,找出其中两个数相加等于目标值(去重set)
题目描述 给定一个整数数组,找出其中两个数相加等于目标值 输入 [1,3,5,7,9,11] 10 输出 1,9 3,7 代码: import java.util.HashMap; import ja ...
- 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数
今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...
- 给定一个整数数组 nums 和一个目标值 target,求nums和为target的两个数的下表
这个是来自力扣上的一道c++算法题目: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案 ...
- 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。
/** * 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标. * * 你可以假设每种输入只会对应一个答案.但是,数组中 ...
- 【编程题目】一个整数数组,长度为 n,将其分为 m 份,使各份的和相等,求 m 的最大值★★ (自己没有做出来!!)
45.雅虎(运算.矩阵): 2.一个整数数组,长度为 n,将其分为 m 份,使各份的和相等,求 m 的最大值 比如{3,2,4,3,6} 可以分成 {3,2,4,3,6} m=1; {3,6}{2,4 ...
- 产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复
产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复 用一个ArrayList存储1到100然后随机产生0到arraylist.size()之间的数字作为下标然后从arrayli ...
- Java实现产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复。
public static void main(String[] args){ //创建一个int数组,长度为100, int n = 100; int[] arrayInt = new int[n] ...
- 给定一个无序数组arr,求出需要排序的最短子数组长度。例如: arr = [1,5,3,4,2,6,7] 返回4,因为只有[5,3,4,2]需要排序。
思路 首先从左往右遍历,然后设定一个Max,如果遍历的过程中array[i]大于Max,则置换Max,若小于Max,则指定 k 记录该位置. 然后再从右往左遍历,设定一个Min,在遍历的过程中arra ...
随机推荐
- spring-dao.xml
本文件的作用:1整合dao层,连接数据库 2设置数据库连接池3配置SqlSessionFactory对象4配置扫描Dao接口包,动态实现dao接口,注入到spring容器中 Ps:此文件可以替代myb ...
- CSS pointer-events 属性
pointer-events 属性用于设置元素是否对鼠标事件做出反应. CSS 语法 pointer-events: auto|none; 属性值 属性值 描述 auto 默认值,设置该属性链接可以正 ...
- Linux & 标准C语言学习 <DAY7>
一.windows下获取方向键: 1.导入#include <conio.h> 2.通过getch()获取键盘上的键值 上:72 下:80 左:75 ...
- AES 简介 以及 C# 和 js 实现【加密知多少系列】
〇.AES 简介 AES 的全称是 Advanced Encryption Standard,意思是高级加密标准.它的出现主要是为了取代 DES(Data Encryption StandardDat ...
- MybatisPlus------代码生成器
快速开发: 代码生成器: (1)模版:MyBatisPlus提供 (2)数据库相关配置:读取数据库获取信息 (3)开发者自定义配置:手工配置 package com.ithema; import co ...
- 接入HMS Core应用内支付服务过程中一些常见问题总结
华为HMS Core应用内支付服务(In-App Purchases,IAP)为应用提供便捷的应用内支付体验和简便的接入流程.该服务支持客户端和服务端两种开发形式,具体可以参考官方文档. 往期文章:常 ...
- 使用requests的session发送请求
import requests # (1)网址 url = 'https://www.xslou.com/login.php' # (2)输入登录框-->输入密码框-->点击登录找到php ...
- 浅谈$\mathcal{LCT}$初步使用及具体操作
\(0x01\) 闲话 · \(LCT\)的用途以及具体思路 \(LCT\)是啥?百度一下的话--貌似是一种检查妇科病的东西?Oier的口味可是真不一般啊 咳,其实在我最近只是浅浅地学了一部分的基础上 ...
- 使用 SK 示例 探索 GitHub 存储库 中的机器人
微软 3月22日 一篇文章"Semantic-kernel 嵌入和记忆:使用聊天UI探索GitHub Repos"[1] ,文章中进行了展示了嵌入,该文章解释了他们如何帮助开发人员 ...
- LRU缓存替换策略及C#实现
目录 LRU缓存替换策略 核心思想 不适用场景 算法基本实现 算法优化 进一步优化 Benchmark LRU缓存替换策略 缓存是一种非常常见的设计,通过将数据缓存到访问速度更快的存储设备中,来提高数 ...