如何用栈生成各出现4次的1-6随机数(共24个,禁用数组)
如何用栈构造包含1-6各4次的24元素栈
首先,咱们先聊聊你原来的代码问题出在哪:你是先给计数器加1,再判断能不能入栈,这就会导致某个数字已经达到4次上限后,再生成它时计数器会被错误地加到5+,之后再也无法通过判断,最后栈可能填不满24个元素——因为这个数字的计数器已经“虚高”了,实际栈里它只有4次,但计数器显示的是更高的数,后续生成它时永远不会被允许入栈。
修正后的计数器实现方法
其实只要调整一下逻辑顺序:先判断当前数字的计数是否还没到4,只有满足这个条件,再把它push进栈,然后更新计数器。这样计数器的数值就和栈里实际的元素数量完全对应了。代码大概是这样:
// 初始化每个数字的计数,一开始都是0 int count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0, count6 = 0; Random rnd = new Random(); Stack<Integer> ottf = new Stack<>(); while (!ottf.isFull()) { int x = rnd.nextInt(6) + 1; // 先判断当前数字的计数是否小于4 boolean canPush = switch(x) { case 1 -> count1 < 4; case 2 -> count2 < 4; case 3 -> count3 < 4; case 4 -> count4 < 4; case 5 -> count5 < 4; case 6 -> count6 < 4; default -> false; }; if (canPush) { ottf.push(x); // 只有push成功后才更新计数器 switch(x) { case 1 -> count1++; case 2 -> count2++; case 3 -> count3++; case 4 -> count4++; case 5 -> count5++; case 6 -> count6++; } } }
如果你的Java版本不支持switch表达式,换成if-else也完全没问题:
while (!ottf.isFull()) { int x = rnd.nextInt(6) + 1; boolean canPush = false; if (x == 1 && count1 < 4) canPush = true; else if (x == 2 && count2 < 4) canPush = true; else if (x == 3 && count3 < 4) canPush = true; else if (x == 4 && count4 < 4) canPush = true; else if (x == 5 && count5 < 4) canPush = true; else if (x == 6 && count6 < 4) canPush = true; if (canPush) { ottf.push(x); if (x == 1) count1++; else if (x == 2) count2++; else if (x == 3) count3++; else if (x == 4) count4++; else if (x == 5) count5++; else count6++; } }
这个方法的核心是计数器只在元素成功入栈后才递增,这样计数器永远准确反映栈里对应数字的数量,不会出现“计数超了但实际没入栈”的情况,最后肯定能填满24个元素。
只用栈(无单独计数器)的实现思路
如果严格要求“只能用栈,不能用单独的计数器变量”,咱们可以用一个辅助栈来记录每个数字的剩余可入栈次数:
- 首先,创建一个辅助栈,把
[4,4,4,4,4,4]依次push进去(分别对应1-6的剩余次数,栈底对应1的次数,栈顶对应6的次数)。 - 循环直到目标栈填满:
- 生成1-6的随机数x,为了获取它的剩余次数,需要把辅助栈中前
x-1个元素暂时移到临时栈中,取出第x个元素(剩余次数)。 - 如果剩余次数大于0,就把xpush进目标栈,然后把剩余次数减1后放回辅助栈,再把临时栈的元素移回辅助栈。
- 如果剩余次数为0,就直接把临时栈的元素移回辅助栈,重新生成随机数。
- 生成1-6的随机数x,为了获取它的剩余次数,需要把辅助栈中前
不过说实话,这种方法比用计数器麻烦很多,而且可读性差,除非有特殊要求,否则上面的计数器方法是最直接高效的。
内容的提问来源于stack exchange,提问作者Ersun Yanal
相关产品推荐
相关产品推荐

