JavaScriptでチェーン操作を実現する-16 Sorted Intersect


TL;DR
二つの並べ替えチェーンのクロスを通して、一連のカタログを前書きと目次に見ました.
需要
実現関数sortedIntersect()は、順序付けられた2つのチェーンテーブルの交差点を取り、交差点は、2つのチェーンテーブルの両方にあるノードを指し、ノードは必ずしも連続していない.チェーンは一回しか回りません.結果チェーンに重複ノードは含まれません.
var first = 1 -> 2 -> 2 -> 3 -> 3 -> 6 -> null
var second = 1 -> 3 -> 4 -> 5 -> 6 -> null
sortedIntersect(first, second) === 1 -> 3 -> 6 -> null
分析
最も容易に考えられる解法は、リンクAからノードを取って、チェーンBを通して同じノードを見つけ、結果チェーンテーブルに参加し、最後にチェーンAの次のノードを取って、このステップを繰り返すことができる.しかし、この問題はチェーンごとに一回の制限しかないです.どうすればいいですか?
まず、2つのポインタp1p2とを仮定して、それぞれ2つのチェーンの最初のノードを指す.p1p2の値を比較すると、このような場合があります.
  • p1.data === p2.dataは、ノードが必ず交差し、結果チェーンに加入する.両方のノードが使用されているので、私たちは同時に後にp1p2のペアを比較することができる.
  • p1.data < p2.dataは、チェーンが昇順に配列されているので、p1の後続ノードはp2と同じ大きさになる可能性があります.
  • p1は、上記とは反対にp2を移動する.
  • p1.data > p2.dataまたはp2は空です.後ろはきっと交差していません.
  • 基本的な考えはこのようにして、再帰と循環はすべてこのようです.
    再帰的解法
    コードは以下の通りです
    function sortedIntersect(first, second) {
      if (!first || !second) return null
    
      if (first.data === second.data) {
        return new Node(first.data, sortedIntersect(nextDifferent(first), nextDifferent(second)))
      } else if (first.data < second.data) {
        return sortedIntersect(first.next, second)
      } else {
        return sortedIntersect(first, second.next)
      }
    }
    
    function nextDifferent(node) {
      let nextNode = node.next
      while (nextNode && nextNode.data === node.data) nextNode = nextNode.next
      return nextNode
    }
    重複ノードに参加できないという判断に注意が必要です.私は5行目の2つのチェーンテーブルのノードが等しい後、次の値の異なるノードを巡回して、このために単独でp1関数を書きました.このやり方は私の考えに合っていますが、実は循環体にも書いてもいいです.皆さんは自分で考えてもいいです.
    循環解法
    コードは以下の通りです.
    function sortedIntersectV2(first, second) {
      const result = new Node()
      let [pr, p1, p2] = [result, first, second]
    
      while (p1 || p2) {
        if (!p1 || !p2) break
    
        if (p1.data === p2.data) {
          pr = pr.next = new Node(p1.data)
          p1 = nextDifferent(p1)
          p2 = nextDifferent(p2)
        } else if (p1.data < p2.data) {
          p1 = p1.next
        } else {
          p2 = p2.next
        }
      }
    
      return result.next
    }
    参考資料
    Codewars Kata GitHubのコードはGitHubのテストを実現します.