【问题标题】:How to count how many different nodes are in my linkedlist?如何计算我的链表中有多少个不同的节点?
【发布时间】:2013-03-27 23:08:49
【问题描述】:

我创建了自己的 Node 类和我自己的 LinkedList 类,我想构建一个函数来计算我的 LinkedList 中有多少不同的 Node。

我已尝试使用此代码,但它不起作用:

for (int i = 0; i < quantityOfNode(); i++) {
    boolean isDistinct = true;

    for (int j = 0; j < i; j++) {
        if (node.getInfo().equals(node.getNext().getInfo())) {
            isDistinct = false;
        }
    }
    if (isDistinct) {
        nbDistinct++;
    }
    if (node.getNext().getNext() != null) {
        node= node.getNext();
    }
}

示例:

        list.add(3);
    list.add(2);
    list.add(5);
    list.add(3);
    list.add(3);
    list.add(8);

这应该给我 4 个不同的节点,但我得到 5 个,因为节点 3 被计算了 2 次​​p>

现在我尝试在我的 j 循环中使用第二个节点旅行,对于相同的输入,它现在给我 2 而不是 4

这是我尝试过但仍然无法正常工作的新代码:

            for (int i = 0; i < quantityOfNode(); i++) {
            boolean isDistinct = true;
            for (int j = 0; j < i; j++) {
                if (node.getInfo().equals(node2.getInfo())) {
                    isDistinct = false;

                }

                if (node2.getNext() != null) {
                    node2 = node2.getNext();
                }

            }
            if (isDistinct) {
                nbDistinct++;
            }
            if (node.getNext() != null) {
                node= node.getNext();
            }
        }

【问题讨论】:

  • 在什么情况下不起作用?举例说明输入和预期输出和实际输出。
  • length() 方法有什么作用?
  • list.add(3); list.add(2); list.add(5); list.add(3); list.add(3); list.add(8);我想有 4 个不同的节点,但我得到了 5 个
  • list.add(x) 是添加到开头还是结尾。
  • 它添加在链表的末尾

标签: java collections linked-list nodes


【解决方案1】:

第一个问题:

如果你的 for 循环写得不超过链表的长度:

