遇到一个随机数面试题,目测无最优解

小湿哥 2021-05-25 03:15:17
偶然看到群里别人发的一条面试题


生成随机数 (由0~9的阿拉伯数字组成的,长度是6~15个字符)
要求
1. 不能出现连续3个以上相同的数字(11234,2333456 是不允许的)
2. 不能出现3个连号的情况( 123456, 123457, 2567891)
3. 生成的字符串不能是等差数列
4. 要求算法高效,少占内存。


我是没什么好办法。大概三步走

第一步
生成随机数
一次生成64位的数,再做随机长度分割。

第二步
每个字符串从头到尾遍历,检查是否有三个连续数字一致,同时也检查是否有连续3个连号。
若有则该数失败。

第三步
依次遍历,判断等差数列

抛转引玉,有没有更高效的办法来解这个题?!
...全文
2840 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
我感觉这条:
2. 不能出现3个连号的情况( 123456, 123457, 2567891)
是楼主理解错了
图片中题目说的是不允许3连号(123456、123457、123458)
楼主似乎理解成了同一个号内部不允许3连数字
赵4老师 2021-05-25
  • 打赏
  • 举报
回复
随机必然有重复,所谓“不重复的随机”实际上是洗牌。洗牌算法参考下面:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int d[6];
int i,n,a,b,t;
int c,j;
void main() {
    srand(time(NULL));
    printf("shuffle 0..n-1 demo\n");
    for (n=1;n<=5;n++) {/* 测试1~5个元素 */
        printf("_____n=%d_____\n",n);
        j=1;
        for (c=1;c<=n;c++) j=j*c;/* j为n! */
        j*=n*2;
        for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
            for (i=0;i<n;i++) d[i]=i;/* 填写0~n-1 */
            for (i=n;i>0;i--) {/* 打乱0~n-1 */
                a=i-1;b=rand()%i;
                if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
            }
            printf("%04d:",c);
            for (i=0;i<n;i++) printf("%d",d[i]);
            printf("\n");
        }
    }
    printf("shuffle 1..n demo\n");
    for (n=1;n<=5;n++) {/* 测试1~5个元素 */
        printf("_____n=%d_____\n",n);
        j=1;
        for (c=1;c<=n;c++) j=j*c;/* j为n! */
        j*=n*2;
        for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
            for (i=1;i<=n;i++) d[i]=i;/* 填写1~n */
            for (i=n;i>1;i--) {/* 打乱1~n */
                a=i;b=rand()%i+1;
                if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
            }
            printf("%04d:",c);
            for (i=1;i<=n;i++) printf("%d",d[i]);
            printf("\n");
        }
    }
}
小湿哥 2021-05-25
  • 打赏
  • 举报
