【スナップアルゴリズム】112-パス合計
14835 ワード
タイトル
ツリーとターゲット和を指定し、ツリーにルートノードからリーフノードへのパスが存在するかどうかを判断します.このパスのすべてのノード値がターゲット和に加算されます.
説明:リーフノードとは、サブノードがないノードを指します.
例:次のツリーとターゲットとsum=22が与えられます.
ターゲットと22のルートノードからリーフノードへのパス5->4->11->2があるため、trueを返します.
ソース:力ボタン(LeetCode)リンク:https://leetcode-cn.com/problems/path-sum著作権はインターネットの所有に帰属する.商業転載は公式の授権に連絡してください.非商業転載は出典を明記してください.
問題解
ツリー定義
まず、ツリーの構造TreeNodeを定義します.
方法1:再帰
最も直接的な方法は、再帰を利用して、ツリー全体を巡回することです.現在のノードが葉でない場合、そのすべての子供ノードに対してhasPathSum関数を再帰的に呼び出し、sum値から現在のノードの重み値を減算します.現在のノードがリーフである場合、sum値が0であるかどうか、すなわち所与のターゲットとが見つかっているかどうかを確認します.
複雑度分析
時間複雑度:各ノードに1回アクセスし,時間複雑度はO(N)O(N)O(N)であり,ここでN Nはノード個数である.空間複雑度:最悪の場合、ツリー全体が非平衡であり、例えば各ノードに子供が1人しかいない場合、再帰的にはN N N回(ツリーの高さ)が呼び出されるため、スタックの空間オーバーヘッドはO(N)O(N)O(N)O(N)である.しかし、最良の場合、木は完全にバランスがとれており、高さはlog(N)log(N)log(N)log(N)だけであるため、この場合の空間複雑度はO(log(N))O(log(N))O(log(N))のみである.
方法2:反復
アルゴリズム#アルゴリズム#
スタックで再帰を反復形式に変換できます.深度優先検索は、最悪の場合を除いて、広さ優先検索よりも高速です.最悪の場合、ターゲット和を満たすroot->leafパスが最後に考慮される場合、深さ優先探索と広さ優先探索の代価は共通する.
深度優先ポリシーを使用して各ノードにアクセスし、残りのターゲットとを更新します.
ルートノードを含むスタックからシミュレーションを開始し、残りのターゲットはsum-rootである.val.
次に反復を開始します:現在の要素がポップアップされ、現在の残りのターゲットが0の場合、リーフノードでTrueが返されます.残りの和がゼロでなく、非リーフノードにある場合、現在のノードのすべての子供と対応する残りの和をスタックに押し込みます.
複雑度分析
時間複雑度:再帰法と同様にO(N)O(N)O(N)である.空間的複雑さ:木のアンバランスが最悪の場合はO(N)O(N)O(N)である.最良の場合(木がバランスしている)はO(logN)O(log N)O(logN)である.
作者:LeetCodeリンク:https://leetcode-cn.com/problems/two-sum/solution/lu-jing-zong-he-by-leetcode/出典:力扣(LeetCode)著作権は作者の所有.商业転載は作者に连络して授権を得て、非商业転載は出典を明記してください.
感想
さいきかいほう
実行時間:1 ms、すべてのJavaコミットで98.40%のユーザーを破った
メモリ消費量:37.3 MB、すべてのJavaコミットで66.08%のユーザーを破った
ツリーとターゲット和を指定し、ツリーにルートノードからリーフノードへのパスが存在するかどうかを判断します.このパスのすべてのノード値がターゲット和に加算されます.
説明:リーフノードとは、サブノードがないノードを指します.
例:次のツリーとターゲットとsum=22が与えられます.
5
/ \
4 8
/ / \
11 13 4
/ \ \
7 2 1
ターゲットと22のルートノードからリーフノードへのパス5->4->11->2があるため、trueを返します.
ソース:力ボタン(LeetCode)リンク:https://leetcode-cn.com/problems/path-sum著作権はインターネットの所有に帰属する.商業転載は公式の授権に連絡してください.非商業転載は出典を明記してください.
問題解
ツリー定義
まず、ツリーの構造TreeNodeを定義します.
/* Definition for a binary tree node. */
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
方法1:再帰
最も直接的な方法は、再帰を利用して、ツリー全体を巡回することです.現在のノードが葉でない場合、そのすべての子供ノードに対してhasPathSum関数を再帰的に呼び出し、sum値から現在のノードの重み値を減算します.現在のノードがリーフである場合、sum値が0であるかどうか、すなわち所与のターゲットとが見つかっているかどうかを確認します.
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null)
return false;
sum -= root.val;
if ((root.left == null) && (root.right == null))
return (sum == 0);
return hasPathSum(root.left, sum) || hasPathSum(root.right, sum);
}
}
複雑度分析
時間複雑度:各ノードに1回アクセスし,時間複雑度はO(N)O(N)O(N)であり,ここでN Nはノード個数である.空間複雑度:最悪の場合、ツリー全体が非平衡であり、例えば各ノードに子供が1人しかいない場合、再帰的にはN N N回(ツリーの高さ)が呼び出されるため、スタックの空間オーバーヘッドはO(N)O(N)O(N)O(N)である.しかし、最良の場合、木は完全にバランスがとれており、高さはlog(N)log(N)log(N)log(N)だけであるため、この場合の空間複雑度はO(log(N))O(log(N))O(log(N))のみである.
方法2:反復
アルゴリズム#アルゴリズム#
スタックで再帰を反復形式に変換できます.深度優先検索は、最悪の場合を除いて、広さ優先検索よりも高速です.最悪の場合、ターゲット和を満たすroot->leafパスが最後に考慮される場合、深さ優先探索と広さ優先探索の代価は共通する.
深度優先ポリシーを使用して各ノードにアクセスし、残りのターゲットとを更新します.
ルートノードを含むスタックからシミュレーションを開始し、残りのターゲットはsum-rootである.val.
次に反復を開始します:現在の要素がポップアップされ、現在の残りのターゲットが0の場合、リーフノードでTrueが返されます.残りの和がゼロでなく、非リーフノードにある場合、現在のノードのすべての子供と対応する残りの和をスタックに押し込みます.
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null)
return false;
LinkedList<TreeNode> node_stack = new LinkedList();
LinkedList<Integer> sum_stack = new LinkedList();
node_stack.add(root);
sum_stack.add(sum - root.val);
TreeNode node;
int curr_sum;
while ( !node_stack.isEmpty() ) {
node = node_stack.pollLast();
curr_sum = sum_stack.pollLast();
if ((node.right == null) && (node.left == null) && (curr_sum == 0))
return true;
if (node.right != null) {
node_stack.add(node.right);
sum_stack.add(curr_sum - node.right.val);
}
if (node.left != null) {
node_stack.add(node.left);
sum_stack.add(curr_sum - node.left.val);
}
}
return false;
}
}
複雑度分析
時間複雑度:再帰法と同様にO(N)O(N)O(N)である.空間的複雑さ:木のアンバランスが最悪の場合はO(N)O(N)O(N)である.最良の場合(木がバランスしている)はO(logN)O(log N)O(logN)である.
作者:LeetCodeリンク:https://leetcode-cn.com/problems/two-sum/solution/lu-jing-zong-he-by-leetcode/出典:力扣(LeetCode)著作権は作者の所有.商业転載は作者に连络して授権を得て、非商业転載は出典を明記してください.
感想
さいきかいほう
実行時間:1 ms、すべてのJavaコミットで98.40%のユーザーを破った
メモリ消費量:37.3 MB、すべてのJavaコミットで66.08%のユーザーを破った
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if(root==null) return false;
if(root.left==null&&root.right==null) return root.val==sum;
if(root.left==null) return hasPathSum(root.right, sum-root.val);
else if(root.right==null) return hasPathSum(root.left,sum-root.val);
else return hasPathSum(root.left,sum-root.val)||hasPathSum(root.right, sum-root.val);
}
}