for (int i = 0; i &lt; length(); i++) {

那你为什么需要这个?

            if (node.getNext().getNext() != null) {
                node= node.getNext();
            }

特别是,这段代码可能意味着结束之前的一个节点被计算两次,因为它后面的节点是null。这不一定会让你的算法出错,但它闻起来很糟糕,我不喜欢它。

第二个问题:

            for (int j = 0; j < i; j++) {
                if (node.getInfo().equals(node.getNext().getInfo())) {
                    isDistinct = false;
                }
            }

这是一种计算重复项的错误方法,因为您没有存储和推进要比较的第二个节点的位置。尝试类似

            Node node2 = firstNode(); //idk what method gets the first node :)
            for (int j = 0; j < i; j++) {
                if (node.getInfo().equals(node2.getInfo())) {
                    isDistinct = false;
                    break; //optimization, stop as soon as we find a duplicate
                }
                node2 = node2.GetNext();
            }

最后,每当遇到无法运行的代码时,请附加一个调试器,单步调试它,并注意代码何时没有按照您的预期运行。这将通过以下方式快速解决所有逻辑错误只是少量的观察。即使您无法访问调试器,您也可以使用print 语句打印各种变量的值以及某些代码分支何时执行并与您预期的结果进行比较。

【讨论】:

  • 他使用双 for 循环将每个元素与其他元素进行比较。
  • @corsiKa 他只检查列表中比当前节点更早的节点,以便您正确计算重复节点的第一个实例并跳过所有其他实例。另外,它没有工作,因为它没有第二个节点在列表中前进,它只会一遍又一遍地将该节点与其下一个节点进行比较i 次。
  • @Patashu 所以你建议我为我的 j 循环添加另一个节点?
  • @Patashu 你能告诉我更多关于添加另一个节点的信息吗?你的意思是我创建另一个节点,从我的链表开始,并与 j 循环一起旅行??
  • @phaaon450 请检查我回答中的第四个代码 sn-p。是的,您创建了第二个节点,该节点从开头开始并与 j 循环一起传播 - 这样您就可以将节点 i 与节点 0、节点 1、节点 2... 与节点 i-1 进行比较,对于每个值j,在节点 i 之前停止,因此您不会将该节点与自身进行比较。
【解决方案2】:

你可以使用一个集合。

Set set = new HashSet();
Node cur = list.head;
while(cur != null) {
    set.add(cur.getInfo());
    cur = cur.getNext();
}
return set.size();

这不使用泛型,因为我不知道你有什么类型的 getInfo。

或者,如果您不能使用集合,您应该尝试摆脱您的“索引”变量(i 和 j)。您确实希望将应用程序逻辑集中在您实际拥有的东西上,而不是隐式计算的值。您希望在当前节点变为空时停止,而不是在您前进一定次数时停止。如果这不合逻辑,请告诉我。

对于每个节点,检查它之前的节点以查看该节点是否存在。我每次都从头开始,因为我不知道你是否有双链接。无论哪种方式,它的复杂性都相同,但在排序列表上,这不是最佳的。

Node cur = list.head; // for each node
int nbDistinct = 0;
while(cur != null) { // go until we're out of nodes
    Node check = list.head; // check the first node
    boolean isDistinct = true; // assume distinct
    while(check != cur && isDistinct) { // stop if we found a match OR if our checker caught up to our current node
        isDistinct |= !check.getInfo().equals(cur.getInfo()); // essentially "if(check.getInfo().equals(cur.getInfo()) isDistinct = true;"
        check = check.getNext(); // advance the checker
    }
    if(isDistinct) nbDistinct++;
    cur = cur.getNext(); // advance the current node
}

【讨论】:

  • 对不起,我不知道 Set 所以我试图不使用它,但谢谢你
  • 我还有一个替代解决方案,带有评论。
  • 我会试试的,谢谢,但你能告诉我为什么我找到匹配项时要停下来吗?我的目标是知道我的链表中有多少不同的节点
  • 当你找到匹配时你会停下来,因为isDistinct 永远不会变得比现在更真实。
【解决方案3】:

您的 j 循环没有向前推进 node - 它总是比较同一对节点,因此没有任何功能。

你需要这样的东西:

...
Node earlierNode = rootNode;
for (int j = 0; j < i; j++) {
    if (earlierNode.getInfo().equals(node.getInfo())) {
        isDistinct = false;
    }
    earlierNode = earlierNode.getNext();
}
...

【讨论】:

  • @phaaon450 - 添加了建议。
  • 谢谢你,我还在尝试它仍然不起作用:(也许有什么方法可以和你聊天,我是这个网站的新手
  • 我认为你应该试试@Patashu 的建议。该答案涵盖了您遇到的问题。或许你的旧代码之后发布你的新代码,看看你现在哪里错了。
  • 我发布了新代码,但它仍然无法正常工作,它给了我 2,而不是 4
  • 您还没有在j 循环中将新的Node 推向列表。在我建议Node earlierNode = rootNode; for (int j = 0; j &lt; i; j++) { 的地方查看我的代码,在他建议Node node2 = firstNode(); for (int j = 0; j &lt; i; j++) { 的地方查看@Patashu 的代码
【解决方案4】:

使用集合

Set<Node> mySet = new HashSet<Node>(list);
answer = mySet.size();

这取决于您在节点类中实现 hashCode 和 equals,或者您可以使用 TreeSet 和 Comparator。

Comparator<Node> myComparator = new MyCustomComparator();// you have to define your comparator.
Set<Node> mySet = new TreeSet<Node>(myComparator);
mySet.addAll(list);
answer = mySet.size();

【讨论】:

  • 对不起,我不知道 Set,所以我不能使用它,但谢谢
【解决方案5】:

您第一次围绕 i 循环时,您的 j 循环什么都不做(因为它从 0 开始并继续,而 j &lt; i 不是)所以您将 distinct 设置为 true 而不将任何内容与任何内容进行比较.

尝试从 1 点开始 i

【讨论】:

  • 您误解了第二个循环的要点 - 它的目的是查看该节点在列表中是否有任何重复项 EARLIER 比它。您的建议将使每个节点也与自身进行比较,因此没有节点会被视为不重复。,
  • 您仍然会在第一次时增加 nbDistinct 一次,而无需将任何内容与任何内容进行比较。
  • @OldCurmudgeon 是,因为第一个节点是离散的
  • @phaaon450 - 你是对的 - 看看我的第二个想法here
猜你喜欢
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多