3354. 使数组元素等于零

3354、[简单] 使数组元素等于零

1、题目描述

给你一个整数数组 nums

开始时,选择一个满足 nums[curr] == 0 的起始位置 curr ,并选择一个移动 方向 :向左或者向右。

此后,你需要重复下面的过程:

  • 如果 curr 超过范围 [0, n - 1] ,过程结束。
  • 如果 nums[curr] == 0 ,沿当前方向继续移动:如果向右移,则 递增 curr ;如果向左移,则 递减 curr
  • 如果 nums[curr] > 0:
    • nums[curr] 减 1 。
    • 反转 移动方向(向左变向右,反之亦然)。
    • 沿新方向移动一步。

如果在结束整个过程后,nums 中的所有元素都变为 0 ,则认为选出的初始位置和移动方向 有效

返回可能的有效选择方案数目。

2、解题思路

  1. 问题描述:

    • 从一个初始位置 curr 开始,选择方向(左或右),按题目要求依次处理元素。

    • 如果结束时 nums 所有元素为 0,则此方案有效。

    • 我们需要统计满足条件的方案数目。

  2. 核心逻辑:

    • 遍历所有满足 nums[curr] == 0 的起始位置 curr

    • 针对每个起始位置,尝试两种移动方向(左、右),模拟过程并验证是否满足条件。

    • 使用辅助数组 temp 保存当前模拟的状态,避免修改原始数组。

  3. 模拟移动:

    • 如果当前位置值是 0,继续沿当前方向移动。

    • 如果当前位置值是 >0:

      • 减少当前值 1
      • 反转方向。
      • 移动一步。
    • 如果当前位置越界(curr < 0curr >= n),结束模拟。

  4. 优化点:

    • 尽量减少不必要的模拟操作。

    • 当发现某个状态无法满足条件时立即终止。

3、代码实现

复制代码
class Solution {
public:
    int countValidSelections(vector<int>& nums) {
        int n = nums.size();
        int result = 0;

        // 遍历所有可能的起始位置
        for (int start = 0; start < n; ++start) {
            if (nums[start] != 0)
                continue;

            // 两个方向:1 表示向右,-1 表示向左
            for (int direction : {1, -1}) {
                vector<int> temp = nums; // 临时数组用于模拟
                int curr = start;
                bool valid = true;

                while (curr >= 0 && curr < n) {
                    if (temp[curr] == 0) {
                        // 当前位置为 0,继续移动
                        curr += direction;
                    } else if (temp[curr] > 0) {
                        // 当前位置值 > 0
                        temp[curr]--;           // 减少当前值
                        direction = -direction; // 反转方向
                        curr += direction;      // 移动一步
                    } else {
                        // 理论上不会出现这种情况
                        valid = false;
                        break;
                    }
                }

                // 如果数组所有元素都变为 0,则该方案有效
                if (valid && all_of(temp.begin(), temp.end(), [](int x) { return x == 0; })) {
                    result++;
                }
            }
        }

        return result;
    }
};

4、复杂度分析

  • 时间复杂度
    • 遍历所有起始位置 O(n)
    • 每个起始位置模拟两种方向,最多访问每个元素一次,因此单次模拟的复杂度为 O(n)
    • 总复杂度为 O(n2)。
  • 空间复杂度
    • 额外使用了一个数组 temp,大小为 O(n)。
相关推荐
CM莫问3 小时前
<论文>(微软)WINA:用于加速大语言模型推理的权重感知神经元激活
人工智能·算法·语言模型·自然语言处理·大模型·推理加速
计信金边罗5 小时前
是否存在路径(FIFOBB算法)
算法·蓝桥杯·图论
MZWeiei5 小时前
KMP 算法中 next 数组的构建函数 get_next
算法·kmp
Fanxt_Ja6 小时前
【JVM】三色标记法原理
java·开发语言·jvm·算法
luofeiju6 小时前
行列式的性质
线性代数·算法·矩阵
緈福的街口6 小时前
【leetcode】347. 前k个高频元素
算法·leetcode·职场和发展
南郁7 小时前
007-nlohmann/json 项目应用-C++开源库108杰
c++·开源·json·nlohmann·现代c++·d2school·108杰
pen-ai7 小时前
【统计方法】基础分类器: logistic, knn, svm, lda
算法·机器学习·支持向量机
鑫鑫向栄7 小时前
[蓝桥杯]春晚魔术【算法赛】
算法·职场和发展·蓝桥杯
roman_日积跬步-终至千里7 小时前
【Go语言基础【3】】变量、常量、值类型与引用类型
开发语言·算法·golang