首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >2026-06-24:使数组奇偶交替的最少操作。用go语言,给定整数数组 nums。若对所有相邻位置 i 和 i+1,它们的奇偶性不同(一个为奇数、另一

2026-06-24:使数组奇偶交替的最少操作。用go语言,给定整数数组 nums。若对所有相邻位置 i 和 i+1,它们的奇偶性不同(一个为奇数、另一

作者头像
福大大架构师每日一题
发布2026-06-24 15:58:00
发布2026-06-24 15:58:00
1230
举报

2026-06-24:使数组奇偶交替的最少操作。用go语言,给定整数数组 nums。若对所有相邻位置 i 和 i+1,它们的奇偶性不同(一个为奇数、另一个为偶数),则称该数组为“奇偶交替”。你可以对任意下标 i 做一次操作:把 nums[i] 加 1 或减 1。

现在要返回两个数:

  • • answer[0]:把数组调整为“奇偶交替”所需的最少操作次数。
  • • answer[1]:在所有恰好用了 answer[0] 次操作得到“奇偶交替”的结果数组中,max(数组) - min(数组) 能取得的最小值。

注意:当数组长度为 1 时,它天然满足“奇偶交替”条件。

1 <= nums.length <= 100000。

-1000000000 <= nums[i] <= 1000000000。

输入: nums = [-2,-3,1,4]。

输出: [2,6]。

解释:

执行以下操作:

将 nums[2] 增加 1,得到 nums = [-2, -3, 2, 4]。

将 nums[3] 减少 1,得到 nums = [-2, -3, 2, 3]。

得到的数组是奇偶交替的,且 max(nums) - min(nums) = 3 - (-3) = 6 是所有使用恰好 2 次操作可获得的奇偶交替数组中的最小值。

题目来自力扣3854。

一、整体算法分步流程

步骤1:前置全局预处理

  1. 1. 判断数组长度:输入长度为4≠1,进入主逻辑;
  2. 2. 遍历整个数组,求出全局最小值gMin=-3、全局最大值gMax=4; 作用:当数字需要修改时,控制修改方向,用来计算修改后新数字,方便后续求极差。

步骤2:定义通用计算函数calc(target)

函数输入0/1两种模板,一次性算出两个结果: 返回值1:该模板需要的总最少操作次数op 返回值2:该模板在最少操作前提下,修改后数组能达到的最小极差minD 函数内部完整执行流程:

子步骤2.1 初始化变量

  • • op=0:统计当前模板总操作次数
  • • mn=无穷大:记录修改后数组所有元素最小值
  • • mx=负无穷大:记录修改后数组所有元素最大值

子步骤2.2 逐一遍历数组每个下标i、原数字x

核心判断条件:(x - i) & 1 != target,等价校验「当前x奇偶是否匹配当前模板要求」: 推导: x奇偶 ^ i奇偶 = target(x&1) ^ (i&1) = target (x-i)&1 = (x&1)^(i&1),因此条件不成立代表当前数字奇偶不达标,必须修改。

分两种分支处理每个元素:

分支A:当前数字奇偶不匹配模板(需要操作)
  1. 1. 操作计数op +=1(仅±1,最少代价,不做多次修改);
  2. 2. 决定修改后新x的值:
    • • 如果原x是全局最小值gMin:只能+1(如果-1会更小,极差会变大,为了拿到最小极差优先往大改);
    • • 如果原x是全局最大值gMax:只能-1(如果+1会更大,极差会变大,优先往小改); 逻辑目的:修改时尽可能压缩数值区间,让最终极差最小。
  3. 3. 用修改后的新x,更新全局mn、mx(记录当前修改后数组的最大、最小值)。
分支B:当前数字奇偶匹配模板(无需操作)

直接用原x更新mn、mx,不增加操作次数。

子步骤2.3 遍历完所有元素后计算极差

计算当前模板修改后数组极差:mx - mn; 题目规定数组长度≥2时极差至少为1,因此最终取max(mx-mn,1)作为该模板的最小极差minD; 函数返回 (总操作次数op,最小极差minD)。

步骤3:分别计算两种模板的代价

  1. 1. 调用calc(0),得到模板0数据:op1、minD1;
  2. 2. 调用calc(1),得到模板1数据:op2、minD2;

结合示例nums = [-2,-3,1,4]手动演算:

数组下标0: -2、下标1: -3、下标2: 1、下标3:4

calc(0)(偶、奇、偶、奇模板)

i=0,x=-2:x偶,i偶,匹配模板0,不操作,mn=-2,mx=-2 i=1,x=-3:x奇,i奇,匹配模板0,不操作,mn=-3,mx=-2 i=2,x=1:x奇,i偶,不匹配,op+1;x不是gMin/gMax,任意±1(示例选+1→2),新x=2,mn=-3,mx=2 i=3,x=4:x偶,i奇,不匹配,op+1;x是gMax=4,只能-1→3,新x=3,mn=-3,mx=3 总op1=2,极差3-(-3)=6 → minD1=6

calc(1)(奇、偶、奇、偶模板)

i=0,x=-2偶,i偶,不匹配,op+1;x=gMin=-3?不是,x=-2,±1变-1 i=1,x=-3奇,i奇,不匹配,op+1;±1变-2 i=2,x=1奇,i偶,匹配,无操作 i=3,x=4偶,i奇,匹配,无操作 总op2=2;修改后数值区间极差会大于6,minD2>6

步骤4:对比两套模板,选出最优方案

对比规则优先级:

  1. 1. 优先选总操作次数更少的模板;
  2. 2. 若次数相等,选极差更小的模板。

示例中op1=op2=2,minD1=6 < minD2,因此选用模板0结果,返回数组[2,6],和题目输出一致。

步骤5:边界兜底逻辑

如果输入数组长度等于1,直接返回[0,0],不执行上述calc计算流程。

二、时间复杂度分析

  1. 1. 求全局最大最小值:单次O(n)遍历;
  2. 2. calc(0)完整遍历数组O(n),calc(1)完整遍历数组O(n); 总遍历次数:3次线性遍历,总运算量与数组长度n成正比; 总时间复杂度:O(n) n最大1e5,线性复杂度满足数据范围要求。

三、额外空间复杂度分析

  1. 1. 仅使用固定数量局部变量:gMin、gMax、op、mn、mx、op1、minD1、op2、minD2等;
  2. 2. 没有开辟随n增长的数组、切片、哈希容器; 输出切片固定长度为2,属于常量空间; 总额外空间复杂度:O(1)(常数空间)

Go完整代码如下:

.

代码语言:javascript
复制
package main

import (
    "fmt"
    "math"
    "slices"
)

func makeParityAlternating(nums []int) []int {
    iflen(nums) == 1 {
        return []int{0, 0}
    }

    gMin := slices.Min(nums)
    gMax := slices.Max(nums)

    calc := func(target int) (int, int) {
        op, mn, mx := 0, math.MaxInt, math.MinInt
        for i, x := range nums {
            // 如果 target = 0,那么操作后,nums 每个数的奇偶性必须分别等于 0,1,0,1,... 即 target ^ i%2
            if (x-i)&1 != target { // 等价于 x&1 != target ^ i%2
                op++
                if x == gMin {
                    x++
                } elseif x == gMax {
                    x--
                }
            }
            mn = min(mn, x)
            mx = max(mx, x)
        }
        return op, max(mx-mn, 1) // 在 n >= 2 的情况下,极差至少是 1
    }

    op1, minD1 := calc(0)
    op2, minD2 := calc(1)

    if op1 < op2 || op1 == op2 && minD1 < minD2 {
        return []int{op1, minD1}
    }
    return []int{op2, minD2}
}

func main() {
    nums := []int{-2, -3, 1, 4}
    result := makeParityAlternating(nums)
    fmt.Println(result)
}
在这里插入图片描述
在这里插入图片描述

Python完整代码如下:

.

代码语言:javascript
复制
# -*-coding:utf-8-*-

from typing import List

def make_parity_alternating(nums: List[int]) -> List[int]:
    iflen(nums) == 1:
        return [0, 0]
    
    g_min = min(nums)
    g_max = max(nums)
    
    def calc(target: int) -> tuple:
        op = 0
        mn = float('inf')
        mx = float('-inf')
        
        for i, x in enumerate(nums):
            # 如果 target = 0,那么操作后,nums 每个数的奇偶性必须分别等于 0,1,0,1,...
            # 即 target ^ (i % 2)
            if (x - i) & 1 != target:  # 等价于 x&1 != target ^ i%2
                op += 1
                if x == g_min:
                    x += 1
                elif x == g_max:
                    x -= 1
            mn = min(mn, x)
            mx = max(mx, x)
        
        # 在 n >= 2 的情况下,极差至少是 1
        return op, max(mx - mn, 1)
    
    op1, min_d1 = calc(0)
    op2, min_d2 = calc(1)
    
    if op1 < op2 or (op1 == op2 and min_d1 < min_d2):
        return [op1, min_d1]
    return [op2, min_d2]

if __name__ == "__main__":
    nums = [-2, -3, 1, 4]
    result = make_parity_alternating(nums)
    print(result)
在这里插入图片描述
在这里插入图片描述

C++完整代码如下:

.

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>

using namespace std;

vector<int> makeParityAlternating(vector<int>& nums) {
    if (nums.size() == 1) {
        return {0, 0};
    }

    int gMin = *min_element(nums.begin(), nums.end());
    int gMax = *max_element(nums.begin(), nums.end());

    auto calc = [&](int target) -> pair<int, int> {
        int op = 0;
        int mn = INT_MAX;
        int mx = INT_MIN;

        for (int i = 0; i < nums.size(); i++) {
            int x = nums[i];
            // 如果 target = 0,那么操作后,nums 每个数的奇偶性必须分别等于 0,1,0,1,...
            // 即 target ^ i%2
            if (((x - i) & 1) != target) {  // 等价于 x&1 != target ^ i%2
                op++;
                if (x == gMin) {
                    x++;
                } elseif (x == gMax) {
                    x--;
                }
            }
            mn = min(mn, x);
            mx = max(mx, x);
        }
        // 在 n >= 2 的情况下,极差至少是 1
        return {op, max(mx - mn, 1)};
    };

    auto [op1, minD1] = calc(0);
    auto [op2, minD2] = calc(1);

    if (op1 < op2 || (op1 == op2 && minD1 < minD2)) {
        return {op1, minD1};
    }
    return {op2, minD2};
}

int main() {
    vector<int> nums = {-2, -3, 1, 4};
    vector<int> result = makeParityAlternating(nums);
    cout << result[0] << " " << result[1] << endl;
    return0;
}
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、整体算法分步流程
    • 步骤1:前置全局预处理
    • 步骤2:定义通用计算函数calc(target)
      • 子步骤2.1 初始化变量
      • 子步骤2.2 逐一遍历数组每个下标i、原数字x
      • 子步骤2.3 遍历完所有元素后计算极差
    • 步骤3:分别计算两种模板的代价
      • 结合示例nums = [-2,-3,1,4]手动演算:
    • 步骤4:对比两套模板,选出最优方案
    • 步骤5:边界兜底逻辑
  • 二、时间复杂度分析
  • 三、额外空间复杂度分析
  • Go完整代码如下:
  • Python完整代码如下:
  • C++完整代码如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档