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

在R语言中生成无重复“非随机”数字的实现方案求助

解决你的「不完全随机」无重复序列生成问题

嘿,先帮你梳理下现有代码里的几个关键问题,这也是你报错和逻辑走不通的原因:

  • sample.int(1, 100, replace = FALSE) 参数搞反啦!sample.int的语法是sample.int(n, size),你想从100个数字里选1个,应该写成sample.int(100, 1, replace=FALSE),反过来就会触发"样本不能大于总体"的错误,这正是你遇到的问题。
  • 变量初始化太混乱:比如guess_sets_i还没赋值就直接用setdiff,第一次循环时guess_i都没定义就想guess_i +1,还有all_games_i的as.list用法错了(应该用list(index_i, guess_i, ...)而不是as.list传多参数)。
  • 没处理你提到的边界情况:比如当前数字是100时不能加1,或者前一个数字加1后已经被用过的情况。

接下来给你正确的实现方式,我把单个序列的生成封装成了函数,这样逻辑清晰,也方便重复生成100次:

第一步:编写单个序列生成函数

这个函数严格遵循你的规则:第一个数字随机选,之后每个数字有50%概率是前一个+1(前提是+1后不超范围且未被使用),否则随机选未用过的数字:

generate_semi_random_seq <- function(max_num = 100) {
  # 初始化已使用数字集合和结果序列
  used <- integer(0)
  seq <- integer(0)
  
  # 第一个数字随机选取
  first_num <- sample.int(max_num, 1)
  seq <- c(seq, first_num)
  used <- c(used, first_num)
  
  # 生成剩下的99个数字
  for (i in 2:max_num) {
    prev_num <- seq[i-1]
    # 50%概率尝试前一个数字+1
    if (runif(1) > 0.5) {
      next_candidate <- prev_num + 1
      # 检查候选数字是否合法(在范围内且未被使用)
      if (next_candidate <= max_num && !(next_candidate %in% used)) {
        seq <- c(seq, next_candidate)
        used <- c(used, next_candidate)
        next # 合法的话直接进入下一次循环,跳过随机选择
      }
    }
    # 如果加1不合法,就从剩余未使用的数字里随机选一个
    available <- setdiff(1:max_num, used)
    next_num <- sample(available, 1)
    seq <- c(seq, next_num)
    used <- c(used, next_num)
  }
  return(seq)
}

第二步:生成100个这样的序列

用replicate可以非常简便地生成多个序列,比手动循环列表清爽多了:

# 生成100个序列,每个序列是一个向量,存储在列表中
all_games <- replicate(100, generate_semi_random_seq(), simplify = FALSE)

# 如果想转成数据框(每一行对应一个序列),可以这么做:
all_games_df <- do.call(rbind, lapply(all_games, function(x) data.frame(t(x))))
# 给列命名(可选操作)
colnames(all_games_df) <- paste0("num_", 1:100)

看看示例结果

运行generate_semi_random_seq(),你会得到类似这样的序列:

[1]  5  6 51  4  3 88 87  9 10 11 12 ...(后续是剩余未使用的数字)

完全符合你想要的格式~

有没有更简便的写法?

上面的方法已经很清晰易读了,如果想优化效率(比如生成更大的序列),可以用集合来存储已使用的数字,查找速度会更快。比如用sets包的set类型:

# 先安装sets包(如果没装的话)
# install.packages("sets")
library(sets)

generate_semi_random_seq_fast <- function(max_num = 100) {
  used <- set()
  seq <- integer(0)
  
  first_num <- sample.int(max_num, 1)
  seq <- c(seq, first_num)
  used <- used + first_num
  
  for (i in 2:max_num) {
    prev_num <- seq[i-1]
    if (runif(1) > 0.5) {
      next_candidate <- prev_num + 1
      if (next_candidate <= max_num && !(next_candidate %in% used)) {
        seq <- c(seq, next_candidate)
        used <- used + next_candidate
        next
      }
    }
    available <- setdiff(1:max_num, as.vector(used))
    next_num <- sample(available, 1)
    seq <- c(seq, next_num)
    used <- used + next_num
  }
  return(seq)
}

不过对于100个数字的场景,用普通向量存储已使用数字完全够用,没必要特意装包。

总的来说,你的核心思路非常棒,只需要修正代码里的参数错误和变量初始化问题,再补充边界条件的检查,就能完美实现你想要的「不完全随机」序列啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 17:12:40