[配列内の数値の出現回数 - 有限状態オートマトン]

おそらく, 誰もが配列内の数字の数を尋ねることは珍しくありません.
3つの主なタイプがあります:
1. 配列内で1回だけ現れる数字を見つける (他の数字は2回現れる)
2. 配列内の2つの数字だけを見つける.配列 1 回だけ出現する数値 (他の数値は 2 回出現する)
3. 配列内で 1 回だけ出現する数値を見つける (他のすべての数値は 3 回出現する)

今回は、最初の 2 つのアイデアが思いつきやすく、理解しやすいので、主に 3 番目の質問について説明します。
3 つの質問のリンクを以下に示します:
リンク: 1、1 つの数字のみが 1 回表示されます
ここに画像の説明を挿入

リンク: 2、2 つの数字のみが 1 回表示されます
ここに画像の説明を挿入

リンク: 3、1 つの数字のみが 1 回表示され、残りは 3 回表示されます
ここに画像の説明を挿入

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 つだけです。しかし、効率は上記のソリューションほど良くありません。

おすすめ

転載: blog.csdn.net/Djsnxbjans/article/details/128434677