目次
1. 質問分析
質問リンク: 34. ソートされた配列内の要素の最初と最後の位置を見つける - LeetCode
この問題は、配列内のターゲット値の開始位置と終了位置を見つけることです。
2. アルゴリズム原理
ここで標準二等分を直接使用する場合、配列全体が同じ数値である場合、
O(N) に縮退してしまうので、ここで最適化する必要があります。
1.左端点を見つけることによって分析を開始します。x を中間値、t をターゲット値とします。
x < t の場合、左 = 中央 + 1
x >= t の場合、right = Mid (ここでは、以上の状況と等しい状況を組み合わせます)
この設定は、左 == 右の場合の最終結果です。
中点を見つける方法は、左 + (右 - 左) / 2 (つまり、偶数を見つける形式) でなければなりません。
このようにして、各ステップは左のエンドポイントに近くなり、無限ループに陥ることはありません。
2. 分析して適切なエンドポイントを見つけてみましょう:
x <= t の場合、left = Mid (ここで + 1 を使用しないのはなぜでしょうか。たまたまターゲット値に達した場合、すぐに超えてしまうからです。)
x > t の場合、right = Mid - 1
このように、左 == 右の場合、それが最終結果になります。
そして、中点を見つける方法は、 left + (right - left + 1) / 2 です。
こうすることで、各ステップが正しいエンドポイントに近づき、無限ループに陥ることがなくなります。
3. コードの書き方
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.size() == 0) return {-1, -1}; // 处理越界
int left = 0, right = nums.size() - 1, begin = 0;
while(left < right) {
int mid = left + (right - left) / 2;
if(nums[mid] < target) left = mid + 1;
else right = mid;
}
if(nums[left] != target) return {-1, -1};
else begin = left;
left = 0, right = nums.size() - 1;
while(left < right) {
int mid = left + (right - left + 1) / 2;
if(nums[mid] <= target) left = mid;
else right = mid - 1;
}
return {begin, right};
}
};
4. 2 部構成のテンプレート
左側のエンドポイントを探す場合:
while(左 < 右) {
int ミッド = 左 + (右 - 左) / 2;
if(...) 左 = 中央 + 1;
それ以外の場合は右 = 中央;
}
while (left < right) {
int mid = left + (right - left) / 2;
if (...) left = mid + 1;
else right = mid;
}
適切なエンドポイントを探す場合:
while(左 < 右) {
int ミッド = 左 + (右 - 左 + 1) / 2;
if(...) 左 = 中央;
それ以外の場合は右 = 中央 - 1;
}
while (left < right) {
int mid = left + (right - left + 1) / 2;
if (...) left = mid;
else right = mid - 1;
}
最後に次のように書きます。
以上がこの記事の内容です、読んでいただきありがとうございます。
何かを得たと感じたら、ブロガーに「いいね! 」を与えることができます。
記事の内容に漏れや間違いがある場合は、ブロガーにプライベートメッセージを送信するか、コメント欄で指摘してください〜