回复
引用 3 楼 赵4老师 的回复:
仅供参考:
//要求1:从给出来的不同的六组数字中,从每组任意挑选一个数字,最后组成一个六个数字的数组。
//将所有的数组全部列出来。
//同时,排除全部为偶数、全部为奇数的数组。
//排除四个数字递增连续(比如8、9、10、11)的数组。
//如下:
//第一个数字从这12个数字中挑选:,1,3,2,4,5,6,7,8,9,10,11,12
//第二个数字从这17个数字中挑选:,8,7,5,9,6,4,11,10,12,13,3,14,17,2,16,15,18
//第三个数字从这21个数字中挑选:,13,10,15,16,18,11,14,12,7,19,21,17,8,22,9,20,6,23,5,24,25
//第四个数字从这20个数字中挑选:,22,23,18,20,16,17,15,21,14,26,19,24,27,25,12,13,11,10,28,29
//第五个数字从这19个数字中挑选:,26,25,27,29,30,28,23,24,20,22,19,31,21,17,18,32,13,15,16
//第六个数字从这14个数字中挑选:,32,33,30,31,29,28,27,26,25,24,23,22,18,21
//要求2:
//请输入第1个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第2个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第3个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第4个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第5个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第6个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//然后回车,输出结果到cp.txt
//要求3:
//保证同一组数据的数都不相同。
//比如,第一个数为6时,第二个数或其他的数都不能再为6;第二个数为10时,第三个数或其他的数都不能再为10,以此类推……
//要求4:
//增加一个条件:在产生的每个数组A1A2A3A4A5A6中,要求A1<A2<A3<A4<A5<A6
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int v[6];
int n[6]={12,17,21,20,19,14};
int d[6][30]={
      {1,3,2,4,5,6,7,8,9,10,11,12},
      {8,7,5,9,6,4,11,10,12,13,3,14,17,2,16,15,18},
      {13,10,15,16,18,11,14,12,7,19,21,17,8,22,9,20,6,23,5,24,25},
      {22,23,18,20,16,17,15,21,14,26,19,24,27,25,12,13,11,10,28,29},
      {26,25,27,29,30,28,23,24,20,22,19,31,21,17,18,32,13,15,16},
      {32,33,30,31,29,28,27,26,25,24,23,22,18,21},
};
int i,j,i0,i1,i2,i3,i4,i5,s;
char ln[100],*t;
FILE *f;
int main() {
    for (i=0;i<6;i++) {
        printf("请输入第%d个数字的选择范围:",i+1);
        fgets(ln,100,stdin);
        j=0;
        t=strtok(ln," ");
        while (1) {
            if (NULL==t) break;
            if (0==t[0]) continue;//跳过多个空格间隔时取出的空串
            d[i][j]=atoi(t);
            j++;
            if (j>=30) break;
            t=strtok(NULL," ");
        }
        n[i]=j;
    }
    f=fopen("cp.txt","w");
    if (NULL==f) {
        printf("无法生成cp.txt!\n");
        return 1;
    }
    printf("正在生成cp.txt...");
    for (i0=0;i0<n[0];i0++) {
    for (i1=0;i1<n[1];i1++) {
    for (i2=0;i2<n[2];i2++) {
    for (i3=0;i3<n[3];i3++) {
    for (i4=0;i4<n[4];i4++) {
    for (i5=0;i5<n[5];i5++) {
        v[0]=d[0][i0];
        v[1]=d[1][i1];
        v[2]=d[2][i2];
        v[3]=d[3][i3];
        v[4]=d[4][i4];
        v[5]=d[5][i5];
        if (0==(v[0]%2)
         && 0==(v[1]%2)
         && 0==(v[2]%2)
         && 0==(v[3]%2)
         && 0==(v[4]%2)
         && 0==(v[5]%2)) continue;//排除全部为偶数
        if (1==(v[0]%2)
         && 1==(v[1]%2)
         && 1==(v[2]%2)
         && 1==(v[3]%2)
         && 1==(v[4]%2)
         && 1==(v[5]%2)) continue;//排除全部为奇数
        for (i=0;i<5;i++) {
            for (j=i+1;j<6;j++) {
                if (v[i]==v[j]) goto NEXT;//保证同一组数据的数都不相同
            }
        }
    NEXT:
        if (i>=5) {
            for (i=0;i<5;i++) for (j=i+1;j<6;j++) if (v[i]>v[j]) {s=v[i];v[i]=v[j];v[j]=s;}//从小到大排序
            if ((v[0]+1==v[1]
              && v[1]+1==v[2]
              && v[2]+1==v[3])
             || (v[1]+1==v[2]
              && v[2]+1==v[3]
              && v[3]+1==v[4])
             || (v[2]+1==v[3]
              && v[3]+1==v[4]
              && v[4]+1==v[5])) continue;//排除四个数字递增连续
            fprintf(f,"%2d,%2d,%2d,%2d,%2d,%2d\n",v[0],v[1],v[2],v[3],v[4],v[5]);
        }
    }}}}}}
    fclose(f);
    printf("\n生成cp.txt完毕\n");
    return 0;
}
//如果文件in.txt的内容为
//1 3 2 4 5 6 7 8 9 10 11 12
//8 7 5 9 6 4 11 10 12 13 3 14 17 2 16 15 18
//13 10 15 16 18 11 14 12 7 19 21 17 8 22 9 20 6 23 5 24 25
//22 23 18 20 16 17 15 21 14 26 19 24 27 25 12 13 11 10 28 29
//26 25 27 29 30 28 23 24 20 22 19 31 21 17 18 32 13 15 16
//32 33 30 31 29 28 27 26 25 24 23 22 18 21
//可以在cmd窗口里面输入命令
//cp <in.txt
//得到要求1对应的结果
//BTW:中了一定要分我六成啊!嘿嘿!(^=^)
赵老师一如既往地犀利, 数十年如一日, 想当初10年前我刚进CSDN的时候,赵老师就犹如指路明灯,照耀着我一路从菜鸟变成了老鸟。
小湿哥 2021-05-25
  • 打赏
  • 举报
回复
引用 6 楼 早打大打打核战争 的回复:
还要保证生成50万个不同的随机数
确实 50万个,得用hash 或者 树 或者 跳表 的数据结构来保存 已有的随机数, 每次生成了一堆随机数,还得先做查重。
小湿哥 2021-05-25
  • 打赏
  • 举报
回复
引用 4 楼 NorZ 的回复:
等差数列只是一种例举的规律...是不是还有其他的规律?
问题简化,就只考虑等差吧。
  • 打赏
  • 举报
回复
还要保证生成50万个不同的随机数
NorZ 2021-05-25
  • 打赏
  • 举报
