配列内の数値の出現回数
おそらく, 誰もが配列内の数字の数を尋ねることは珍しくありません.
3つの主なタイプがあります:
1. 配列内で1回だけ現れる数字を見つける (他の数字は2回現れる)
2. 配列内の2つの数字だけを見つける.配列 1 回だけ出現する数値 (他の数値は 2 回出現する)
3. 配列内で 1 回だけ出現する数値を見つける (他のすべての数値は 3 回出現する)今回は、最初の 2 つのアイデアが思いつきやすく、理解しやすいので、主に 3 番目の質問について説明します。
3 つの質問のリンクを以下に示します:
リンク: 1、1 つの数字のみが 1 回表示されます
1. 有限状態オートマトンのソリューション
一般的な考え方:
32 ビットの中で 1 の出現回数を数え、残りの 3 を取り、最終的に 1 回だけ出現する数. 2 進ビットのビット演算規則は同じなので、1 を考慮してください。できるように少し
。
下の図に示すように、あるバイナリ 1 の数は、0、1、2
1 の 3 つの状態しかありません。バイナリ ビット 1 が入力された場合、変換は次のように実行されます。
2. 2 進数の 0 が入力された場合、変換は行われません。
各ビットは 0 または 1 であるため、2 を記録することはできません。そのため、2 番目のステータス ビットが導出され、
それぞれ名前が付けられます。1 2 は 2 つのステータス ビットを意味します。
- 次に、1 と 2 の 2 つのステータス ビットを更新する方法を説明します。
- ステータス ビット 1 の更新:
if(two==0)
{
if(n==1)
one=~one;
else
one=one;
}
else if(two==1)
{
one=0;
}
はい、ビットごとの演算子で単純化します。
- ステータスビット 2 の更新:
ステータス 2 の更新は、更新されたものに従って実行されます (更新されたものであることに注意してください)。
if(two==1)
{
if(n==1)
{
if(one==0)
two=0;
}
}
else if(two==0)
{
if(n==1)
{
if(one==0)
two=1;
}
}
理解を容易にするために、上記の関係式は、表のデータに従って理解することができます。
- コード:
- 注: & は ^ よりも優先されます。
int singleNumber(int* nums, int numsSize){
int twos=0,ones=0;
for(int i=0;i<numsSize;i++)
{
ones = ones ^ nums[i] & ~twos;
twos = twos ^ nums[i] & ~ones;
}
return ones;
}
コードはほんの数行の短いものですが、考えられる量は少なくありません。
- 単純化が必要な理由を説明してください。
上記の if else ステートメントに従って記述した場合、それは特定のビットに対してのみであり、単純化はデータ全体 (つまり 32 ビット) に対して行われるためです。
第二に、一般的な解決策
いわゆる一般的な解決策は、各データの各ビットを別々に記録し、各ビットの数に対して %3 処理を実行することです。
int singleNumber(int* nums, int numsSize){
int a[32]={
0};
for(int i=0;i<numsSize;i++)
{
for(int j=0;j<32;j++)
{
a[j]+=nums[i]&1;
nums[i]>>=1;
}
}
int sum=0;
for(int i=0;i<32;i++)
{
sum+=a[i]%3==0?0:(int)pow(2,i);
}
return sum;
}
このソリューションに比べて、理解しやすく、適用性が高く、問題の他のデータが何度出てきても、必要なコードはこの 1 つだけです。しかし、効率は上記のソリューションほど良くありません。