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 < 0 或 curr >= 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)。
相关推荐
坤坤子吖几秒前
算法学习——高精度加减乘除
c++·笔记·学习·算法
CQU_JIAKE8 分钟前
10.1[A]2267,磐久UMX【上下文128K,KVCache部分]
算法
朝朝辞暮i13 分钟前
C++ 第 14 课:引用 &
开发语言·c++·算法
白山编程大哥24 分钟前
适合初学者练习的 C/C++ 开源项目推荐
c语言·c++·开源
Joe_Wang532 分钟前
【从0到1学习JVM · 21】既不浪费空间又没有碎片,标记整理算法到底慢在哪
jvm·学习·算法·垃圾回收·标记整理算法
让学习成为一种生活方式38 分钟前
PlantCellChat--单细胞与空间转录组数据预测植物细胞间通讯的R包--The Plant Journal
算法
C++ 老炮儿的技术栈1 小时前
有符号变量与无符号变量的区别
服务器·开发语言·前端·数据结构·c++·算法·c
个 人 练 习 生1 小时前
C++:模板初阶详解
开发语言·c++·经验分享·学习
梦帮科技1 小时前
多任务权重流形融合:SLERP 球形线性插值、DARE 稀疏剪枝与多专家模型融合落地
人工智能·深度学习·算法·机器学习·tensorflow·聚类·剪枝
Tisfy1 小时前
LeetCode 0020.有效的括号:栈匹配
算法·leetcode·字符串·题解·括号匹配