首页 > 解决方案 > 嵌套循环和飞镖内存不足

问题描述

我尝试使用嵌套 for 循环中的重复数据删除代码制作一个简单的随机数生成器程序。但是当我尝试在 dartpad 或 android studio 上运行这段代码时,工作了两三遍,然后,我收到了“内存不足”的消息。我的代码有问题吗?

import 'dart:math';

void main() {
  final myNum = <int>[];
  final random = Random();
  int num;

  for (int i = 0; i < 6; i++) {
    num = random.nextInt(45) + 1;
    myNum.add(num);

    for (int j = 0; j < i; j++) {
      if (myNum[i] == myNum[j]) {
        i--;
        break;
      }
    }
  }

  print(myNum);
}

标签: dartrandomout-of-memory

解决方案


原因是 DartPad 仅在没有更多工作要做时才首先显示输出(例如等待异步或程序完成)。

在您的情况下,您的程序包含一个无限循环,因此程序将无休止地运行,不断将元素添加到列表中,直到内存不足。如果您在程序中添加一些额外的日志记录并在 DartVM 中运行它,则可以看到这一点,它会在程序运行时打印。

你的问题可以在这里找到:

    for(int j=0; j<i; j++){
      if(myNum[i]==myNum[j]){
        i--;
        break;
      }
    }

有更好的方法来检测多个值(有些人可能会争辩使用 aSet代替),但主要问题是您永远不会从列表中删除检测到的元素。相反,您只是在倒计时i。将元素插入您正在使用的列表中时:

    myNum.add(num);

这只是继续将元素添加到现有的值列表中。因此,您的程序运行良好,直到if(myNum[i]==myNum[j])为真,这将随机发生(而且很多时间永远不会发生,这就是为什么您的程序通常看起来很好)。

您应该将 a 添加myNum.removeLast()到您的逻辑中,如下所示:

    for (int j = 0; j < i; j++) {
      if (myNum[i] == myNum[j]) {
        i--;
        myNum.removeLast();
        break;
      }
    }

然后它按预期工作。

更新更简单的解决方案示例

ASet不能多次包含相同的值。因此,如果我们尝试插入一个已经是长度的一部分的元素,Set则不会改变。所以我们基本上可以做到以下几点:

import 'dart:math';

void main() {
  final myNum = <int>{};
  final random = Random();

  while (myNum.length != 6) {
    myNum.add(random.nextInt(45) + 1);
  }

  print(myNum.toList()); // [2, 23, 40, 35, 39, 22]
}

更短的解决方案

如果您想最小化代码并获得稳定的执行时间,您还可以执行以下操作:

void main() {
  print((List.generate(45, (index) => ++index)..shuffle()).sublist(0, 6)); // [6, 41, 12, 2, 11, 42]
}

推荐阅读