今天面试遇到的最后一题,求解题思路

的费时费工 2015-12-14 06:08:33
利用0,1,2,3,4,5,6,7,8,9 共十个数字和运算符+,-,X(乘),/(除) ,还有括号(), 构成表达式,要求其计算结果是1,其中十个数字每一个都需要用到,但是不能重复,运算符可以重复,不需要全部用到。请写程序输出所有可能的表达式,如果不存在的话,就输出“不存在”。
...全文
316 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
的费时费工 2016-04-09
  • 打赏
  • 举报
回复
引用 8 楼 zhao4zhong1 的回复:
仅供参考:
//给出2~12个数加括号改变运算顺序的所有方案
//例如:
//输入2,输出
//(1+2)
//输入3,输出
//((1+2)+3)
//(1+(2+3))
//输入4,输出
//(((1+2)+3)+4)
//((1+(2+3))+4)
//((1+2)+(3+4))
//(1+((2+3)+4))
//(1+(2+(3+4)))
//依此类推
//
//解题思路:
//后缀表达式转中缀表达式
//后缀表达式总是前2个是数字, 最后一个是运算符, 中间是各 n-2 个数字和运算符,
//程序里用一个bit表示后缀表达式中是出现数字还是运算符, 1表示数字, 0表示运算符,
//check检查是否是合法的表达式
//output把后缀表达式转成中缀表达式输出
//中缀表达式好像除了给人看也没啥用, 如果是具体计算就完全不用转中缀表达式了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int b1c( unsigned x ) {
    x = (x&0x55555555) + ((x&0xaaaaaaaa)>>1);
    x = (x&0x33333333) + ((x&0xcccccccc)>>2);
    x = (x&0x0f0f0f0f) + ((x&0xf0f0f0f0)>>4);
    x = (x&0x00ff00ff) + ((x&0xff00ff00)>>8);
    x = (x&0x0000ffff) + ((x&0xffff0000)>>16);
    return x;
}
int check(int n, int v) {
    int c = 1;

    n-=2;
    while (n--) {
        if (v & (1<<(2*n + 1)))
            ++c;
        else if (--c < 0)
            return 0;
        if (v & (1<<2*n))
            ++c;
        else if (--c < 0)
            return 0;
    }
    return 1;
}
void output(int idx, int n, int v) {
    char s_expr[16][80], expr_r[80], expr[80], *pi, *po;
    int  stack[16], ne = 1, ns = 2;

    strcpy(s_expr[0], ".");
    stack[0] = stack[1] = 0;
    n = 2 * (n-2);
    while (n--) {
        if (v & (1<<n)) {
            stack[ns++] = 0;
        } else {
            --ns;
            sprintf(s_expr[ne], "(%s+%s)", s_expr[stack[ns-1]], s_expr[stack[ns]]);
            stack[ns-1] = ne++;
        }
    }
    sprintf(expr_r, "(%s+%s)", s_expr[stack[0]], s_expr[stack[1]]);
    for (n = 0, pi = expr_r, po = expr; *pi; ++pi, ++po) {
        if ('.' == *pi) {
            ++n;
            if (n < 10) {
                *po = '0' + n;
            } else {
                *po++ = '1';
                *po   = '0' + n - 10;
            }
        } else {
            *po = *pi;
        }
    }
    *po = 0;
    printf("%8d: %s\n", idx, expr);
}
int main(int argc, char* argv[]) {
    int n = 8, nmx, i, idx = 0;

    if (argc == 2) n = atoi(argv[1]);
    if (n < 2 || n > 16) n = 8;
    nmx = 1 << 2 * (n-2);
    for (i = 0; i < nmx; ++i) {
        if (b1c(i) == n - 2 && check(n, i))
            output(idx++, n, i);
    }
    return 0;
}
还是赵老师66666
赵4老师 2015-12-16
  • 打赏
  • 举报
