1089. Duplicate Zeros*

1089. Duplicate Zeros*

https://leetcode.com/problems/duplicate-zeros/

题目描述

Given a fixed length array arr of integers, duplicate each occurrence of zero, shifting the remaining elements to the right.

Note that elements beyond the length of the original array are not written.

Do the above modifications to the input array in place, do not return anything from your function.

Example 1:

Input: [1,0,2,3,0,4,5,0]
Output: null
Explanation: After calling your function, the input array is modified to: [1,0,0,2,3,0,0,4]

Example 2:

Input: [1,2,3]
Output: null
Explanation: After calling your function, the input array is modified to: [1,2,3]

Note:

  • 1 <= arr.length <= 10000
  • 0 <= arr[i] <= 9

C++ 实现 1

这题如果用额外的空间, 那特别好做. 现在我们只考虑 in-place 的做法.

先看一种实现特别慢的. 最后只 beats 5% 🥺, 但思路直观. 向后移动元素.

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        for (int i = 0; i < arr.size() - 1; ++ i) {
            if (arr[i] == 0) {
                for (int j = arr.size() - 2; j > i; -- j)
                    arr[j + 1] = arr[j];
                arr[++i] = 0;
            }
        }
    }
};

C++ 实现 2

进一步思考🤔. 我们用例子来介绍, 比如 arr = [1,0,2,3,0,4,5,0], 如果只考虑 0 的复制, 那么数组将变成:

复制前: 1 0 2 3 0 4 5 0
复制后: 1 0 0 2 3 0 0 4 5 0 0

原本数组可能变成 11 个元素, 但由于原数组大小只有 8, 所有最后 3 个元素要被丢弃. 被利用到的数只有 1 0 2 3 0 4. 那是不是就可以用一个指针 k 来指向最后所需要的元素的范围, 比如此时 k 应当指向 4. 因此下面代码中:

// 注意 k 初始化为 -1
for (int i = 0; i < arr.size(); ++ i) {
   if (arr[i] == 0) count += 2;
   else count += 1;
   ++ k;
   if (count >= arr.size()) break;
}

作用就是确定会用到的数据的范围. 之后只需要将 1 0 2 3 0 4 按规则正确地放置在 arr 中. 遇到 0 则放置两个 0. 但其中有一点要注意, count 可能会大于 arr.size(), 比如能用的数据最后一个为 0, 但这个 0 不必复制. 比如 arr = [1, 2, 0]. 这种特殊情况应该考虑. 下面代码使用:

if (count > arr.size() && j == arr.size() - 1) continue;

处理这种情况. 此种做法最后 beats 98%.

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int k = -1, count = 0;
        for (int i = 0; i < arr.size(); ++ i) {
            if (arr[i] == 0) count += 2;
            else count += 1;
            ++ k;
            if (count >= arr.size()) break;
        }
        for (int j = arr.size() - 1; j >= 0; -- j) {
            if (arr[k] != 0) arr[j] = arr[k--];
            else {
                arr[j] = arr[k--];
                if (count > arr.size() && j == arr.size() - 1) continue;
                if (j - 1 >= 0) arr[--j] = 0;
            }
        }
    }
};

扩展阅读

在 LeetCode Submission 看到的一种方法, 没有细看, 以后有机会再去详细理解 ⛳.

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cntz = 0;
        int n = arr.size();
        for(int i = 0; i < arr.size(); i++) {
            if(arr[i] == 0) cntz++;
        }
        int pos = cntz + n - 1;
        for(int i = n - 1; i >= 0; i--) {
            if(pos < n) arr[pos] = arr[i];
            if(arr[i] == 0) {
                pos--;
                if(pos < n) arr[pos] = 0;
            }
            pos--;
        }
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值