🤖 AI总结
主题
算法题分析与代码实现:构造奇偶一致的数组Ⅱ
摘要
本文解析力扣3876题,利用奇偶规律和最小奇偶数判断能否构造全奇或全偶数组,并给出Go/Python/C++实现。
关键信息
- 1 核心规则:通过直接取值或差值构造全奇或全偶数组
- 2 数学基础:奇偶加减规律决定差值奇偶性
- 3 解题思路:基于最小奇偶数的条件判断
2026-07-11:构造奇偶一致的数组Ⅱ。用go语言,给定一个长度为 n 的整数数组 nums1,所有元素互不相同。需要构造一个同样长度为 n 的数组 nums2,使得 nums2 的每个元素都必须是奇数或者都必须是偶数(只能二选一)。对每个下标 i,nums2[i] 只能用两种方式之一生成:要么直接取 nums2[i] 等于 nums1[i];要么选择某个不同下标 j,把 nums2[i] 设为 nums1[i] 减去 nums1[j],并且要求这个差值为正(即 nums1[i] – nums1[j] >= 1)。如果能找到某种构造使得 nums2 全为奇数或全为偶数则返回 true,否则返回 false。
1 <= n == nums1.length <= 100000。
1 <= nums1[i] <= 1000000000。
nums1 中的所有整数互不相同。
输入: nums1 = [1,4,7]。
输出: true。
解释:
设置 nums2[0] = nums1[0] = 1。
设置 nums2[1] = nums1[1] – nums1[0] = 4 – 1 = 3。
设置 nums2[2] = nums1[2] = 7。
nums2 = [1, 3, 7],所有元素均为奇数。因此答案为 true。
题目来自力扣3876。
一、先拆解题目核心规则与奇偶数学基础 1. nums2 元素生成规则(每个位置二选一)
对任意下标 i:
1. 方案A:nums2[i] = nums1[i],直接复用原数;
2. 方案B:找另一个下标 j(j≠i),满足nums1[i] - nums1[j] ≥ 1,令nums2[i] = nums1[i] - nums1[j];
最终要求整个 nums2全部奇数 或 全部偶数,满足其一就返回 true。
2. 奇偶加减基础规律(解题核心)
设 a、b 为整数:
1. 奇数 − 奇数 = 偶数
2. 偶数 − 偶数 = 偶数
3. 奇数 − 偶数 = 奇数
4. 偶数 − 奇数 = 奇数
结论:两数做差,奇偶性由两数是否相同决定;相同奇偶得偶,不同奇偶得奇。
3. 目标拆解:只分两种可行目标,满足任一即true
目标1:构造全奇数 nums2
目标2:构造全偶数 nums2
只要其中一种目标存在可行构造,答案就是 true。
二、分步推导代码的完整逻辑(对应 uniformArray 函数思路) 步骤1:遍历数组,记录全局最小奇数、全局最小偶数
1. 初始化两个极值变量:mn[0]存最小偶数、mn[1]存最小奇数,初始值设为系统最大整数(代表当前还没找到对应类型数字);
2. 逐个遍历 nums1 中每个数字 x:
• 用x & 1判断奇偶:结果0=偶数、结果1=奇数;
• 把当前类型的最小值更新:如果x比已存的同类型最小值更小,就替换;
3. 遍历结束后得到两个关键值:
•mn[0]:数组里所有偶数的最小值;若无偶数,保持最大值;
•mn[1]:数组里所有奇数的最小值;若无奇数,保持最大值。
步骤2:分类讨论数组本身的奇偶构成,判断是否能构造合法nums2 情况A:数组只有偶数(mn[1] = 极大值,没有奇数)
此时直接满足函数返回条件mn[1] == math.MaxInt,直接返回 true。
原理:每个位置i都选择方案A(直接取原偶数),nums2 全偶数,天然合法。
情况B:数组只有奇数(mn[0] = 极大值,没有偶数)
此时mn[0] > mn[1]恒成立(极大值一定大于奇数最小值),满足第二个判断条件,返回 true。
原理:每个位置i直接取原奇数,nums2 全奇数,天然合法。
情况C:数组同时存在奇数、偶数(mn[0]、mn[1]都不是极大值)
此时判断条件:最小偶数 > 最小奇数(mn[0] > mn[1]),分两种子情况:
子情况C1:最小偶数 > 最小奇数 → 返回true
以示例[1,4,7]举例:
最小奇数 mn[1]=1,最小偶数 mn[0]=4,4>1,符合条件。
推导为什么能构造全奇数nums2:
1. 全局最小数字是奇数(最小奇数),记为 min_odd;
2. 对数组里任意数字 x,分两类处理:
• 若x本身是奇数:直接方案A,nums2[i]=x,天然奇数;
• 若x是偶数:x 一定大于 min_odd(全局最小数是奇数,所有偶数都比它大),满足x - min_odd ≥ 1;根据奇偶规律,偶数−奇数=奇数,因此选方案B,用j对应min_odd的下标,差值就是奇数;
3. 所有位置都能生成奇数,nums2全奇数,符合要求。
子情况C2:最小偶数 < 最小奇数 → 返回false
此时全局最小数字是偶数 min_even,数组同时有奇数、偶数,无法构造全奇数/全偶数数组:
1. 尝试构造全奇数nums2:
数组里存在奇数,奇数只能通过两种方式变成奇数:①直接保留奇数;②奇数−偶数。
但全局最小数是偶数 min_even,所有奇数都大于 min_even,奇数减min_even确实是奇数;但数组里的偶数无法变成奇数:偶数要得到奇数只能 偶数−奇数,但所有奇数都比min_even大,而当前最小偶数比所有奇数更小,不存在任何奇数满足「偶数−奇数≥1」,偶数位置无法生成奇数,全奇数方案作废。
2. 尝试构造全偶数nums2:
奇数想要生成偶数,只能用「奇数−奇数」,但全局最小数字是偶数,不存在比奇数更小的奇数,任意奇数找不到j满足差值为正且同为奇数;奇数位置无法生成偶数,全偶数方案作废。
两种目标都无法实现,最终返回 false。
步骤3:整合判断逻辑,统一返回结果
函数判断式mn[1] == math.MaxInt || mn[0] > mn[1]等价于:
要么数组无奇数(全偶数直接合法),要么最小偶数大于最小奇数(可以构造全奇数数组),满足任意一条就返回true,其余情况返回false。
三、示例 [1,4,7] 完整演算过程
1. 遍历数组提取奇偶最小值:
• x=1,奇数,mn[1]更新为1;
• x=4,偶数,mn[0]更新为4;
• x=7,奇数,mn[1]仍为1;
2. 状态:mn[0]=4,mn[1]=1,两种数字都存在;
3. 判断 4 > 1,条件成立,返回true;
4. 实操构造nums2:
• 下标0数字1(奇数):直接保留,得1;
• 下标1数字4(偶数):减去全局最小奇数1,4-1=3(奇数);
• 下标2数字7(奇数):直接保留,得7;
nums2=[1,3,7],全部奇数,符合题目要求。
四、时间复杂度、额外空间复杂度分析 1. 时间复杂度
• 核心操作:单次完整遍历数组 nums1,数组长度为 n;
• 遍历内每个元素仅做奇偶判断、一次最小值比较,均为 O(1) 常量操作;
• 无嵌套循环、无排序、无哈希、无额外多次遍历;
总时间复杂度:O(n),n 为数组长度,上限1e5,效率满足题目数据范围。
2. 额外空间复杂度
仅开辟固定长度数组mn [2]int,只存储两个整数,空间大小与输入数组长度 n 无关,属于常量空间;
没有开辟动态切片、哈希表、辅助数组等随n增长的空间;
总额外空间复杂度:O(1)(常数空间)。
Go完整代码如下:
package main
import (
"fmt"
"math"
)
func uniformArray(nums1 []int)bool {
// 计算最小偶数、最小奇数
mn := [2]int{math.MaxInt, math.MaxInt}
for _, x := range nums1 {
mn[x&1] = min(mn[x&1], x) // &1 比 %2 好,nums1 有负数也适用
}
// 只有偶数,或者偶数 >= 最小的偶数 > 最小的奇数
// 只有奇数的情况蕴含在 mn[0] > mn[1] 中
return mn[1] == math.MaxInt || mn[0] > mn[1]
}func main() {
nums1 := []int{1, 4, 7}
result := uniformArray(nums1)
fmt.Println(result)
}
![]()
Python完整代码如下:
# -*-coding:utf-8-*-
import math
from typing import List
def uniform_array(nums: List[int]) -> bool:
# 计算最小偶数、最小奇数
mn = [math.inf, math.inf]
for x in nums:
# & 1 比 % 2 更好,nums 有负数也适用
mn[x & 1] = min(mn[x & 1], x)
# 只有偶数,或者偶数 >= 最小的偶数 > 最小的奇数
# 只有奇数的情况蕴含在 mn[0] > mn[1] 中
return mn[1] == math.inf or mn[0] > mn[1]
def main():
nums = [1, 4, 7]
result = uniform_array(nums)
print(result)if __name__ == "__main__":
main()
![]()
C++完整代码如下:
bool uniformArray(const std::vector& nums) {
// 计算最小偶数、最小奇数
int mn[2] = {INT_MAX, INT_MAX};
for (int x : nums) {
// & 1 比 % 2 更好,nums 有负数也适用
mn[x & 1] = std::min(mn[x & 1], x);
}
// 只有偶数,或者偶数 >= 最小的偶数 > 最小的奇数
// 只有奇数的情况蕴含在 mn[0] > mn[1] 中
return mn[1] == INT_MAX || mn[0] > mn[1];
}int main() {
std::vector nums = {1, 4, 7};
bool result = uniformArray(nums);
std::cout << std::boolalpha << result << std::endl;
return0;
}
![]()
我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。