Q:あなたは、家の通りの計画を盗むためにプロの泥棒です。同じ夜上の2つの隣接する家は、泥棒がシステムに侵入した場合の各部屋にはいくつかの現金を所持している、影響を与える唯一の制約は、相互に通信し、あなたの隣人の家は、盗難防止システムが装備されて盗む自動的に警報。
もし警報装置に触れていない場合に算出ハウジングストレージ量の各非負整数のアレイからの代表与え、に最大量を盗むことができます。
実施例1:
入力:[1,2,3,1]
出力:4
説明:ハウジング盗難番号1(量= 1)、次いで盗難ハウジング3(量= 3)。
盗難= 3 + 1 = 4の最大量。
実施例2:
入力:[2,7,9,3,1]
出力:12
説明:ハウジング盗難番号1(量= 2)、3盗難ハウジング(量= 9)、盗難続いハウジング5(1 =金額)。
盗難= 2 + 9 + 1 = 12に最大量。
A:一般的な動的なプログラミングの問題。
現在の家は二つの可能性、グラブやないグラブのいずれかに分割されています。
電流が奪われた場合は、どちらかのどちらか奪われ、最後に、最後の時間をつかむませんでした。
現在は、グラブ、グラブ最後または最後の時間が奪われるかしていない場合は、
そう、良い書き込みのDP:
DP [I] [0] = Math.max(DP [I - 1] [1]、DP [I - 2] [1]); // グラブ最後または最後から二番目のグラブのいずれかである
、DP [I] [1] = Math.max (DP [I - 1] [0] + NUMS [I]、DP [I - 2] [1] + NUMS [I]); // 最後ないかラッシュどちらかの最後に強盗
コード:
public static int rob(int[] nums) {
if (nums.length == 0)
return 0;
if(nums.length == 1)
return nums[0];
int[][] dp = new int[nums.length][2];
dp[0][0] = 0;
dp[0][1] = nums[0];
dp[1][0] = nums[0];
dp[1][1] = nums[1];
for (int i = 2; i < nums.length; i++) {
dp[i][0] = Math.max(dp[i - 1][1], dp[i - 2][1]);
dp[i][1] = Math.max(dp[i - 1][0] + nums[i], dp[i - 2][1] + nums[i]);
}
return Math.max(dp[nums.length - 1][0], dp[nums.length - 1][1]);
}
または、テールヘッドから来る:(「labuladongアルゴリズムチートシート」から引用)
// 返回 nums[start..] 能抢到的最⼤值
private int dp(int[] nums, int start) {
if (start >= nums.length) {
return 0;
}
int res = Math.max(
// 不抢,去下家
dp(nums, start + 1),
// 抢,去下下家
nums[start] + dp(nums, start + 2)
);
return res;
}
このメモは、二重カウントを防止するために添加することができます。
また、これは、計算を減らすことができるトップダウン、ボトムアップであります
int rob(int[] nums) {
int n = nums.length;
// dp[i] = x 表⽰:
// 从第 i 间房⼦开始抢劫,最多能抢到的钱为 x
// base case: dp[n] = 0
int[] dp = new int[n + 2];
for (int i = n - 1; i >= 0; i--) {
dp[i] = Math.max(dp[i + 1], nums[i] + dp[i + 2]);
}
return dp[0];
}
のみとDP [I + 1]、DP [I + 2]関連するので、二つの変数は、それを記録することができます。
Q:あなたは、家の通りの計画を盗むためにプロの泥棒です、各部屋には、いくつかの現金を所持しています。この場所は、すべての家があるサークルで最初と最後の家は家の隣にあることを意味し、。同じ夜上の2つの隣接する家は、泥棒は、システムが自動的に警報に押し入った場合一方、盗難防止システムを備えた隣接する家は、互いに通信します。
もし警報装置に触れていない場合に算出ハウジングストレージ量の各非負整数のアレイからの代表与え、に最大量を盗むことができます。
例1:
入力:[2,3,2]
出力:3
説明:あなたが最初の第1ハウジング(量= 2)を盗み、その後、彼らは隣接しているので、第三家(お金= 2)を盗むことはできません。
実施例2:
入力:[1,2,3,1]
出力:4
説明:最初の盗難ハウジング3(= 3量)、次いで、ハウジング1(= 1量)を盗むことができます。
盗難= 3 + 1 = 4の最大量。
:
そのため、特に最初、部屋の端部は、したがって、特に奪われないことができ、その後、唯一の三つの異なる状況がありすることができますいずれか奪われていない、あるいは最初のフレームのサブメニューは、部屋間のグラブをしません最後のフレームを奪われた、サブメニューの部屋が最後のフレームのいずれかの間に奪われました間⼀急いではありません。
それは、結果の種類が最も大きい、シンプル、ああ、これら3例である最終的な答えの聖歌です!しかし、実際には、我々は3例よりも⽐必要があり、限り、両方のケースでズームうん、お金を数える⼀のサブメニュー⽐選択の状況室は便利な部屋に来るので⽐上の3つの状況⼆の場合よりも⾏、サブメニューがあるよう⾥はありません最適な決定の負の、選択はズームインして、確かではない結果⼩。その上に持って来られる。
public static int rob(int[] nums) {
int n = nums.length;
if (n == 0)
return 0;
if (n == 1)
return nums[0];
return Math.max(maxRob(nums, 0, n - 2), maxRob(nums, 1, n - 1));
}
private static int maxRob(int[] nums, int start, int end) {
int dp_2 = 0;
int dp_1 = 0;
int dp = 0;
for (int i = end; i >= start; i--) {
dp = Math.max(dp_1, dp_2 + nums[i]);
dp_2 = dp_1;
dp_1 = dp;
}
return dp;
}
Q:街路や家を奪った後、最終ラップの完了後、泥棒が新しい分野を盗むことができます発見しました。領域は、我々が呼んで唯一の入り口、持っている「ルートを。」「ルート」に加えて、唯一の家それに関連する「親」の家。いくつかの偵察後、賢い泥棒は「この場所は、すべての家がバイナリツリーに似て配置されている。」ことを実現します 両院が直接接続されている場合は、同じ夜、家のアラームを奪いました。
アラームを触れることなく計算し、泥棒は、夜の最大量を盗むことができます。
実施例1:
入力:[3,2,3、ヌル、3、NULL、1]
3
/
2 3
\ \
3 1
出力:7
説明:夜の最大量を盗む盗人は3 + 3 = 7 + 1 =であることができます。
実施例2:
入力:[3,4,5,1,3、ヌル,. 1]
。3
/
5
/ \ \
1. 1. 3。
出力:9
説明:最大量= 5 + 4 = 9であることができる夜を盗む盗人。
A:
私は、再帰的に、ツリーを参照してください。
Map<TreeNode, Integer> map = new HashMap<>();
public int rob(TreeNode root) {
if (root == null)
return 0;
if (map.containsKey(root))
return map.get(root);
int do_it = root.val + (root.left == null ? 0 : rob(root.left.left) + rob(root.left.right)) + (root.right == null ? 0 : rob(root.right.left) + rob(root.right.right));
int not_do = rob(root.left) + rob(root.right);
int res = Math.max(do_it, not_do);
map.put(root, res);
return res;
}