トピック:
122. 株を売買するのに最適な時期 II
特定の株式の初日の価格を表す 整数の配列が与えられ prices
ます 。prices[i]
i
毎日、株を買うか売るかを決定できます。一度に 保有できる 株式は1株までです 。最初に購入して、同日に販売することもできます 。
あなたが得ることができる 最大の 利益を返します 。
例 1:
入力:価格 = [7,1,5,3,6,4] 出力: 7 説明: 2 日目に買い (株価 = 1)、3 日目に売る (株価 = 5) この取引は利益を得ることができます= 5 - 1 = 4。 そして、4日目に買って(株価=3)、5日目に売る(株価=6)とすると、この取引では利益=6-3=3が得られます。 利益の合計は 4 + 3 = 7 です。
例 2:
入力:価格 = [1,2,3,4,5] 出力: 4 説明: 1 日目に買い (株価 = 1)、5 日目に売り (株価 = 5)、利益 = 5 - 1 = 4この商売。 合計利益は4です。
例 3:
入力:価格 = [7,6,4,3,1] 出力: 0 説明:この場合、トランザクションはプラスの利益を得ることができないため、トランザクションに参加しないことで最大の利益を得ることができ、最大の利益はは0です。
ヒント:
1 <= prices.length <= 3 * 104
0 <= prices[i] <= 104
思考プロセスと知識ポイント:
毎日のプラスの利益を収集するだけでよく、プラスの利益を収集する範囲は株式取引の範囲であり、範囲を記録することなく、最終的な利益のみに注目する必要があります。
そうなると、プラスの利益を集める場合にのみ、貪欲が現れるのです。
ローカル最適: 毎日のプラスの利益を収集し、グローバル最適: 最大利益を見つけます。
局所的な最適性は全体的な最適性につながる可能性があります。反例は見つかりません。貪欲に試してください。
答え:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int result = 0;
for (int i = 1; i < prices.size(); i++) {
result += max(prices[i] - prices[i - 1], 0);
}
return result;
}
};
トピック:
55. ジャンプゲーム
負でない整数の配列を指定すると nums
、最初は 配列の最初のインデックスに位置します 。
配列内の各要素は、その位置でジャンプできる最大長を表します。
最後の添え字に到達できるかどうかを判断します。
例 1:
入力: nums = [2,3,1,1,4] 出力: true 説明:最初に添字 0 から添字 1 まで 1 ステップジャンプし、次に添字 1 から最後の添字まで 3 ステップジャンプできます。
例 2:
入力: nums = [3,2,1,0,4] 出力: false 説明:何があっても、添字 3 の位置には常に到達します。ただし、この添字の最大ジャンプ長は 0 であるため、最後の添字に到達することはできません。
ヒント:
1 <= nums.length <= 3 * 104
0 <= nums[i] <= 105
思考プロセスと知識ポイント:
貪欲アルゴリズムの局所最適解: 毎回最大数のジャンプ ステップを実行します (最大カバレッジを取得します)。全体最適解: 最終的に全体の最大カバレッジを取得して、最後まで到達できるかどうかを確認します。
答え:
class Solution {
public:
bool canJump(vector<int>& nums) {
int cover = 0;
if (nums.size() == 1) return true; // 只有一个元素,就是能达到
for (int i = 0; i <= cover; i++) { // 注意这里是小于等于cover
cover = max(i + nums[i], cover);
if (cover >= nums.size() - 1) return true; // 说明可以覆盖到终点了
}
return false;
}
};
トピック:
45. ジャンピングゲームⅡ
n
lengthの 0 から始まるインデックス付き整数 の配列を指定します nums
。初期位置は です nums[0]
。
各要素は、 インデックスから前方にジャンプする最大長をnums[i]
表します 。i
つまり、 にいる場合は nums[i]
、どこにでもジャンプできます nums[i + j]
。
0 <= j <= nums[i]
i + j < n
nums[n - 1]
到達した最小ホップ数を返します 。生成されたテスト ケースにアクセスできます nums[n - 1]
。
例 1:
入力: nums = [2,3,1,1,4] 出力: 2 説明:最後の位置に到達するための最小ホップ数は です2
。 インデックス 0 からインデックス 1 にジャンプし、スキップして1
、3
配列の最後の位置にスキップします。
例 2:
入力: nums = [2,3,0,1,4] 出力: 2
ヒント:
1 <= nums.length <= 104
0 <= nums[i] <= 1000
- 件名は到達可能であることが保証されています
nums[n-1]
思考プロセスと知識ポイント:
55. ジャンプゲーム (新しいウィンドウが開きます)と比較すると、この問題はさらに難しいです。
ただし、考え方は似ていますが、やはり最大カバレッジに依存します。
この質問では最小ステップ数を計算する必要があるため、ステップ数を 1 つ増やす必要がある場合を把握する必要があります。
欲張り思考、局所最適:現状の移動可能距離を可能な限り増やし、終点に到達しない場合はステップ数を1つ増やします。全体的に最適: 最小ステップ数を達成するために、1 つのステップでできるだけ多くのステップを実行します。
考え方としてはこんな感じですが、コードを書いていると実際にどこまでジャンプできるわけでもなく、次にどこまでジャンプできるのかわかりません。
したがって、実際に問題を解くときは、カバーエリアから開始します。どのようにジャンプしても、カバーエリア内でジャンプできなければなりません。最小限のステップ数でカバーエリアを増やします。カバーエリアが終点をカバーしたら、最小限のステップ数が得られます。
ここでは、現在のステップの最大カバレッジと次のステップの最大カバレッジの 2 つのカバレッジ エリアをカウントする必要があります。
移動添え字が現在のステップの最大カバレッジおよび最遠距離に達し、終点に到達していない場合は、カバレッジ エリアが終点をカバーするまで別のステップを実行してカバレッジを拡大する必要があります。
答え:
class Solution {
public:
int jump(vector<int>& nums) {
if (nums.size() == 1) return 0;
int curDistance = 0; // 当前覆盖最远距离下标
int ans = 0; // 记录走的最大步数
int nextDistance = 0; // 下一步覆盖最远距离下标
for (int i = 0; i < nums.size(); i++) {
nextDistance = max(nums[i] + i, nextDistance); // 更新下一步覆盖最远距离下标
if (i == curDistance) { // 遇到当前覆盖最远距离下标
ans++; // 需要走下一步
curDistance = nextDistance; // 更新当前覆盖最远距离下标(相当于加油了)
if (nextDistance >= nums.size() - 1) break; // 当前覆盖最远距到达集合终点,不用做ans++操作了,直接结束
}
}
return ans;
}
};
「いいね!」、ブックマーク、コメントを歓迎します。あなたの励ましが私の創作の最大の動機です。(๑╹◡╹)ノ"""
著作権に関する声明: この記事は、CSDN ブロガー「Dumengjiu」によるオリジナルの記事であり、CC 4.0 BY-SA 著作権契約に準拠しています。転載する場合は、元のソースのリンクとこの声明を添付してください。
元のリンク: Dumengjiu の blog_CSDN blog-csdn ドメイン ブロガー