题解:学而思编程 更奇怪的照片

【题目来源】

学而思编程:更奇怪的照片

【题目描述】

Farmer John 正再一次尝试给他的 \(N\) 头奶牛拍照(\(2≤N≤1000\))。

每头奶牛有一个范围在 \(1…100\) 之内的整数的「品种编号」。Farmer John 对他的照片有一个十分古怪的构思:他希望将所有的奶牛分为不相交的若干组(换句话说,将每头奶牛分到恰好一组中)并将这些组排成一行,使得第一组的奶牛的品种编号之和为偶数,第二组的编号之和为奇数,以此类推,奇偶交替。

Farmer John 可以分成的最大组数是多少?

【输入】

输入的第一行包含 \(N\)。下一行包含 \(N\) 个空格分隔的整数,为 \(N\) 头奶牛的品种编号。

【输出】

输出 Farmer John 的照片中的最大组数。可以证明,至少存在一种符合要求的分组方案。

【输入样例】

7
1 3 5 7 9 11 13

【输出样例】

3

【核心思想】

  1. 问题分析:给定 \(N\) 个奶牛的品种编号,要求分成尽可能多的组,按顺序排列使得各组和的奇偶性交替(偶、奇、偶、奇...)。这是一个奇偶分析 + 贪心调整问题,关键在于统计奇数和偶数的数量,并通过合并调整使它们能形成最长交替序列。

  2. 算法选择

    • 奇偶计数:统计奇数个数 odd 和偶数个数 even
    • 贪心合并:当奇数过多时,将两个奇数合并为一个偶数(奇+奇=偶),使奇偶数量趋于平衡
    • 边界调整:最终偶数最多比奇数多 \(1\)(序列以偶数开头),否则需要截断
  3. 关键步骤

    • 初始化:读取 \(N\)\(N\) 个品种编号
    • 统计奇偶数量
      • 遍历每个数 \(t\)
        • \(t \bmod 2 = 0\)even++
        • 否则:odd++
    • 调整奇偶平衡
      • odd > even 时循环:
        • odd -= 2:两个奇数合并为一个偶数
        • even++:合并后得到一个偶数
    • 最终边界处理
      • even > oddeven = odd + 1:偶数最多比奇数多 \(1\)(序列以偶开头)
    • 输出 even + odd:最大组数
  4. 时间/空间复杂度

    • 时间复杂度:\(O(N)\),线性遍历统计,调整循环最多 \(O(N)\)
    • 空间复杂度:\(O(1)\),仅需计数变量
  5. 奇偶合并的核心思想

    • 交替序列结构:目标序列形如 偶、奇、偶、奇... 或 偶、奇、偶(以偶开头),因此偶数个数等于奇数个数或比奇数多 \(1\)
    • 奇数合并策略:两个奇数之和为偶数,因此当奇数过多时,可将两个奇数合并为一组(和为偶),相当于消耗 \(2\) 个奇数产生 \(1\) 个偶数,使奇偶比例趋于 \(1:1\)
    • 贪心最优性:每次合并减少 \(2\) 个奇数增加 \(1\) 个偶数,是使奇偶数量接近的最快方式,局部最优即全局最优
    • 边界截断:若偶数仍多于奇数 \(+1\),说明偶数过剩,只能保留 odd + 1 个偶数以维持交替结构
    • 适用于"奇偶交替分组 + 资源调整"类问题,通过合并操作将不平衡状态转化为可交替结构

【算法标签】

数学

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n, odd, even;  // n: 数字个数,odd: 奇数个数,even: 偶数个数

int main()
{
    cin >> n;  // 读入数字个数

    for (int i = 1; i <= n; i++)  // 遍历每个数字
    {
        int t;
        cin >> t;  // 读入当前数字

        if (t % 2 == 0)  // 如果是偶数
        {
            even++;  // 偶数计数加1
        }
        else  // 如果是奇数
        {
            odd++;  // 奇数计数加1
        }
    }

    // 调整奇偶数量,使它们可以交替排列
    while (odd > even)  // 当奇数多于偶数时
    {
        odd -= 2;  // 将两个奇数合并成一个偶数
        even++;    // 合并后得到一个偶数
    }

    if (even > odd)  // 如果偶数多于奇数
    {
        even = odd + 1;  // 最多只能多一个偶数
    }

    // 输出最大交替序列长度
    cout << even + odd << endl;  // 总长度是奇数和偶数个数之和
    return 0;
}

【运行结果】

7
1 3 5 7 9 11 13
3
posted @ 2026-07-05 14:24  团爸讲算法  阅读(4)  评论(0)    收藏  举报