C++
 Computer >> コンピューター >  >> プログラミング >> C++

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単語分の合計 tempk 未満かどうかを判定します。未満なら 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) ときわめて効率的です。そのため、長いテキストでも高速に処理できる点が大きな魅力といえます。

  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

  2. サイズ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 以上だからです。解法のアプローチ(スライディングウィンドウ)この問題は、スライディングウィンドウ(尺取り法)を使えば効率的に解