記事ディレクトリ
1. 137. 一度だけ現れる数字Ⅱ
1. トピックの紹介
137. 1 回だけ現れる数値 II は、
整数配列 nums を与えます。1 回だけ現れる 1 つの要素を除いて、他の各要素はちょうど 3 回現れます。1 回だけ出現する要素を見つけて返してください。
この問題を解決するには、余分なスペースを使用しない線形時間計算量のアルゴリズムを設計して実装する必要があります。
2. 問題解決のアイデア
配列内のすべての要素の各ビット値の出現回数を記録します。3 で割り切れないビットを組み合わせると、探している値が 1 回出現する数になります。
3.コード
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ret = 0;
for(int i = 0;i < 32; ++i)
{
int sum = 0;
for(auto& e : nums)
{
if(((e >> i) & 1) == 1) sum++;
}
if(sum % 3)
{
ret |= (1 << i);
}
}
return ret;
}
};
4. 走行結果
2. ソード ポイント オファー 53 - II. 0 から n-1 までの欠落した数字
1. トピックの紹介
Sword Pointer Offer 53 - II. 0 から n-1 までの欠落した数値 長
さ n-1 の昇順にソートされた配列内のすべての数値は一意であり、各数値は 0 から n-1 の範囲内にあります。0~n-1のn個の数値のうち、配列にない数値が1つだけありますので、その数値を探してください。
2. 問題解決のアイデア
二分法:
欠落している数値を見つけるには、次の 2 つの状況が考えられます:
1. Mid に対応する配列要素 nums[mid] は Mid に等しい このとき、mid + 1~right の間を検索する必要があります; 2. 配列
要素Mid に対応する Mid と等しくありません (mid より大きくなければなりません。mid 要素に nums[mid] がない場合は、mid より大きくなければなりません) このとき、left~mid の間を検索する必要があります。
left == right の場合、次の 2 つの状況が発生します。
1. left に対応する要素 nums[left] が left と等しくない (left より大きい) 場合、欠落している数値は左になります (欠落している数値は 0 ~ n- の間です)。 2)
2. left に対応する要素 nums[left] が left と等しい場合、不足している数は left+1 (不足している数は n-1)
3.コード
class Solution {
public:
int missingNumber(vector<int>& nums) {
int left = 0, right = nums.size() - 1;
while(left < right)
{
int mid = left + (right - left) / 2;
if(nums[mid] == mid) left = mid + 1;
else right = mid;
}
return left == nums[left] ? left + 1 : left;
}
};
4. 走行結果
3. 153. 回転ソートされた配列の最小値を見つける
1. トピックの紹介
153. 回転ソート配列の最小値を求める
. 長さ n の配列があらかじめ昇順に並べられていることがわかっており、1 ~ n 回転すると入力配列が得られます。たとえば、元の配列 nums = [0,1,2,4,5,6,7] は、変更後に取得される可能性があります。4
回回転すると、[4,5,6,7,0,1] を取得できます。 ,2]
7 回回転すると、 [0,1,2,4,5,6,7] が得られます
。配列 [a[0], a[1], a[2], …, a [n-1] ] 1 回の回転の結果は、配列 [a[n-1], a[0], a[1], a[2], …, a[n-2]] になります。
異なる要素値を持つ配列 nums が与えられますが、これは元々は昇順に配置され、上記のように複数回回転された配列です。配列内の最小の要素を見つけて返してください。
この問題を解決するには、時間計算量が O(log n) のアルゴリズムを設計する必要があります。
2. 問題解決のアイデア
二分法
では、配列を A B と C D の 2 つの部分配列に昇順で分割します (A は最初の部分の最初の要素、B は最初の部分の最後の要素です。C と D は類似しています)。
3.コード
class Solution {
public:
int findMin(vector<int>& nums) {
int left = 0, right = nums.size() - 1;
while(left < right)
{
int mid = left + (right - left) / 2;
if(nums[mid] > nums[right]) //说明mid位于第一部分。则要在mid + 1~right之间寻找数组的最小值
left = mid + 1;
else//说明mid位于第二部分,则要在left~mid之间进行寻找
right = mid;
}
return nums[left];
}
};
4. 走行結果
要約する
今日はアルゴリズム実習10日目です。
神は努力に報いてくださるので、これからも頑張ってください。
この記事にある問題はすべて Leetcode のもので、友達は問題紹介のリンクをクリックすると元のページに飛んで練習することができます。
この記事があなたにインスピレーションを与えたなら、著者をもっとサポートしていただければ幸いです。皆さん、ありがとう!