用二分法解决问题

leetcode 1011.在 D 天内送达包裹的能力 && 1482. 制作 m 束花所需的最少天数

1011题
在这里插入图片描述

int shipWithinDays(vector<int>& weights, int D) {
        int day = 1, i;
        int s = 0,ma = weights[0], carry;
        for(i = 0; i < weights.size(); i++)
        {
            s += weights[i];
            ma = max(ma,weights[i]);
        }
        int left = ma, right = s, mid;
        while(left <= right)
        {
            carry = 0;//carry每次重新计算清零
            mid = (left + right) / 2;
             for(i = 0; i < weights.size(); i++)
             {
                 carry += weights[i];
                 if(carry > mid)//假设mid为当前的运载能力
                 {
                     day += 1;
                     carry = weights[i];
                 }
             }
             if(day <= D)
             {
                right = mid - 1;
                day = 1;
             }
             else 
             {
                left = mid + 1;
                day = 1;
             }
             
        }
        return left;
    }

1482题解
在这里插入图片描述

  bool judge(vector<int>bloomDay, int m, int k, int days)
    {
        int l = bloomDay.size(), count = 0,tmp = 0;;
        vector<int>flag(l,0);
        int i, j;
        for(i = 0; i < l; i++)
        {
            if(bloomDay[i] <= days)
              flag[i] = 1;
        }
        for(i = 0; i < l; i++)
        {
             if(flag[i])
             {
                  tmp++;
                  if(tmp == k)
                  {
                      count++;
                      tmp = 0;
                  }
             }
             else
               tmp = 0;
        }
        if(count >= m)
         return true;
       return false;
    }
    int minDays(vector<int>& bloomDay, int m, int k) {
        int l = bloomDay.size();
        if(m > l / k) return -1;
         int i, j, left, right, mid;
         int mi = bloomDay[0], ma = bloomDay[0];
         for(i = 1; i < l; i++)
         {
            mi = min(mi,bloomDay[i]);
            ma = max(ma,bloomDay[i]);
         }
         left = mi;
         right = ma;
         while(left <= right)
         {
              mid = (left + right) / 2;
             if(judge(bloomDay,m,k,mid))
               right = mid - 1;
             else
              left = mid + 1;
         }
         return left;
    }

仅看代码结构的话会发现这两道题还是有很多相似之处的。

### 使用二分法解决13个球中找出重量不同的小球问题解决13个球中找出重量不同的小球问题时,直接应用传统意义上的二分法并不适用[^1]。这是因为二分法的核心思想是通过每次操作将问题规模缩小一半,但在天平称重问题中,每次称重可以提供三种可能的结果(左重、右重或平衡),因此更优的策略是将问题规模缩小为三分之一,而不是二分。 然而,如果坚持使用二分法的思想,可以尝试以下方法来解决问题: #### 方法描述 1. 将13个小球分为两组,每组6个球,剩下1个球单独放置。 2. 第一次称重:将两组各6个球分别放在天平两侧。 - 如果天平平衡,则重量不同的小球为剩下的那个单独的小球。 - 如果天平不平衡,则重量不同的小球位于较重或较轻的一侧。 3. 假设第一次称重后确定了包含异常小球的6个球。将这6个球再次分为两组,每组3个球。 4. 第二次称重:将两组各3个球分别放在天平两侧。 - 如果天平平衡,则重量不同的小球为未参与称重的那个单独的小球。 - 如果天平不平衡,则重量不同的小球位于较重或较轻的一侧。 5. 最后一步:从剩余的3个球中任选2个进行称重。 - 如果天平平衡,则重量不同的小球为未参与称重的那个。 - 如果天平不平衡,则根据天平倾斜方向确定重量不同的小球及其轻重。 #### 注意事项 尽管上述方法使用了二分法的思想,但实际上效率不如三进制划分方法。三进制划分方法可以通过每次称重将问题规模缩小为三分之一,从而在3次称重中找到异常小球并判断其轻重[^3]。 ```python def find_odd_ball(balls, left, right): if left >= right: return -1 mid = (left + right) // 2 result = compare_weights(balls[left:mid], balls[mid+1:right]) if result == "equal": return find_odd_ball(balls, mid + 1, right) elif result == "left_heavy": return find_odd_ball(balls, left, mid) else: return find_odd_ball(balls, mid + 1, right) def compare_weights(left_group, right_group): if sum(left_group) > sum(right_group): return "left_heavy" elif sum(left_group) < sum(right_group): return "right_heavy" else: return "equal" ``` #### 结论 虽然二分法可以用于解决问题,但三进制划分方法更为高效。对于13个球的问题,三进制划分方法可以在3次称重中找到异常小球并判断其轻重。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值