• 今日头条 2018 AI Camp 5 月 26 日在线笔试编程题第二道——最小分割分数


    题目:

    给 n 个正整数 a_1,…,a_n, 将 n 个数顺序排成一列后分割成 m 段,每一段的分数被记为这段内所有数的和,该次分割的分数被记为 m 段分数的最大值。问所有分割方案中分割分数的最小值是多少?

      • 输入描述: 
        第一行依次给出正整数 n, m。 
        第二行依次给出n 个正整数 a1,...,ana1,...,an。

      • 示例:

        输入 
        5 3 
        1 4 2 3 5 
        输出 
        5

      • 说明 
        分割成 1 4 | 2 3 | 5 的时候三段的分数都为 5,得到分割分数的最小值。

      • 备注: 
        对于所有的数据,有 m <= n <= 100000,0 <= aiai <= 2^39。

      • 思路

        1. 将 n 个数划分为 n 段,分割分数即为 n 个正整数的最大值;
        2. 将 n 个数划分为 1 段,分割分数即为 n 个正整数的和;
        3. 若分为 m 段,则分割分数一定介于最大值与和之间。因此采用二分查找,每次取一个值对序列进行划分,若能划分出 
          m 段,使得每段的和都小于这个数值,则满足划分,反之不满足,直至找到一个最小的满足划分的值为止。
      • 代码实现如下:

    #include <iostream>
    using namespace std;
    
    int Judge(int data[], int sum, int m, int n);
    int Binary_Search(int data[], int left, int right, int m, int n);
    
    
    int main()
    {
        int n = 0, m = 0;
        cin >> n >> m;
    
        int data[n];
        int max_num = 0;
        int sum = 0;
    
        int i = 0;
    
        for(i = 0; i < n ; i++)
        {
            cin >> data[i];
            if (data[i] > max_num)
            {
                max_num = data[i];
            }
            sum += data[i];
        }
    
        cout << Binary_Search(data, max_num, sum, m, n);
    
        return 0;
    }
    
    int Binary_Search(int data[], int left, int right, int m, int n)
    {
        int mid = 0;
    
        while (left < right)
        {
            mid = left + (right - left) / 2;
            if (Judge(data, mid, m, n)) //满足划分,继续向左寻找
            {
                right = mid;//不减是因为无法确保减一之后的数是否满足划分
            }
            else    //不满足划分,继续向右寻找
            {
                left = mid + 1;
            }
        }
    
        return left;
    }
    
    int Judge(int data[], int mid, int m, int n)
    {
        int cnt = 0;
        int sum = 0;
    
        for (int i = 0; i < n; i++)
        {
            if (sum + data[i] > mid) //累加和大于 mid,进行一次划分
            {
                sum = data[i];
                cnt++;
                if (cnt > m - 1)    //划分次数大于 m-1,不满足划分
                {
                    return 0;
                }
            }
            else
            {
                sum += data[i];
            }
        }
    
        return 1;
    }

    个人见解,如有错误,欢迎指正与交流!

    获取更多精彩,请关注「seniusen」!

     
  • 相关阅读:
    获取windows所有用户名
    windbg内存查看(d*)
    Windbg查看调用堆栈(k*)
    Windbg调试互斥体(Mutex)死锁
    Windbg调试关键区(CriticalSection)死锁
    "R6002 floating point support not loaded"错误
    由可变参数引起的崩溃
    【Dubbo源码学习】负载均衡算法(2)-轮询算法的实现
    jdk1.8源码解析(1):HashMap源码解析
    Java annotation浅析
  • 原文地址:https://www.cnblogs.com/seniusen/p/9143685.html
Copyright © 2020-2023  润新知