[LeetCode] 971. Flip Binary Tree To Match Preorder Traversal 翻轉二叉樹以匹配先序遍歷
Given two stringsS
andT
, each of which represents a non-negative rational number, returnTrueif and only if they represent the same number. The strings may use parentheses to denote the repeating part of the rational number.
In general a rational number can be represented using up tothree parts: aninteger part
<IntegerPart>
(e.g. 0, 12, 123)<IntegerPart><.><NonRepeatingPart>
(e.g. 0.5, 1., 2.12, 2.0001)<IntegerPart><.><NonRepeatingPart><(><RepeatingPart><)>
The repeating portion of a decimal expansion is conventionally denoted within a pair of round brackets. For example:
1 / 6 = 0.16666666... = 0.1(6) = 0.1666(6) = 0.166(66)
Both 0.1(6) or 0.1666(6) or 0.166(66) are correct representations of 1 / 6.
Example 1:
Input: S = "0.(52)", T = "0.5(25)" Output: true Explanation: Because "0.(52)" represents 0.52525252..., and "0.5(25)" represents 0.52525252525..... , the strings represent the same number.
Example 2:
Input: S = "0.1666(6)", T = "0.166(66)"
Output: true
Example 3:
Input: S = "0.9(9)", T = "1."
Output: true
Explanation:
"0.9(9)" represents 0.999999999... repeated forever, which equals 1. [[See this link for an explanation.](https://en.wikipedia.org/wiki/0.999...)]
"1." represents the number 1, which is formed correctly: (IntegerPart) = "1" and (NonRepeatingPart) = "".
Note:
- Each part consists only of digits.
- The
<IntegerPart>
willnot begin with 2 or more zeros. (There is no other restriction on the digits of each part.) 1 <= <IntegerPart>.length <= 4
0 <= <NonRepeatingPart>.length <= 4
1 <= <RepeatingPart>.length <= 4
這道題給了一棵二叉樹,說是我們可以調換任意結點的左右子結點,又給了一個數組,說是按照先序遍歷二叉樹得到的結點值組成的。現在問能否通過最少的調換操作,使得給定的二叉樹經過先序遍歷得到的結點值陣列和給定的陣列相同,可以的話返回需要調換操作的結點值,否則返回 -1。遇到二叉樹的問題,十有八九都是遞迴來做的,這道題也不例外,而且又是先序遍歷,妥妥的遞迴啊。難點在於如何在遞迴的過程中把問題解決了,由於我們需要在遞迴的過程中就和給定陣列進行比較,所以 voyage 陣列是要在遞迴陣列中的,這樣就需要一個子函式進行遞迴呼叫,而且還要知道當前對比到哪個位置了,需要一個座標變數傳入,同時當然還要傳入結果陣列 res。同時這個遞迴函式需要返回一個布林值,因為有可能是無法生成跟給定陣列一樣的順序的。在遞迴函式中,若當前結點不存在,直接返回 true。若當前結點值不等於陣列中的對應位置的值,直接返回 false,因為此時只能調換子結點的位置,當前結點的位置不會改變。否則此時看若左子結點存在,且左子結點值不等於陣列中對應位置的值,此時應該嘗試進行翻轉,先將當前結點值存入結果 res 中,然後先對右子結點呼叫遞迴函式,之後再對左子結點呼叫遞迴函式,這樣就相當於完成了調換左右子結點的操作。否則就按原順序分別對左右子結點呼叫遞迴函式即可,最終在主函式中對於遞迴函式的返回值需要做個判斷,若為 true,則返回 res,否則返回一個只有 -1 的陣列,參見程式碼如下:
class Solution {
public:
vector<int> flipMatchVoyage(TreeNode* root, vector<int>& voyage) {
vector<int> res;
int i = 0;
return helper(root, voyage, i, res) ? res : vector<int>{-1};
}
bool helper(TreeNode* node, vector<int>& voyage, int& i, vector<int>& res) {
if (!node) return true;
if (node->val != voyage[i++]) return false;
if (node->left && node->left->val != voyage[i]) {
res.push_back(node->val);
return helper(node->right, voyage, i, res) && helper(node->left, voyage, i, res);
}
return helper(node->left, voyage, i, res) && helper(node->right, voyage, i, res);
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/971
參考資料:
https://leetcode.com/problems/flip-binary-tree-to-match-preorder-traversal/