【问题标题】:Cracking the coding interview 2.1 remove duplicate values from singly linked list javascript破解编码面试2.1 去除单链表中的重复值javascript
【发布时间】:2020-09-07 16:44:15
【问题描述】:
class LinkedListNode {
    constructor(value) {
        this.value = value;
        this.next = null;
    }
}

let head = new LinkedListNode("head");

let x = [1, 1, 1, 1, 4, 10, 10, 3, 10, 9, 5, 5, 5, 8];

for (let ele of x) {
    let y = new LinkedListNode(ele);
    let pointer = head;
    while (pointer.next != null) {
        pointer = pointer.next;
    }
    pointer.next = y;
}

有人可以解释为什么以下“解决方案”会导致无限循环吗?

let removeDup = function(sll) {
    let array = []
    let pointer = sll;
    while (pointer) {
        if (array.includes(pointer.value)){
        } else {
            array.push(pointer.value);
            sll.next = pointer;
            sll = sll.next;
        }
        pointer = pointer.next;
    }
}

看来如果我

let pointer = sll.next;

let array = [sll.value]

然后它工作正常,但如果我按原样运行它,则会导致无限循环。我可以看到为什么它可能会创建一个包含第一个值的 2 个重复项的链表,但我不明白为什么它会产生无限循环。或者,如果有人能指出我调试的正确方向,那也将不胜感激!

【问题讨论】:

  • sll.next = pointer; 所以,用pointer = sll,然后你让下一个节点成为同一个节点。

标签: javascript algorithm infinite-loop singly-linked-list


【解决方案1】:

看起来您最终定义了一个在 else 条件中引用自身的节点。

您可能正在寻找这样的东西:

class LinkedListNode {
    constructor(value) {
        this.value = value;
        this.next = null;
    }
}

let head = new LinkedListNode("head");

let x = [1, 1, 1, 1, 4, 10, 10, 3, 10, 9, 5, 5, 5, 8];

for (let ele of x) {
    let y = new LinkedListNode(ele);
    let pointer = head;
    while (pointer.next != null) {
        pointer = pointer.next;
    }
    pointer.next = y;
}

function removeDup(currentNode = sll) {
	const seen = {};
	let lastUnique;
	while (currentNode) {
		if (seen[currentNode.value]) {
			lastUnique.next = currentNode.next;
		} else {
			seen[currentNode.value] = true;
			lastUnique = currentNode;
		}
		currentNode = currentNode.next;
	}
}

removeDup(head);

let outputNode = head;
while (outputNode) {
	outputNode = outputNode.next;
	if (outputNode) {
		console.log(outputNode.value);
	}
}

【讨论】:

    【解决方案2】:
    1. 如何调查您的错误

    你可以使用调试器,但是对于像我这样的原始人,你也可以使用console.log

    • 在无限循环的情况下,你想要的就是挣脱
    let count = 0
    while (pointer && count++<5) {
      //whatever
    }
    

    即使你的算法失败了,你仍然会退出

    • 输出变量

    发挥创意,在您认为合适的地方发送垃圾邮件 console.log。放一些字符串来提醒你输出了什么垃圾

    while (pointer) {
      if (array.includes(pointer.value)){
        console.log('cached skip')
      } else {
        console.log('pointervalue', pointer.value)
        array.push(pointer.value);
        sll.next = pointer;
        sll = sll.next;
        console.log('sllendloop', sll)
      }
      pointer = pointer.next;
    }
    
    1. 修复代码

    注意:不要使用数组进行缓存,因为它看起来是 O(n)

    你可以使用 Set (O(1)) 代替

    const removeDup = function(sll) {
      const dupes = new Set()
      let cur = { next: null }
      // you can also as you suggested initialize cur as sll
      // in which case you must mark it as "consumed" idem add the value to dupes
      let sllIter = sll
      while (sllIter) {
        if (dupes.has(sllIter.value)) {
          // early continue to avoid nesting else
          // subjective preference
          sllIter = sllIter.next
          continue
        }
        dupes.add(sllIter.value)
        // link our node to the currently being iterated node
        cur.next = sllIter;
    
        // advance our node
        cur = sllIter
    
        // advance iter
        sllIter = sllIter.next
      }
      return sll
    }
    const l = (value, next) => ({ value, next })
    const sllStr = ({ value: a, next: b }) => b ? `${a} -> ${sllStr(b)}`: a
    const sll = l(1, l(1, l(2, l(1, l(2, l(3))))))
    console.log(sllStr(removeDup(sll))) // 1 -> 2 -> 3

    【讨论】:

    • 我尝试使用 console.log 但 chrome 上的开发人员工具只是冻结而不是记录任何值。我会尝试使用套装,谢谢!
    • 在无限循环的情况下退出不会冻结确保添加最大迭代计数条件
    【解决方案3】:

    也许你可以写一个微型链表库。这是一个有功能描述的;

    • toList :将数组转换为列表
    • foldList :类似减少的东西。接受一个列表、一个函数和一个累加器。
    • sum :获取一个列表并给出它的总和 :)
    • prt : 漂亮地打印一个列表
    • nub :从列表中删除欺骗。

    function List(e){
      this.data = e;
      this.next = null;
    }
    
    List.fromArray = function([a,...as]){
                       var h = new List(a),
                           t = as.reduce((l,e) => [l[0],l[1].next = new List(e)], [h,h]);
                       return t[0];
                     };
    List.prototype.fold = function (f,a){
                            var newa = f(a, this.data);
                            return this.next ? this.next.fold(f, newa)
                                             : newa
                          };
    List.prototype.log = function(){
                           return this.fold((a,e) => a + e + " -> ", "") + "null";
                         };
    List.prototype.nub = function(){
                           var o = this.fold((a,e) => (a[e] = e, a), {}),
                               a = Object.values(o);
                           return List.fromArray(a);
                         }
    
    var arr = [1, 1, 1, 1, 4, 10, 10, 3, 10, 9, 5, 5, 5, 8],
        lst = List.fromArray(arr),
        sum = l => l.fold((a,e) => a + e, 0), // just for fun
        res = lst.nub().log();
    
    console.log(res);

    nub 是 O(n)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-12
      • 1970-01-01
      • 2013-09-05
      • 2018-11-21
      相关资源
      最近更新 更多