2025-11-23:数组元素相等转换。用go语言,给出一个长度为 n 的数组 nums,元素仅为 1 或 -1,和一个非负整数
【摘要】 2025-11-23:数组元素相等转换。用go语言,给出一个长度为 n 的数组 nums,元素仅为 1 或 -1,和一个非负整数 k。允许你执行不超过 k 次以下变换:选定一个索引 i(0 ≤ i < n−1),把位置 i 和 i+1 的两个数同时取相反数(即把它们的符号都反过来)。同一个索引可以在不同操作中重复选择。判断是否存在一种不超过 k 步的操作序列,使得操作结束后数组中的所有元素都...
2025-11-23:数组元素相等转换。用go语言,给出一个长度为 n 的数组 nums,元素仅为 1 或 -1,和一个非负整数 k。
允许你执行不超过 k 次以下变换:选定一个索引 i(0 ≤ i < n−1),把位置 i 和 i+1 的两个数同时取相反数(即把它们的符号都反过来)。
同一个索引可以在不同操作中重复选择。判断是否存在一种不超过 k 步的操作序列,使得操作结束后数组中的所有元素都相同。
如果存在返回 true,否则返回 false。
<= n == nums.length <= 100000。
nums[i] 的值为 -1 或 1。
1 <= k <= n。
输入: nums = [1,-1,1,-1,1], k = 3。
输出: true。
解释:
我们可以通过以下两次操作使数组的所有元素相等:
选择下标 i = 1,将 nums[1] 和 nums[2] 同时乘以 -1。此时 nums = [1,1,-1,-1,1]。
选择下标 i = 2,将 nums[2] 和 nums[3] 同时乘以 -1。此时 nums = [1,1,1,1,1]。
题目来自力扣3576。
🔄 分步骤详细过程
-
双目标检查
- 算法首先明确最终的目标:数组中的所有元素必须全部是
1或者全部是-1。因此,它会分别针对这两种情况(target = 1和target = -1)进行独立的检查。 - 只要其中任意一种情况能够在给定的操作次数
k内实现,函数就会返回true。这是一种常见的解题思路,通过枚举有限的可能结果来简化问题。
- 算法首先明确最终的目标:数组中的所有元素必须全部是
-
贪心遍历与符号传播
- 对于每一种目标值,算法采用一次从左到右的线性遍历。这个过程模拟了操作对数组元素符号的累积影响。
- 在遍历过程中,算法维护两个关键状态:
left:剩余的可执行操作次数,初始值为k。mul:一个乘数因子(其值为 1 或 -1),用于表示由于之前位置的操作对当前正在检查的元素造成的累积符号翻转效应。初始值为 1,表示没有累积影响。
-
处理每个元素
- 对于数组中的每一个元素
nums[i],算法计算其当前的有效值nums[i] * mul。这个有效值反映了在考虑了之前所有操作的影响后,该元素当前“表现”出的符号。 - 情况一:有效值等于目标值
- 如果
nums[i] * mul等于目标值,说明当前位置的元素符号已经是正确的,不需要执行操作。 - 此时,将
mul重置为 1。这意味着之前的操作链影响到此结束,下一个元素nums[i+1]的符号不会被本次遍历中之前的操作所影响。
- 如果
- 情况二:有效值不等于目标值
- 如果
nums[i] * mul不等于目标值,说明需要执行一次操作来翻转nums[i]和nums[i+1]的符号。 - 首先检查是否满足执行操作的条件:① 剩余操作次数
left大于 0;② 当前索引i不是数组的最后一个元素(因为操作需要同时改变i和i+1位置)。 - 如果条件不满足,则说明无法使当前元素匹配目标,本次检查(对于当前目标值)失败。
- 如果条件满足,则执行以下动作:
- 剩余操作次数
left减少 1。 - 将乘数
mul设置为 -1。这个操作非常关键:它意味着由于在位置i执行了翻转,下一个元素nums[i+1]的符号将会被改变。因此,在检查下一个位置时,需要通过乘以-1来“补偿”这次操作产生的影响。这个机制模拟了操作效应沿着数组向后传播的过程。
- 剩余操作次数
- 如果
- 对于数组中的每一个元素
-
最终判断
- 如果遍历完所有元素,都没有因为无法匹配而提前返回,则说明可以在
k次操作内使所有元素变为当前检查的目标值,返回true。 - 如果对于两个目标值(1 和 -1)的检查都失败了,则函数返回
false。
- 如果遍历完所有元素,都没有因为无法匹配而提前返回,则说明可以在
⏱️ 复杂度分析
- 总的时间复杂度:算法对数组进行了常数次(2次)完整的遍历。每次遍历的时间复杂度是 O(n),其中 n 是数组
nums的长度。因此,总的时间复杂度是 O(n)。 - 总的额外空间复杂度:算法只使用了固定数量的额外变量(如
left,mul, 循环变量i等),这些空间开销不随输入数组的大小n而变化。因此,总的额外空间复杂度是 O(1)。
Go完整代码如下:
package main
import (
"fmt"
)
func canMakeEqual(nums []int, k int) bool {
check := func(target int) bool {
left := k
mul := 1
for i, x := range nums {
if x*mul == target {
mul = 1 // 不操作,下一个数不用乘 -1
continue
}
if left == 0 || i == len(nums)-1 {
return false
}
left--
mul = -1 // 操作,下一个数要乘 -1
}
return true
}
return check(-1) || check(1)
}
func main() {
nums := []int{1, -1, 1, -1, 1}
k := 3
result := canMakeEqual(nums, k)
fmt.Println(result)
}

Python完整代码如下:
# -*-coding:utf-8-*-
def canMakeEqual(nums, k):
def check(target):
left = k
mul = 1
for i, x in enumerate(nums):
if x * mul == target:
mul = 1 # 不操作,下一个数不用乘 -1
continue
if left == 0 or i == len(nums) - 1:
return False
left -= 1
mul = -1 # 操作,下一个数要乘 -1
return True
return check(-1) or check(1)
# 测试示例
if __name__ == "__main__":
nums = [1, -1, 1, -1, 1]
k = 3
result = canMakeEqual(nums, k)
print(result) # 输出结果

C++完整代码如下:
#include <iostream>
#include <vector>
using namespace std;
bool canMakeEqual(vector<int>& nums, int k) {
auto check = [&](int target) -> bool {
int left = k;
int mul = 1;
for (int i = 0; i < nums.size(); i++) {
int x = nums[i];
if (x * mul == target) {
mul = 1; // 不操作,下一个数不用乘 -1
continue;
}
if (left == 0 || i == nums.size() - 1) {
return false;
}
left--;
mul = -1; // 操作,下一个数要乘 -1
}
return true;
};
return check(-1) || check(1);
}
int main() {
vector<int> nums = {1, -1, 1, -1, 1};
int k = 3;
bool result = canMakeEqual(nums, k);
cout << boolalpha << result << endl; // 输出结果
return 0;
}

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)