折木棍

在你的面前从左到右摆放着n根长短不一的木棍,你每次可以折断一根木棍,并将折断后得到的两根木棍一左一右放在原来的位置(即若原木棍有左邻居,则两根新木棍必须放在左邻居的右边,若原木棍有右邻居,新木棍必须放在右邻居的左边,所有木棍保持左右排列)。折断后的两根木棍的长度必须为整数,且它们之和等于折断前的木棍长度。你希望最终从左到右的木棍长度单调不减,那么你需要折断多少次呢?

输入描述:
第一行是一个数n,表示开始时有多少根木棍(1<=n<=3000)第二行有n个数,从第1个到第n个分别表示从左到右的木棍长度。对任意木棍的长度l,有1<=l<=3000。
输出描述
输出一行,一个数,你最少所需的折断木棍的次数x

示例1
输入:

5
3 5 13 9 12
输出

1
说明
你可以将长度为13的木棍折成长度分别为5和8的两根木棍,最终得到的排列是3 5 5 8 9 12

思路
从后往前遍历,使用单调递减栈,数组中元素从后往前呈递减关系,如果碰到nums[i]>nums[i+1],则将nums[i]折断成若干小于等于栈顶的小木棒,并让他们尽量保持平均大小,将略小的入栈。原理如下:题目中要求的是最小的折断次数,从而要折断的木棍数越少越好。从而对于nums[i]>nums[i+1],一定要对nums[i]做对应处理,且不能对数组整体产生太大影响(如果nums[i]折的太小,会使Nums[i]的前面发生nums[k]>nums[k+1]),因此,思路就是将nums[i]折断后的长度尽量靠近nums[i+1]且保持平均,从而使其对数组整体造成的影响最小

图解
在这里插入图片描述
C++单调栈代码

int breakNum(vector<int>& nums)
{
    int ans = 0;
    for (int i = nums.size() - 2; i >= 0; i--)
    {
        if (nums[i + 1] >= nums[i]) continue;
        int t = (nums[i] - 1) / nums[i + 1];
        ans += t;
        nums[i] /= (t + 1);
    }
    return ans;
}

作者:Ikaruga
链接:https://leetcode-cn.com/circle/discuss/eXOcnD/view/SecVmv/

代码如下(python)

nums = [3,5,13,9,12]
res = 0
for i in range(len(nums)-1):
    temp = len(nums)-2-i
    if nums[temp]<nums[temp+1]:continue
    else:
        t = nums[temp]//nums[temp+1]
        yushu = nums[temp]%nums[temp]+1
        res+=t
        if yushu==0:nums[temp]=nums[temp]/t
        else:nums[temp]=nums[temp]/(t+1)
print(res)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值