回复
仅供参考:
//给出2~12个数加括号改变运算顺序的所有方案
//例如:
//输入2,输出
//(1+2)
//输入3,输出
//((1+2)+3)
//(1+(2+3))
//输入4,输出
//(((1+2)+3)+4)
//((1+(2+3))+4)
//((1+2)+(3+4))
//(1+((2+3)+4))
//(1+(2+(3+4)))
//依此类推
//
//解题思路:
//后缀表达式转中缀表达式
//后缀表达式总是前2个是数字, 最后一个是运算符, 中间是各 n-2 个数字和运算符,
//程序里用一个bit表示后缀表达式中是出现数字还是运算符, 1表示数字, 0表示运算符,
//check检查是否是合法的表达式
//output把后缀表达式转成中缀表达式输出
//中缀表达式好像除了给人看也没啥用, 如果是具体计算就完全不用转中缀表达式了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int b1c( unsigned x ) {
    x = (x&0x55555555) + ((x&0xaaaaaaaa)>>1);
    x = (x&0x33333333) + ((x&0xcccccccc)>>2);
    x = (x&0x0f0f0f0f) + ((x&0xf0f0f0f0)>>4);
    x = (x&0x00ff00ff) + ((x&0xff00ff00)>>8);
    x = (x&0x0000ffff) + ((x&0xffff0000)>>16);
    return x;
}
int check(int n, int v) {
    int c = 1;

    n-=2;
    while (n--) {
        if (v & (1<<(2*n + 1)))
            ++c;
        else if (--c < 0)
            return 0;
        if (v & (1<<2*n))
            ++c;
        else if (--c < 0)
            return 0;
    }
    return 1;
}
void output(int idx, int n, int v) {
    char s_expr[16][80], expr_r[80], expr[80], *pi, *po;
    int  stack[16], ne = 1, ns = 2;

    strcpy(s_expr[0], ".");
    stack[0] = stack[1] = 0;
    n = 2 * (n-2);
    while (n--) {
        if (v & (1<<n)) {
            stack[ns++] = 0;
        } else {
            --ns;
            sprintf(s_expr[ne], "(%s+%s)", s_expr[stack[ns-1]], s_expr[stack[ns]]);
            stack[ns-1] = ne++;
        }
    }
    sprintf(expr_r, "(%s+%s)", s_expr[stack[0]], s_expr[stack[1]]);
    for (n = 0, pi = expr_r, po = expr; *pi; ++pi, ++po) {
        if ('.' == *pi) {
            ++n;
            if (n < 10) {
                *po = '0' + n;
            } else {
                *po++ = '1';
                *po   = '0' + n - 10;
            }
        } else {
            *po = *pi;
        }
    }
    *po = 0;
    printf("%8d: %s\n", idx, expr);
}
int main(int argc, char* argv[]) {
    int n = 8, nmx, i, idx = 0;

    if (argc == 2) n = atoi(argv[1]);
    if (n < 2 || n > 16) n = 8;
    nmx = 1 << 2 * (n-2);
    for (i = 0; i < nmx; ++i) {
        if (b1c(i) == n - 2 && check(n, i))
            output(idx++, n, i);
    }
    return 0;
}
looklzg1108 2015-12-16
  • 打赏
  • 举报
回复
0 1 2 3 4 5 6 7 8 9 排列 362880
()添加 C(9-1) * C(9-2) ......* C(9-8) * C(9-9) 组合 = 9^6 * 8^3 * 7^4 * 6^2 = 23519044749312
+-*/ 添加 4^9 = 262144

合计 362880*262144*23519044749312 = ()种排列组合,然后编写计算器来计算即可。
looklzg1108 2015-12-16
  • 打赏
  • 举报
回复
0 1 2 3 4 5 6 7 8 9 排列 362880
()添加 C(9-1) * C(9-2) ......* C(9-8) * C(9-9) 组合 = 9^6 * 8^3 * 7^4 * 6^2 = 23519044749312
+-*/ 添加 4*4*4*4*4*4*3*2*1 = 4096*6 = 24576

合计 362880*24576*23519044749312 = ()种排列组合,然后编写计算器来计算即可。
lm_whales 2015-12-16
  • 打赏
  • 举报
