字节笔试——折木棍

笔试时候没做得太好,结束了重新做一遍,刷题还是不能停啊QAQ。

题目描述

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

输出描述

第一行是一个数n,表示开始时有多少根木棍(1<=n<=3000)第二行有n个数,从第1个到第n个分别表示从左到右的木棍长度。对任意木棍的长度l,有1<=l<=3000。

输出一行,一个数,你最少所需的折断木棍的次数x

示例1

输入:

5
3 5 13 9 12

输出

1

考试时提交版本:(没有ac,有的情况没有考虑到)

#coding=utf-8
import sys
if __name__ == "__main__":
    result = 0
    n = int(sys.stdin.readline().strip()) #输入数组长度n
    line = sys.stdin.readline().strip()	 #输入数组
    values= list(map(int,line.split()))   #转为list
    while 1:#循环直至单调不减
    	#判断是否单调不减
        c = values.copy()
        c.sort()
        if c == values:
            break
		#开始遍历
        i = 0
        while 1:       
            if i >= len(values)-1:
                break
            # 如果有不符合规则的木棍直接对折
            if not values[i] <=values[i+1]:   
            	#奇数的话小的放左边大的放右边            
                values.insert(i, values[i]//2)
                values[i+1]=values[i+1]-values[i]
                #折断次数+1
                result = result +1
                continue
            i = i+1
    print(result, values)

从头遍历时间复杂度过高,修改为从尾部开始遍历,只需要遍历一次

#coding=utf-8
import sys
if __name__ == "__main__":
    result = 0
    n = int(sys.stdin.readline().strip())
    line = sys.stdin.readline().strip()
    values= list(map(int,line.split()))
    r = [values[-1]] #创建单调不增栈
    values.pop(-1)  #从尾部开始遍历
    while values:     
        tmp = values[-1]
        #如果没有折完当前木棍    
        while tmp:
            #符合规则直接入栈
            if tmp <= r[-1]:
                r.append(tmp)
                tmp = 0
            #如果有不符合规则的木棍直接对折
            else:
                #对折后小于栈顶    
                if int(tmp/2+0.5) <=r[-1]:
                    r.append(int(tmp/2+0.5))
                #对折后仍然大于栈顶  
                else:
                    r.append(r[-1])
                tmp = tmp - r[-1]  
                result=result+1
        values.pop(-1)
    print(r,result)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值