每日一题——蓝桥杯99.分巧克力(举一反三+思想解读+逐步优化)


一个认为一切根源都是“自己不够强”的INTJ

个人主页:用哲学编程-优快云博客
专栏:每日一题——举一反三
题目链接

目录

菜鸡写法:​编辑

代码点评:

点评

复杂度分析

优化建议

我要更强!

初次修改:​编辑

二次修改:

 三次修改:​编辑

代码点评:

代码逻辑和流程

时间复杂度

空间复杂度

总结和改进建议

最终优化:

这段代码运用了几个哲学和编程思想来解决问题:

分治法(Divide and Conquer):

迭代改进(Iterative Enhancement):

抽象化(Abstraction):

预处理(Preprocessing):

算法优化(Algorithm Optimization):

空间换时间(Space-Time Tradeoff):

模块化(Modularity):

时间复杂度和空间复杂度分析

总结

举一反三:

1. 分治策略

2. 预处理进行优化

3. 算法优化

4. 空间换时间

5. 模块化编程

6. 抽象化

实践建议


菜鸡写法:

import os
import sys
N,K=map(int,input().split())
sizes=[]
output=0
num=100001
for i in range(N):
  sizes.append(list(map(int,input().split())))
while num>=K:
  output+=1
  #print(f"output",output)
  num=0
  for size in sizes:
    H,W=size[0],size[1]
    num+=(H//output)*(W//output)
    #print(f"num",num)
output-=1
print(output)

代码点评:
 

这段代码试图解决的是“分巧克力”问题,它使用了一种迭代增加正方形边长的方法来尝试寻找最大的符合条件的正方形边长。代表巧克力尺寸的数组 sizes 被用来存储每个巧克力的宽度和高度。在每次迭代中,代码计算当前边长 output 可以从每块巧克力中切割出多少个指定大小的正方形,并将这些数量累加到 num 中。如果 num 大于或等于小朋友的数量 K,代码增加 output 的值并继续。如果 num 小于 K,则停止循环,并将 output 减去 1,然后打印出最终的 output 值。

点评

  1. 正确性: 对于给定的问题,这种方法在概念上是可以解决问题的,但效率很低。由于它使用了一个简单的迭代方法,可能会在最坏情况下导致非常长的运行时间。
  2. 效率: 这段代码没有使用二分搜索,这是解决这类问题更常见的方法。二分搜索的效率会更高,因为它可以减少需要试验的正方形边长的数量。
  3. 代码质量: 代码简洁明了,但缺少函数封装和注释。加入函数封装和更多注释可以提高代码的可读性和可维护性。

复杂度分析

  • 时间复杂度: 最差情况下,output 从 1 开始,一直增加到切割出的最大正方形的最大可能边长。在每次迭代中,代码都会遍历 sizes 数组一次,该数组的长度为 N。因此,最差情况下的时间复杂度为 O(NM),其中 M 表示输出的最大边长。
  • 空间复杂度: sizes 数组存储了所有巧克力的尺寸,因此它的空间复杂度为 O(N)。

优化建议

通过二分搜索来优化这个问题的解决方案,可以大幅度提高效率。使用二分搜索时,时间复杂度可以降低到 O(NlogM),其中 M 是可能的最大边长。二分搜索方法会在可能的边长范围内进行逼近搜索,将搜索空间每次减半,直至找到最大可能的边长。这样可以避免不必要的线性搜索,大大提高效率。

如果你想要一个更高效的解决方案,应该考虑实现二分搜索算法。


我要更强!


初次修改:

import os
import sys
N,K=map(int,input().split())
sizes=[]
output=0
num=100001
i,j=0,0
for i in range(N):
    tmp=list(map(int,input().split()))
    if max(tmp)>j:
        j=max(tmp)
    sizes.append(tmp)
    
while i<j:
    output=(j+i)//2
    #print(f"output",output)
    num=0
    for size in sizes:
        H,W=size[0],size[1]
        num+=(H//output)*(W//output)
        #print(f"num",num)
    if num<K:
        #不够,每块巧克力应该更小
        j=output
    elif num>K:
        i=output+1
    else:
        print(output)
        raise SystemExit
output=(j+i)//2
print(output)

这个二分查找代码基本上是正确的,但有一些小问题需要修正。其中一个问题是在最后一个else分支中,如果num正好等于K,那么会打印当前output并退出。但是,可能存在一个更大的output值也能满足条件,所以您应该继续搜索以确认是否有更大的可能性。

另外,在else分支中,既然num等于K,这意味着我们找到了一个有效的解,但不一定是最大的解。我们应该继续向右侧搜索以查找更大的解,即i应该更新为output + 1。最终的output计算也应该在循环外部进行。

二次修改:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

用哲学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值