C++で未ソートの整数配列から欠損している正の数を見つけるプログラムを作成する方法
ここでは、ソートされていない整数の配列が与えられたと仮定します。課題は、範囲[0〜n]の中で、その配列に存在しない正の欠損数を見つけることです。具体的な例を見てみましょう。
入力例1 −
N = 9 arr = [0,2,5,9,1,7,4,3,6]
出力 −
8
説明 − 与えられた未ソートの配列において、「8」だけが欠けている正の整数であるため、出力は「8」となります。
入力例2 −
N = 1 arr = [0]
出力 −
1
説明 − この配列では「1」だけが欠けている正の整数であるため、出力は「1」となります。
この問題を解くためのアプローチ
この問題にはいくつかの解き方がありますが、線形時間 O(n)、定数領域 O(1) という非常に効率的な形で解決できます。
ポイントは、配列のサイズが n であり、その要素がちょうど[0〜n]の範囲に収まっているという点です。そこで、各要素・各インデックス・そして n のすべてに対して XOR 演算を順に行うと、同じ値同士の XOR は打ち消し合うため、最終的に残る値こそが配列から欠けている一意の数値となります。
- [0〜n]の範囲の要素を持つ、サイズNの配列を入力として受け取ります。
- 整数関数 findMissingNumber(int arr[], int size) は、配列とそのサイズを引数として受け取り、欠損数を返します。
- 欠損数を格納する変数の初期値として n を設定します。
- すべての配列要素を走査し、各要素とそのインデックスを、欠損数の変数に対して XOR 演算していきます。
- ループ終了後、変数に残った値が欠損数となるので、それを返します。
コード例
#include<bits/stdc++.h>
using namespace std;
int findMissingNumber(int *arr, int size){
int missing_no= size;
for(int i=0;i<size;i++){
missing_no^= i^arr[i];
}
return missing_no;
}
int main(){
int n= 6;
int arr[n]= {0,4,2,1,6,3};
cout<<findMissingNumber(arr,n)<<endl;
return 0;
}
出力
上記のコードを実行すると、次の出力が表示されます。
5
配列の各要素とそのインデックスに対して XOR 演算を行うことで、配列に存在しない「5」が正しく検出され、出力されます。
-
C++で単調増加数列から最大の集計値を求める方法【DFS全探索】
問題の概要 2つの整数 n と m、さらに4つの整数 {ai, bi, ci, di} を含む k 個のタプルが与えられているとします。配列 a、b、c、d の4つが入力として渡され、a[i] は i 番目のタプルの a の値を表します。 ここで、n 個の正の整数からなる狭義単調増加の数列 dp(1 ≤ dp[1] < dp[2] < … < dp[n] ≤ m)を考えます。「集計(tally)」という指標を次のように定義します。 集計 = 条件 dp[b[i]] − dp[a[i]] = c[i] を満たすすべての添字 i における d[i] の総和 該当する i がひとつ
-
【C++】グラフ内の橋(ブリッジエッジ)の数を検出するプログラムの解説
ブリッジエッジ(橋)とは? 重みなし無向グラフにおけるブリッジエッジ(橋)とは、その辺を取り除いたときにグラフが非連結(複数の連結成分に分断される)となるような辺のことです。本記事では、n個の頂点とm個の辺からなるグラフが与えられたとき、その中に含まれるブリッジの数を求めるC++プログラムを紹介します。なお、対象となるグラフには平行辺や自己ループは含まれないものとします。 問題の例 例として、n = 5、m = 6、edges = {{1, 2}, {1, 3}, {2, 3}, {2, 4}, {2, 5}, {3, 5}} という入力が与えられた場合を考えてみましょう。この場合の出力は