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

编写数组排列校验函数遇问题:非排列数组被误判

数组排列校验函数的问题修复

你的代码逻辑完全偏离了排列校验的需求,导致误判,核心问题如下:

  • 循环里的if (i == n)永远不会触发,因为循环条件是i < n,i的最大值是n-1,这个判断完全多余。
  • arr[n]属于数组越界访问,数组下标范围是0到n-1,访问这个位置会引发未定义行为。
  • 整个逻辑没有贴合排列的定义:排列要求数组包含1到n(或0到n-1)的每个整数恰好一次,你的代码根本没做这个核心校验。

正确实现方案

以下两种方法均针对包含1到n的每个整数恰好一次的排列做校验,如果是0到n-1的排列,只需微调范围判断即可。

方法一:哈希集合校验(直观易读)

#include <stdbool.h>
#include <stdlib.h>

bool permutationChecker(int arr[], int n) {
    // 用数组模拟哈希集合,记录已出现的元素
    int* seen = calloc(n + 1, sizeof(int));
    if (!seen) return false; // 处理内存分配失败的情况
    
    for (int i = 0; i < n; i++) {
        int num = arr[i];
        // 检查元素是否在合法范围
        if (num < 1 || num > n) {
            free(seen);
            return false;
        }
        // 检查元素是否重复出现
        if (seen[num]) {
            free(seen);
            return false;
        }
        seen[num] = 1;
    }
    
    free(seen);
    return true;
}

方法二:原地标记校验(空间复杂度O(1))

利用数组本身空间做标记,无需额外内存(会修改原数组,若需保留原数组优先用方法一):

#include <stdbool.h>
#include <stdlib.h>

bool permutationChecker(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        int num = abs(arr[i]); // 先取绝对值,避免已标记的负数干扰
        // 检查元素范围合法性
        if (num < 1 || num > n) {
            return false;
        }
        // 对应位置已为负数,说明元素重复
        if (arr[num - 1] < 0) {
            return false;
        }
        // 标记为负数,表示该元素已出现过
        arr[num - 1] *= -1;
    }

    // 可选:恢复数组原状态(如果需要保留原数组数据)
    for (int i = 0; i < n; i++) {
        arr[i] = abs(arr[i]);
    }
    
    return true;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:55:20