【问题标题】:variable loses value outside while loop - Javascript变量在while循环外失去价值 - Javascript
【发布时间】:2019-01-19 06:02:42
【问题描述】:

我正在尝试解决这个涉及链表的问题。对链表进行分区,使小于分区的值首先出现,然后是等于或大于分区的值。

例子:

input: 90 -> 30 -> 40 -> 50 -> 100 -> 40
partition: 50
output: 30 -> 40 -> 40 -> 50 -> 100 -> 90

小于分区(50)的所有节点都在所有大于分区(50)的节点之前。

function partitionLl(node) {
  let list = {
    "head": {
      "data": 90,
      "next": {
        "data": 30,
        "next": {
          "data": 40,
          "next": {
            "data": 50,
            "next": {
              "data": 100,
              "next": {
                "data": 40,
                "next": {
                  "data": 15,
                  "next": {
                    "data": 90,
                    "next": {
                      "data": 200,
                      "next": {
                        "data": 90,
                        "next": {
                          "data": 10,
                          "next": {
                            "data": 90,
                            "next": null
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  let test;
  let current = list.head;
  let p1 = {
    data: null,
    next: null
  };
  let p2 = current;

  while (current !== null) {
    if (current.data < node) {
      p1 = current;
      p1 = p1.next;
    } else {
      p2 = current;
      p2 = p2.next;
    }

    current = current.next;
  }
  console.log(p1)
  console.log(p2)

}

partitionLl(50)

这是我拥有的代码,我想要获得的列表在循环中非常棒,它有我需要的列表。问题是我需要在循环完成时附加这些列表(p1 和 p2),但是在 while 循环之外,变量记录的内容完全不同且不准确。

当前变量在循环内部和外部都被跟踪。不知道为什么会这样,或者可能有什么样的范围循环会导致这种情况。我将如何访问循环之外的值?

【问题讨论】:

  • 请同时添加想要的结果。最后一个节点应该去哪里?你想得到一棵树而不是一个链表吗?
  • 是的,刚刚编辑了评论。
  • “记录完全不同的东西”是什么意思?你能告诉我们你得到了什么吗?
  • 为什么第一个 grreter 值出现在列表末尾?为什么不维持秩序?

标签: javascript algorithm loops while-loop linked-list


【解决方案1】:

OPs 程序的问题在于它实际上从未更改列表,也不会为结果构建新列表,即不会发生对数据或下一个属性的分配。只有“指针” p1 和 p2 被移动,直到到达列表的末尾。赋值的方式,无论是p1,还是p2,最终都必然为null。

一种解决方案是创建当前元素的副本,并通过设置 next 属性将它们附加到 p1 或 p2。

像这样:

function partitionLl(node) {
  let list = {
    "head": {
      "data": 90,
      "next": {
        "data": 30,
        "next": {
          "data": 40,
          "next": {
            "data": 50,
            "next": {
              "data": 100,
              "next": {
                "data": 40,
                "next": {
                  "data": 15,
                  "next": {
                    "data": 90,
                    "next": {
                      "data": 200,
                      "next": {
                        "data": 90,
                        "next": {
                          "data": 10,
                          "next": {
                            "data": 90,
                            "next": null
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

    let p1 = {
        "head": null
    }
    let t1 = p1.head
    let p2 = {
        "head": null
    }
    let t2 = p2.head
    let current = list.head
    while (current !== null) {
      if (current.data < node) {

          if(p1.head === null) {
              p1.head = {
                  "data": current.data,
                  "next": null
              }
              t1 = p1.head
          } else {
              t1.next = {
                  "data": current.data,
                  "next": null
              }
              t1 = t1.next
          }
    } else {
          if(p2.head === null) {
              p2.head = {
                  "data": current.data,
                  "next": null
              }
              t2 = p2.head
          } else {
              t2.next = {
                  "data": current.data,
                  "next": null
              }
              t2 = t2.next
          }
    }

    current = current.next;
  }
  console.log(p1)
  console.log(p2)

}

partitionLl(50)

【讨论】:

  • 我认为其他答案中的解决方案更简洁,我只是试图与 OP 的风格保持一致,也让差异变得明显......
  • 你说得对,我需要链接这些值,但我只是一遍又一遍地替换 p1。好的,我会尝试这种方法 - 所以p1.next = current。感谢您指出这一点。
【解决方案2】:

通常使用链表是使用递归的练习。

我会构建一些用于处理链表的原语,然后将它们组合起来以产生您想要的结果 - partition 可以从 filterconcat 构建:

// given a list return a new list that contains only those items than pass the test function const filter = (list, test) => { const next = list.next ? filter(list.next, test) : null; if (test(list.data)) { return { data: list.data, next }; } return next; };

// given two lists return a new list with them concatenated together const concat = (l1, l2) => { if (!l1.next) { return { data: l1.data, next: l2 }; } return { data: l1.data, next: concat(l1.next, l2) }; };

const partition = (list, value) => { const smaller = filter(list, d => d < value); const bigger = filter(list, d => d >= value); return concat(smaller, bigger); };

【讨论】:

    【解决方案3】:

    对于较小的值,您可以使用三个列表:(a) left; (b) 对于更大或相等的值right; (c) 将right 部分拆分为firstlast,其中所有值都进入last 列表,直到找到主值,然后所有值都进入first

    最后,将所有列表合并为一个,并返回一个新列表。

    function partition(list, pivot) {
        var leftHead = {},
            left = leftHead,
            firstHead = {},
            lastHead = {},
            right = lastHead,
            isLast = true,
            node = list.head;
    
        while (node) {
            if (node.data === pivot && isLast) {
                right = firstHead;
                isLast = false;
            }
    
            if (node.data < pivot) {
                left.next = { data: node.data };
                left = left.next;
            } else {
                right.next = { data: node.data };
                right = right.next;
            }
            node = node.next;
        }
    
        if (firstHead.next) {
            right.next = lastHead.next;
            left.next = firstHead.next;
        } else {
            left.next = lastHead.next;
        }
        return { head: leftHead.next };
    
    }
    
    var list1 = { head: { data: 90, next: { data: 30, next: { data: 40, next: { data: 50, next: { data: 100, next: { data: 40, next: { data: 15, next: { data: 90, next: { data: 200, next: { data: 90, next: { data: 10, next: { data: 90, next: null } } } } } } } } } } } } },
        list2 = { head: { data: 90, next: { data: 30, next: { data: 40, next: { data: 50, next: { data: 100, next: { data: 40 } } } } } } };
    
    console.log(partition(list1, 50));
    console.log(partition(list2, 50));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 我喜欢这种细分,并希望更好地理解它。对于这一行left.next = { data: node.data };,当var left 最初设置为没有属性的空对象时,如何调用下一个?这是一个奇怪的 Javascript 事情吗,未定义的属性等同于 null 但您仍然可以调用它?
    • isLast 应该称为isFirst 吗?或者这个变量是什么意思?
    • ad 2: isLast 是一个标志,右侧被占用。所以lastfirst 之前得到填充,以保持列表的顺序。广告 1:left 是一个对象。 left.nextleft 的属性,具有指定值(对象)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 2011-08-14
    相关资源
    最近更新 更多