回复
等差数列只是一种例举的规律...是不是还有其他的规律?
赵4老师 2021-05-25
  • 打赏
  • 举报
回复
仅供参考:
//要求1:从给出来的不同的六组数字中,从每组任意挑选一个数字,最后组成一个六个数字的数组。
//将所有的数组全部列出来。
//同时,排除全部为偶数、全部为奇数的数组。
//排除四个数字递增连续(比如8、9、10、11)的数组。
//如下:
//第一个数字从这12个数字中挑选:,1,3,2,4,5,6,7,8,9,10,11,12
//第二个数字从这17个数字中挑选:,8,7,5,9,6,4,11,10,12,13,3,14,17,2,16,15,18
//第三个数字从这21个数字中挑选:,13,10,15,16,18,11,14,12,7,19,21,17,8,22,9,20,6,23,5,24,25
//第四个数字从这20个数字中挑选:,22,23,18,20,16,17,15,21,14,26,19,24,27,25,12,13,11,10,28,29
//第五个数字从这19个数字中挑选:,26,25,27,29,30,28,23,24,20,22,19,31,21,17,18,32,13,15,16
//第六个数字从这14个数字中挑选:,32,33,30,31,29,28,27,26,25,24,23,22,18,21
//要求2:
//请输入第1个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第2个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第3个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第4个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第5个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//请输入第6个数字的选择范围:(可以手动输入任意几个空格间隔的数字,最多30个)
//然后回车,输出结果到cp.txt
//要求3:
//保证同一组数据的数都不相同。
//比如,第一个数为6时,第二个数或其他的数都不能再为6;第二个数为10时,第三个数或其他的数都不能再为10,以此类推……
//要求4:
//增加一个条件:在产生的每个数组A1A2A3A4A5A6中,要求A1<A2<A3<A4<A5<A6
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int v[6];
int n[6]={12,17,21,20,19,14};
int d[6][30]={
      {1,3,2,4,5,6,7,8,9,10,11,12},
      {8,7,5,9,6,4,11,10,12,13,3,14,17,2,16,15,18},
      {13,10,15,16,18,11,14,12,7,19,21,17,8,22,9,20,6,23,5,24,25},
      {22,23,18,20,16,17,15,21,14,26,19,24,27,25,12,13,11,10,28,29},
      {26,25,27,29,30,28,23,24,20,22,19,31,21,17,18,32,13,15,16},
      {32,33,30,31,29,28,27,26,25,24,23,22,18,21},
};
int i,j,i0,i1,i2,i3,i4,i5,s;
char ln[100],*t;
FILE *f;
int main() {
    for (i=0;i<6;i++) {
        printf("请输入第%d个数字的选择范围:",i+1);
        fgets(ln,100,stdin);
        j=0;
        t=strtok(ln," ");
        while (1) {
            if (NULL==t) break;
            if (0==t[0]) continue;//跳过多个空格间隔时取出的空串
            d[i][j]=atoi(t);
            j++;
            if (j>=30) break;
            t=strtok(NULL," ");
        }
        n[i]=j;
    }
    f=fopen("cp.txt","w");
    if (NULL==f) {
        printf("无法生成cp.txt!\n");
        return 1;
    }
    printf("正在生成cp.txt...");
    for (i0=0;i0<n[0];i0++) {
    for (i1=0;i1<n[1];i1++) {
    for (i2=0;i2<n[2];i2++) {
    for (i3=0;i3<n[3];i3++) {
    for (i4=0;i4<n[4];i4++) {
    for (i5=0;i5<n[5];i5++) {
        v[0]=d[0][i0];
        v[1]=d[1][i1];
        v[2]=d[2][i2];
        v[3]=d[3][i3];
        v[4]=d[4][i4];
        v[5]=d[5][i5];
        if (0==(v[0]%2)
         && 0==(v[1]%2)
         && 0==(v[2]%2)
         && 0==(v[3]%2)
         && 0==(v[4]%2)
         && 0==(v[5]%2)) continue;//排除全部为偶数
        if (1==(v[0]%2)
         && 1==(v[1]%2)
         && 1==(v[2]%2)
         && 1==(v[3]%2)
         && 1==(v[4]%2)
         && 1==(v[5]%2)) continue;//排除全部为奇数
        for (i=0;i<5;i++) {
            for (j=i+1;j<6;j++) {
                if (v[i]==v[j]) goto NEXT;//保证同一组数据的数都不相同
            }
        }
    NEXT:
        if (i>=5) {
            for (i=0;i<5;i++) for (j=i+1;j<6;j++) if (v[i]>v[j]) {s=v[i];v[i]=v[j];v[j]=s;}//从小到大排序
            if ((v[0]+1==v[1]
              && v[1]+1==v[2]
              && v[2]+1==v[3])
             || (v[1]+1==v[2]
              && v[2]+1==v[3]
              && v[3]+1==v[4])
             || (v[2]+1==v[3]
              && v[3]+1==v[4]
              && v[4]+1==v[5])) continue;//排除四个数字递增连续
            fprintf(f,"%2d,%2d,%2d,%2d,%2d,%2d\n",v[0],v[1],v[2],v[3],v[4],v[5]);
        }
    }}}}}}
    fclose(f);
    printf("\n生成cp.txt完毕\n");
    return 0;
}
//如果文件in.txt的内容为
//1 3 2 4 5 6 7 8 9 10 11 12
//8 7 5 9 6 4 11 10 12 13 3 14 17 2 16 15 18
//13 10 15 16 18 11 14 12 7 19 21 17 8 22 9 20 6 23 5 24 25
//22 23 18 20 16 17 15 21 14 26 19 24 27 25 12 13 11 10 28 29
//26 25 27 29 30 28 23 24 20 22 19 31 21 17 18 32 13 15 16
//32 33 30 31 29 28 27 26 25 24 23 22 18 21
//可以在cmd窗口里面输入命令
//cp <in.txt
//得到要求1对应的结果
//BTW:中了一定要分我六成啊!嘿嘿!(^=^)
lin5161678 2021-05-25
  • 打赏
  • 举报
