• LeetCode 1769. 移动所有球到每个盒子所需的最小操作数


    【LetMeFly】1769.移动所有球到每个盒子所需的最小操作数

    力扣题目链接:https://leetcode.cn/problems/minimum-number-of-operations-to-move-all-balls-to-each-box/

    n 个盒子。给你一个长度为 n 的二进制字符串 boxes ,其中 boxes[i] 的值为 '0' 表示第 i 个盒子是 的,而 boxes[i] 的值为 '1' 表示盒子里有 一个 小球。

    在一步操作中,你可以将 一个 小球从某个盒子移动到一个与之相邻的盒子中。第 i 个盒子和第 j 个盒子相邻需满足 abs(i - j) == 1 。注意,操作执行后,某些盒子中可能会存在不止一个小球。

    返回一个长度为 n 的数组 answer ,其中 answer[i] 是将所有小球移动到第 i 个盒子所需的 最小 操作数。

    每个 answer[i] 都需要根据盒子的 初始状态 进行计算。

    示例 1:

    输入:boxes = "110"
    输出:[1,1,3]
    解释:每个盒子对应的最小操作数如下:
    1) 第 1 个盒子:将一个小球从第 2 个盒子移动到第 1 个盒子,需要 1 步操作。
    2) 第 2 个盒子:将一个小球从第 1 个盒子移动到第 2 个盒子,需要 1 步操作。
    3) 第 3 个盒子:将一个小球从第 1 个盒子移动到第 3 个盒子,需要 2 步操作。将一个小球从第 2 个盒子移动到第 3 个盒子,需要 1 步操作。共计 3 步操作。
    

    示例 2:

    输入:boxes = "001011"
    输出:[11,8,5,4,3,4]

    提示:

    • n == boxes.length
    • 1 <= n <= 2000
    • boxes[i]'0''1'

    方法一:数学思维

    首先遍历一遍原始数组,求出将所有小球全部移动到下标 0 0 0的话所需要的步骤。同时,记录下来从下标 1 1 1开始到结束,一共有多少个小球

    int right1 = 0, left1 = 0, cnt = 0;  // right1记录下标0后面有多少个1(不包含下标0) | cnt记录将所有小球都移动到下标0需要多少步 | left1 记录下标0左边有多少个1
    int n = boxes.size();
    for (int i = 1; i < n; i++) {
        if (boxes[i] == '1') {
            right1++, cnt += i;
        }
    }
    vector<int> ans(n);
    ans[0] = cnt;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    接下来我们再次遍历数组,如果某个元素的上一个元素是1,那么这个元素左边的1的数量就会加一,因此left1++

    这时候,这个盒子和上一个盒子相比,这一个盒子左边*的所有1需要移动的步数都+1,这一个盒子左边共有left11,因此cnt += left1

    这时候,这个盒子和上一个盒子相比,上一个盒子右边的所有1需要移动的步数都-1,上一个盒子右边共有right1个1,因此cnt -= right1

    之后,如果这个盒子初始值也是1的话,再在遍历下一个元素之前提前更新right1的值(````right1–```)

    • 时间复杂度 O ( n ) O(n) O(n)
    • 空间复杂度 O ( 1 ) O(1) O(1),力扣答案不计入算法空间复杂度

    AC代码

    C++
    class Solution {
    public:
        vector<int> minOperations(string& boxes) {
            int right1 = 0, left1 = 0, cnt = 0;
            int n = boxes.size();
            for (int i = 1; i < n; i++) {
                if (boxes[i] == '1') {
                    right1++, cnt += i;
                }
            }
            vector<int> ans(n);
            ans[0] = cnt;
            for (int i = 1; i < n; i++) {
                if (boxes[i - 1] == '1')
                    left1++;
                cnt -= right1;
                cnt += left1;
                ans[i] = cnt;
                if (boxes[i] == '1')
                    right1--;
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    运行结果还不错:

    result

    同步发文于CSDN,原创不易,转载请附上原文链接哦~
    Tisfy:https://letmefly.blog.csdn.net/article/details/128146735

  • 相关阅读:
    Redis之分布式锁
    【毕业设计】ESP8266 WiFi 模块使用介绍 - 单片机 物联网 嵌入式
    数据链路层协议 ——— 以太网协议
    DNS域名解析
    html、css学习记录【uniapp前奏】
    【位置推iMessage苹果推】软件安装在GNU通用公共许可证或GNU Lesser GPL /库
    Mysql系列二:Mysql里的锁
    代码随想录第五十七天
    Linux单例模式
    vmware fusion12共享文件夹到虚拟机window10
  • 原文地址:https://blog.csdn.net/Tisfy/article/details/128146735