You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于递归实现数组近似平衡划分的C语言技术咨询

近似平衡数组划分的递归C语言实现

递归辅助函数设计思路

递归核心是逐个处理数组元素,每一步对当前元素做两种选择:放入第一组或第二组。需要跟踪以下关键状态:

  • 当前处理的数组索引
  • 两组各自的元素和
  • 两组各自的元素数量
  • 标记数组(记录每个元素归属的组,用于后续输出)
  • 找到有效划分的标志(避免不必要的递归)

递归终止条件:

  1. 处理完所有元素(索引等于数组大小):检查两组和是否相等,且元素数量差≤2。如果满足,标记找到解并返回;否则回溯。
  2. 已经找到有效划分:直接返回,不再继续递归。

完整实现代码

#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>

// 全局标志:标记是否找到符合条件的划分
int found = 0;

// 递归辅助函数:处理当前索引的元素,尝试放入两组之一
void helper(int arr[], int idx, int size, int sum1, int sum2, int count1, int count2, int* group) {
    // 已找到解或处理完所有元素,直接返回
    if (found || idx == size) {
        if (!found && idx == size && sum1 == sum2 && abs(count1 - count2) <= 2) {
            found = 1;
        }
        return;
    }

    // 尝试将当前元素放入第一组
    group[idx] = 1;
    helper(arr, idx + 1, size, sum1 + arr[idx], sum2, count1 + 1, count2, group);
    if (found) return; // 找到解就停止回溯

    // 尝试将当前元素放入第二组
    group[idx] = 2;
    helper(arr, idx + 1, size, sum1, sum2 + arr[idx], count1, count2 + 1, group);
    if (found) return;

    // 回溯:当前元素暂不归属任何组
    group[idx] = 0;
}

// 递归输出子数组元素(替代循环)
void print_subarray(int arr[], int* group, int idx, int size, int target_group, int first) {
    if (idx == size) {
        printf("}");
        return;
    }
    if (group[idx] == target_group) {
        if (!first) {
            printf(", ");
        }
        printf("%d", arr[idx]);
        print_subarray(arr, group, idx + 1, size, target_group, 0);
    } else {
        print_subarray(arr, group, idx + 1, size, target_group, first);
    }
}

// 题目要求的固定签名函数
void almost_balanced_partition(int arr[], int size) {
    found = 0;
    int* group = (int*)malloc(sizeof(int) * size);
    if (!group) return;

    // 递归初始化标记数组(无循环)
    void init_group(int idx, int size, int* group) {
        if (idx == size) return;
        group[idx] = 0;
        init_group(idx + 1, size, group);
    }
    init_group(0, size, group);

    // 调用递归辅助函数
    helper(arr, 0, size, 0, 0, 0, 0, group);

    if (found) {
        // 输出第一组
        printf("{");
        print_subarray(arr, group, 0, size, 1, 1);
        printf(" and ");
        // 输出第二组
        printf("{");
        print_subarray(arr, group, 0, size, 2, 1);
        printf("\n");
    } else {
        printf("No valid partition found.\n");
    }

    free(group);
}

// 测试示例
int main() {
    int arr1[] = {1, 0, 1, 0};
    almost_balanced_partition(arr1, 4); // 输出{1, 0, 0}和{1}或其他有效划分

    int arr2[] = {2, 2, 3, 3};
    almost_balanced_partition(arr2, 4); // 输出{2, 3}和{2, 3}

    int arr3[] = {1, 2, 3, 4, 5};
    almost_balanced_partition(arr3, 5); // 输出{1, 2, 5}和{3,4}(和为8,数量差1)
    return 0;
}

关键细节说明

  1. 标记数组:用group数组记录每个元素的归属(1=第一组,2=第二组),递归过程中通过回溯更新标记。
  2. 无循环实现:所有数组遍历(初始化标记数组、输出子数组)都用递归完成,完全符合题目要求。
  3. 提前终止:一旦找到有效划分,found标志设为1,后续递归直接返回,避免冗余计算。
  4. 输出格式:print_subarray函数递归遍历数组,只输出目标组的元素,严格按照{元素1,元素2,...}的格式输出。

注意事项

  • 如果数组总和为奇数,直接不可能满足和相等的条件,可在主函数开头加入判断优化(代码中未实现)。
  • 递归深度等于数组大小,对于过大的数组可能导致栈溢出,若需处理大数据量可考虑尾递归优化(取决于编译器支持)。

内容的提问来源于stack exchange,提问作者Wael Jaber

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 09:40:28