回复
引用 8 楼 zhao4zhong1 的回复:
仅供参考:
//给出2~12个数加括号改变运算顺序的所有方案
//例如:
//输入2,输出
//(1+2)
//输入3,输出
//((1+2)+3)
//(1+(2+3))
//输入4,输出
//(((1+2)+3)+4)
//((1+(2+3))+4)
//((1+2)+(3+4))
//(1+((2+3)+4))
//(1+(2+(3+4)))
//依此类推
//
//解题思路:
//后缀表达式转中缀表达式
//后缀表达式总是前2个是数字, 最后一个是运算符, 中间是各 n-2 个数字和运算符,
//程序里用一个bit表示后缀表达式中是出现数字还是运算符, 1表示数字, 0表示运算符,
//check检查是否是合法的表达式
//output把后缀表达式转成中缀表达式输出
//中缀表达式好像除了给人看也没啥用, 如果是具体计算就完全不用转中缀表达式了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int b1c( unsigned x ) {
    x = (x&0x55555555) + ((x&0xaaaaaaaa)>>1);
    x = (x&0x33333333) + ((x&0xcccccccc)>>2);
    x = (x&0x0f0f0f0f) + ((x&0xf0f0f0f0)>>4);
    x = (x&0x00ff00ff) + ((x&0xff00ff00)>>8);
    x = (x&0x0000ffff) + ((x&0xffff0000)>>16);
    return x;
}
int check(int n, int v) {
    int c = 1;

    n-=2;
    while (n--) {
        if (v & (1<<(2*n + 1)))
            ++c;
        else if (--c < 0)
            return 0;
        if (v & (1<<2*n))
            ++c;
        else if (--c < 0)
            return 0;
    }
    return 1;
}
void output(int idx, int n, int v) {
    char s_expr[16][80], expr_r[80], expr[80], *pi, *po;
    int  stack[16], ne = 1, ns = 2;

    strcpy(s_expr[0], ".");
    stack[0] = stack[1] = 0;
    n = 2 * (n-2);
    while (n--) {
        if (v & (1<<n)) {
            stack[ns++] = 0;
        } else {
            --ns;
            sprintf(s_expr[ne], "(%s+%s)", s_expr[stack[ns-1]], s_expr[stack[ns]]);
            stack[ns-1] = ne++;
        }
    }
    sprintf(expr_r, "(%s+%s)", s_expr[stack[0]], s_expr[stack[1]]);
    for (n = 0, pi = expr_r, po = expr; *pi; ++pi, ++po) {
        if ('.' == *pi) {
            ++n;
            if (n < 10) {
                *po = '0' + n;
            } else {
                *po++ = '1';
                *po   = '0' + n - 10;
            }
        } else {
            *po = *pi;
        }
    }
    *po = 0;
    printf("%8d: %s\n", idx, expr);
}
int main(int argc, char* argv[]) {
    int n = 8, nmx, i, idx = 0;

    if (argc == 2) n = atoi(argv[1]);
    if (n < 2 || n > 16) n = 8;
    nmx = 1 << 2 * (n-2);
    for (i = 0; i < nmx; ++i) {
        if (b1c(i) == n - 2 && check(n, i))
            output(idx++, n, i);
    }
    return 0;
}
++
cooaa 2015-12-16
  • 打赏
  • 举报
回复
就是两个排列组合: 0-9 的所有排列组合() {+,-*,/} 可重复的10位长排列组合。 然后 两个组合交叉 组成表达式,并输出结果。 不用考虑括号,所有的都不考虑操作符优先级。 最后输出的时候,再计算括号的输出。
lm_whales 2015-12-15
  • 打赏
  • 举报
回复
一种简单的方式,先排列出一个 0 1 2 3 4 5 6 7 8 9 然后 插入 符号形成字符串 最后解析表达式 +-不能出现在最后。 */不能在前面,后面。 () 可以任意插入,但每个(必有一个)也就是说,必须同时确定左右括号的位置。 不可出现(( 互相对应的两对左右括号在同一位置 )) 可插入符号位置共有11处 括号和+-号 不能无穷添加。。。。很有可能的哦。考虑一下这个吧(+(-(+(-12))))
qq20004604 2015-12-15
  • 打赏
  • 举报
回复
不止排列组合吧,我觉得不加括号还简单点,加了括号就超级复杂。 个人觉得,先考虑和,比如1个数的和(就是数本身),2个数的和,3个数的和,一直到10个数的和(就是10个数相加) 比如10个1个数的和相加,相减,相乘,相处。 然后1个2个数的和,和8个1个数的和相+-*/; 然后2个2个数,其他1个数; 然后3个2个数,……; 5个2个数,; 1个3个数; 好吧。。我想不下去了。。。实现也有点难的样子
looklzg1108 2015-12-15
  • 打赏
  • 举报
回复
排列组合问题吧.

期待大神解答。
用电脑算了下10的排列组合,貌似都是需要很长时间。
不知道 0 12 3 4 5 6 7 8 9 / * - + ( )需要多久

64,646

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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