《劍指offer》分解讓複雜問題更簡單

1.複雜鏈表的複製

輸入一個複雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果爲複製後複雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用)

思路

拆分成三步

1.複製一份鏈表放在前一個節點後面,即根據原始鏈表的每個節點N創建N,把N直接放在N的next位置,讓複製後的鏈表和原始鏈表組成新的鏈表。

2.給複製的鏈表random賦值,即N`.random=N.random.next。

3.拆分鏈表,將N`和N進行拆分,保證原始鏈表不受影響。

代碼

    function Clone(pHead) {
      if (pHead === null) {
        return null;
      }
      cloneNodes(pHead);
      cloneRandom(pHead);
      return reconnetNodes(pHead);
    }

    function cloneNodes(pHead) {
      var current = pHead;
      while (current) {
        var cloneNode = {
          label: current.label,
          next: current.next
        };
        current.next = cloneNode;
        current = cloneNode.next;
      }
    }

    function cloneRandom(pHead) {
      var current = pHead;
      while (current) {
        var cloneNode = current.next;
        if (current.random) {
          cloneNode.random = current.random.next;
        } else {
          cloneNode.random = null;
        }
        current = cloneNode.next;
      }
    }

    function reconnetNodes(pHead) {
      var cloneHead = pHead.next;
      var cloneNode = pHead.next;
      var current = pHead;
      while (current) {
        current.next = cloneNode.next;
        current = cloneNode.next;
        if (current) {
          cloneNode.next = current.next;
          cloneNode = current.next;
        } else {
          cloneNode.next = null;
        }
      }
      return cloneHead;
    }

2.二叉搜索樹轉換爲雙向鏈表

輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。

思路

1.排序的雙向鏈表-中序遍歷二叉樹

2.記錄鏈表的最後一個節點

3.每次遍歷:設置樹節點的left和鏈表的right進行鏈接,鏈接成功後當前節點成爲鏈表的末尾節點,並返回。

代碼

       function Convert(pRootOfTree) {
      var lastNode = null;
      lastNode = convertToList(pRootOfTree, lastNode);
      while (lastNode && lastNode.left) {
        lastNode = lastNode.left;
      }
      return lastNode;
    }

    function convertToList(treeNode, lastNode) {
      if (!treeNode) {
        return null;
      }
      if (treeNode.left) {
        lastNode = convertToList(treeNode.left, lastNode);
      }
      treeNode.left = lastNode;
      if (lastNode) {
        lastNode.right = treeNode;
      }
      lastNode = treeNode;
      if (treeNode.right) {
        lastNode = convertToList(treeNode.right, lastNode);
      }
      return lastNode;
    }

3.字符串的排列

輸入一個字符串,按字典序打印出該字符串中字符的所有排列。例如輸入字符串abc,則打印出由字符a,b,c所能排列出來的所有字符串abc,acb,bac,bca,cab和cba。

輸入一個字符串,長度不超過9(可能有字符重複),字符只包括大小寫字母。

思路

1.把字符串分成兩部分,第一個字符和後面的字符
2.整個字符串的全排列等於:第一個字符+後面字符的全排列,第一個字符和後面的字符諸葛交換。

第一個字符+後面字符的全排列3.除了第一個字符其他字符的全排列等於:第二個字符+後面字符的全排列。

3.遞歸,記錄一個當前節點的位置,該位置指向最後一個節點時記錄一次排列。

代碼

    function Permutation(str) {
      var result = [];
      if (!str) {
        return result;
      }
      var array = str.split('');
      permutate(array, 0, result);
      result.sort();
      return [... new Set(result)];
    }

    function permutate(array, index, result) {
      if (array.length - 1 === index) {
        result.push(array.join(''));
      }
      for (let i = index; i < array.length; i++) {
        swap(array, index, i);
        permutate(array, index + 1, result);
        swap(array, i, index);
      }
    }

    function swap(arr, i, j) {
      [arr[i], arr[j]] = [arr[j], arr[i]];
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章