Given a nested list of integers, return the sum of all integers in the list weighted by their depth.
Each element is either an integer, or a list -- whose elements may also be integers or other lists.
Different from the previous question where weight is increasing from root to leaf, now the weight is defined from bottom up. i.e., the leaf level integers have weight 1, and the root level integers have the largest weight.
Example 1:
Input: [[1,1],2,[1,1]]
Output: 8 Explanation: Four 1's at depth 1, one 2 at depth 2.
Example 2:
Input: [1,[4,[6]]]
Output: 17 Explanation: One 1 at depth 3, one 4 at depth 2, and one 6 at depth 1; 1*3 + 4*2 + 6*1 = 17.
這道題是之前那道 Nested List Weight Sum 的拓展,與其不同的是,這里的深度越深,權重越小,和之前剛好相反。但是解題思路沒有變,還可以用 DFS 來做,由於遍歷的時候不知道最終的 depth 有多深,則不能遍歷的時候就直接累加結果,博主最開始的想法是在遍歷的過程中建立一個二維數組,把每層的數字都保存起來,然后最后知道了 depth 后,再來計算權重和,比如題目中給的兩個例子,建立的二維數組分別為:
[[1,1],2,[1,1]]:
1 1 1 1
2
[1,[4,[6]]]:
1
4
6
這樣我們就能算出權重和了,參見代碼如下:
解法一:
class Solution { public: int depthSumInverse(vector<NestedInteger>& nestedList) { int res = 0; vector<vector<int>> all; for (auto &a : nestedList) { helper(a, 0, all); } for (int i = (int)all.size() - 1; i >= 0; --i) { for (int j = 0; j < all[i].size(); ++j) { res += all[i][j] * ((int)all.size() - i); } } return res; } void helper(NestedInteger& ni, int depth, vector<vector<int>>& all) { vector<int> t; if (depth < all.size()) t = all[depth]; else all.push_back(t); if (ni.isInteger()) { t.push_back(ni.getInteger()); all[depth] = t; } else { for (auto &a : ni.getList()) { helper(a, depth + 1, all); } } } };
其實上面的方法可以簡化,由於每一層的數字不用分別保存,每個數字分別乘以深度再相加,跟每層數字先相加起來再乘以深度是一樣的,這樣只需要一個一維數組就可以了,只要把各層的數字和保存起來,最后再計算權重和即可:
解法二:
class Solution { public: int depthSumInverse(vector<NestedInteger>& nestedList) { int res = 0; vector<int> v; for (auto &a : nestedList) { helper(a, 0, v); } for (int i = (int)v.size() - 1; i >= 0; --i) { res += v[i] * ((int)v.size() - i); } return res; } void helper(NestedInteger& ni, int depth, vector<int>& v) { if (depth >= v.size()) v.resize(depth + 1); if (ni.isInteger()) { v[depth] += ni.getInteger(); } else { for (auto &a : ni.getList()) { helper(a, depth + 1, v); } } } };
下面這個方法就比較巧妙了,由史蒂芬大神提出來的,這個方法用了兩個變量 unweighted 和 weighted,非權重和跟權重和,初始化均為0,然后如果 nestedList 不為空開始循環,先聲明一個空數組 nextLevel,遍歷 nestedList 中的元素,如果是數字,則非權重和加上這個數字,如果是數組,就加入 nextLevel,這樣遍歷完成后,第一層的數字和保存在非權重和 unweighted 中了,其余元素都存入了 nextLevel 中,此時將 unweighted 加到 weighted 中,將 nextLevel 賦給 nestedList,這樣再進入下一層計算,由於上一層的值還在 unweighted 中,所以第二層計算完將 unweighted 加入 weighted 中時,相當於第一層的數字和被加了兩次,這樣就完美的符合要求了,這個思路又巧妙又牛B,大神就是大神啊,參見代碼如下:
解法三:
class Solution { public: int depthSumInverse(vector<NestedInteger>& nestedList) { int unweighted = 0, weighted = 0; while (!nestedList.empty()) { vector<NestedInteger> nextLevel; for (auto a : nestedList) { if (a.isInteger()) { unweighted += a.getInteger(); } else { nextLevel.insert(nextLevel.end(), a.getList().begin(), a.getList().end()); } } weighted += unweighted; nestedList = nextLevel; } return weighted; } };
下面這種算法是常規的 BFS 解法,利用上面的建立兩個變量 unweighted 和 weighted 的思路,大體上沒什么區別:
解法四:
class Solution { public: int depthSumInverse(vector<NestedInteger>& nestedList) { int unweighted = 0, weighted = 0; queue<vector<NestedInteger>> q; q.push(nestedList); while (!q.empty()) { int size = q.size(); for (int i = 0; i < size; ++i) { vector<NestedInteger> t = q.front(); q.pop(); for (auto a : t) { if (a.isInteger()) unweighted += a.getInteger(); else if (!a.getList().empty()) q.push(a.getList()); } } weighted += unweighted; } return weighted; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/364
類似題目:
參考資料:
https://leetcode.com/problems/nested-list-weight-sum-ii/
https://leetcode.com/problems/nested-list-weight-sum-ii/discuss/83655/JAVA-AC-BFS-solution