C++でASCII値の合計がk未満・k超過の単語数をカウントする方法
文字列 str(1つの文章)と整数 k が与えられます。この問題の目的は、str に含まれる単語のうち、ASCII値の合計が k 未満になる単語の数と、k より大きくなる単語の数をそれぞれ求めることです。
ASCIIとは
ASCII(アスキー)とは、言語を構成する各文字に割り当てられた一意のコード番号のことです。英字・数字・記号にはそれぞれ固有の数値が対応しており、単語を構成する各文字のコード値を足し合わせることで、単語ごとの合計値を計算できます。
具体例で理解しよう
例1
入力: str = “This is ASCII”、k = 300
出力:
- ASCII値の合計がk未満の単語数:1
- ASCII値の合計がkより大きい単語数:2
説明: 単語 “is” のASCII値の合計は220で300未満ですが、“This”(408)と “ASCII”(361)は300を超えています。
例2
入力: str = “set set set”、k = 300
出力:
- ASCII値の合計がk未満の単語数:0
- ASCII値の合計がkより大きい単語数:3
説明: すべての単語が同一の “set” であり、そのASCII値の合計は332で300を超えるためです。
プログラムのアプローチ
forループで文字列 str を先頭から1文字ずつ走査し、空白文字に到達したタイミングで「1単語分のASCII値の合計」が確定したとみなします。その合計値を k と比較することで、単語を「k未満」「k以上」に分類していきます。処理の手順は以下の通りです。
- 文字列
strと整数kを受け取ります。 - 関数
words_less_greater(string str, int k, int length)が、ASCII値の合計がk未満およびkより大きい単語の個数を求めます。 - 各単語のASCII値の合計を格納するため、変数
tempを0で初期化します。 - ASCII値の合計がk未満の単語数を数えるため、変数
countを0で初期化します。 - 単語の総数を数えるため、変数
totalを0で初期化します。 - forループで
strを走査します。 - 空白文字(
str[i] == ' ')に到達したら、1単語分の合計tempがk未満かどうかを判定します。未満ならcountをインクリメントします。その後、totalをインクリメントし、tempを0にリセットして次の単語へ移ります。 - 空白以外の文字の場合は、その文字のASCII値を
tempに加算し続けます。 - ループを抜けた後は最後の単語が未処理のまま残るため、
totalをさらにインクリメントし、最後の単語に対しても同じ判定を行います。 - 最終的に、
countがk未満の単語数、total - countがkより大きい単語数となります。これらの結果を出力します。
C++による実装例
#include <bits/stdc++.h>
using namespace std;
void words_less_greater(string str, int k, int length){
int temp = 0;
int total = 0;
int count = 0;
for (int i = 0; i < length; ++i){
if (str[i] == ' '){
if (temp < k){
count++;
}
temp = 0;
total++;
}
else{
temp += str[i];
}
}
total++;
if (temp < k){
count++;
}
cout<<"Count of number of words having sum of ASCII values less than k are: "<< count;
cout<<"\nCount of number of words having sum of ASCII values greater than k are: "<< total -
count;
}
int main(){
string str = "tutorials point";
int k = 900;
int length = str.length();
words_less_greater(str, k, length);
return 0;
}
実行結果
上記のコードを実行すると、次の出力が得られます。
Count of number of words having sum of ASCII values less than k are: 1 Count of number of words having sum of ASCII values greater than k are: 1
この例では文字列 “tutorials point”、k = 900 を使用しています。“point” のASCII値の合計は554で900未満、“tutorials” は999で900を超えるため、それぞれ1語ずつカウントされるのです。
計算量について
この手法では文字列を1回走査するだけで済むため、時間計算量は O(n)(nは文字列の長さ)、追加のメモリ使用量は O(1) ときわめて効率的です。そのため、長いテキストでも高速に処理できる点が大きな魅力といえます。
-
C++でXとの合計がフィボナッチ数になるノードを数える方法
各ノードに数値の重みが割り当てられた二分木が与えられます。この記事の目的は、「ノードの重み + X」の計算結果がフィボナッチ数となるノードの個数を求めることです。フィボナッチ数列とは、0, 1, 1, 2, 3, 5, 8, 13… のように続く数列で、n番目の数は(n−1)番目と(n−2)番目の数の和になります。たとえば重みが13であればフィボナッチ数に該当するため、そのノードはカウント対象となります。入力例1temp = 1 の場合。値を入力すると、以下のような木が構成されます。出力Count the nodes whose sum with X is a Fibonacci number
-
サイズKの部分配列のうち平均が閾値以上になる個数をC++で求める方法
整数型の配列 arr と、2つの整数 k および threshold が与えられます。このとき、サイズが k で平均が threshold 以上となる部分配列(サブアレイ)の個数を求めるのが目的です。例として、入力が [2,2,2,2,5,5,5,8]、k = 3、threshold = 4 の場合を考えてみましょう。このとき出力は 3 になります。これは、部分配列 [2,5,5]、[5,5,5]、[5,5,8] の平均がそれぞれ 4、5、6 となり、いずれも閾値 4 以上だからです。解法のアプローチ(スライディングウィンドウ)この問題は、スライディングウィンドウ(尺取り法)を使えば効率的に解