動態規劃練習題-加分二叉樹

動態規劃練習題-總segmentfault

題目描述
設一個n個節點的二叉樹tree的中序遍歷爲(1,2,3,…,n),其中數字1,2,3,…,n爲節點編號。每一個節點都有一個分數(均爲正整數),記第i個節點的分數爲di,tree及它的每一個子樹都有一個加分,任一棵子樹subtree(也包含tree自己)的加分計算方法以下:
subtree的左子樹的加分× subtree的右子樹的加分+subtree的根的分數。
若某個子樹爲空,規定其加分爲1,葉子的加分就是葉節點自己的分數。不考慮它的空子樹。
試求一棵符合中序遍歷爲(1,2,3,…,n)且加分最高的二叉樹tree。要求輸出tree的最高加分和前序遍歷
輸入
長度爲n的序列,序列值爲每一個節點的分數(分數<100)如:5,7,1,2,10
輸出
最高加分;前序遍歷,如:145; 3 1 2 4 5this


1 思路
若要使加分最高,則需讓父節點儘量小code

2 拆分子問題
構建樹的過程當中,從當前序列找到值最小的節點做爲父節點,節點左側序列爲左子樹,右側序列爲右子樹get

3 計算
T[0,m]={ Node[k], left:T[0,k-1], right:T[k+1,m]}it

4 代碼
recursive DPio

const treeArray = [5,7,1,2,10];
class CalTree {
  constructor(options) {
    this.treeArray = Array.isArray(options) ? options : [];
    this.walkArr = [];
    this.sum = 0;
  }
  getTreeRecursive() {
    const newArr = this.getTreeRec(this.treeArray);
    this.sum = this.getSum(newArr);
    console.log(`前序遍歷序列是: ${ this.walkArr.join(",") }`);
    console.log(`最高加分是 ${this.sum}`); // 最高得分
  }
  getTreeRec(arr) {
    const min = Math.min(...arr);
    const item = {
      value: min,
      index: arr.indexOf(min)
    };
    if (arr.length === 1) {
      return {
        item,
        left: null,
        right: null
      };
    }
    const leftArr = arr.slice(0, item.index);
    const rightArr = arr.slice(item.index + 1, arr.length);
    let obj = {};
    obj.item = item;
    obj.left = leftArr.length > 0 ? this.getTreeRec(leftArr):null;
    obj.right = rightArr.length > 0 ? this.getTreeRec(rightArr) : null;
    return obj;
  }
  getSum(obj) {
    this.walkArr.push(obj.item.value);
    if (!obj.left && !obj.right) {
      return obj.item.value;
    }
    const left = obj.left ? this.getSum(obj.left) : 1;
    const right = obj.right ? this.getSum(obj.right) : 1;
    return obj.item.value + left * right;
  }

}
new CalTree(treeArray).getTreeRecursive();

5 時間複雜度
主要過程是把序列一分爲二分別建子樹,第i次拆分的計算量是2的i次方,故時間複雜度爲O(2的logn次方)console

相關文章
相關標籤/搜索