回复
分段随机就可以了 先随机6-15 作为位数 然后每次随机1位数作为组成部分 每次随机检查会不会重复前面的数字 会不会和前面的数字连号 就可以了
lin5161678 2021-05-25
  • 打赏
  • 举报
回复
第二步 每个字符串从头到尾遍历,检查是否有三个连续数字一致,同时也检查是否有连续3个连号。 若有则该数失败。 别失败呀 签名那么多步骤 别浪费了 你交换一下不就不会失败了么 比如 111234 交换一下变成 121314 不就完事了
内容概要:本文围绕发光太阳聚光器开展蒙特卡洛光线追踪研究,重点利用Matlab编程实现光线在聚光系统中的传播路径模拟。通过蒙特卡洛方法对大量随机光线进行统计追踪,精确分析光能在接收面上的分布特性、聚焦效率及系统整体光学性能,进而评估不同几何结构与材料参数对聚光效果的影响,为高效太阳能收集系统的设计与优化提供理论依据和技术支持。研究不仅涵盖核心算法实现,还结合多个跨领域科研案例(如电力系统、路径规划、信号处理、机器学习等),展示了Matlab/Simulink在科研建模与仿真中的广泛应用价值,突出了算法仿真与多学科交叉融合的重要性。; 适合人群:具备一定Matlab编程基础,从事光学工程、新能源技术、仿真建模及相关领域研究的科研人员,尤其适合研究生及青年研究人员。; 使用场景及目标:①掌握蒙特卡洛方法在光学系统仿真中的原理与应用;②学习使用Matlab实现光线发射、反射、折射及能量统计的完整追踪流程;③通过实际代码实践优化聚光器结构设计;④借鉴文中多领域仿真案例,拓展科研视野与技术迁移能力; 阅读建议:此资源以代码实现为核心,建议读者结合Matlab环境动手运行与调试程序,重点关注光线追踪的物理建模与数值计算细节,并参照其他仿真范例举一反三,全面提升科研建模与算法实现能力。
内容概要:本文复现并深入探讨了一种基于价格弹性矩阵的居民峰谷分时电价激励策略,属于电力系统需求响应领域的关键技术研究。研究通过构建价格弹性矩阵精确刻画居民用户对不同时段电价变化的用电行为响应特性,结合优化算法设计科学合理的峰谷分时电价方案,有效引导用户在高峰时段减少用电、低谷时段增加用电,实现削峰填谷,提升电网运行稳定性与能源利用效率。文中配套提供了完整的Matlab代码实现,涵盖数据处理、模型构建、优化求解及结果可视化等模块,具有较强的可复现性与工程应用价值,适用于需求侧管理政策仿真与学术研究。; 适合人群:面向具备一定电力系统基础知识、能源经济学或需求响应研究背景的科研人员,以及从事相关课题的硕士、博士研究生;熟悉Matlab编程且关注智能电网优化的技术人员亦可从中获益。; 使用场景及目标:①用于居民侧用电行为建模与电价敏感性分析;②支撑峰谷电价政策的设计、仿真评估与优化调整;③作为高校教学中需求响应机制的算法实现案例与科研入门实践项目。; 阅读建议:建议读者结合Matlab代码逐模块解析其实现逻辑,重点掌握价格弹性矩阵的构造方法、目标函数与约束条件的数学建模过程,以及优化求解器的调用方式,同时可尝试引入其他智能优化算法进行对比实验,以深化对电价激励机制设计原理的理解与创新能力。

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