Jianzhi Offer(C++)-JZ67: 文字列を整数に変換する (アルゴリズム シミュレーション)

著者: Zhai Tianbao Steven
著作権表示: 著作権は著者に属します。商業的転載の場合は、作者に連絡して許可を求めてください。非商業的な転載の場合は、出典を示してください。

トピックの説明:

文字列を整数に変換する関数 StrToInt を作成します。atoi などのライブラリ関数は使用できません。受信文字列は次の部分で構成されます。

1. いくつかのスペース

2. (オプション) 記号文字 (「+」または「-」)

3. 数字、文字、記号、スペースで構成される文字列式

4. いくつかのスペース

変換アルゴリズムは次のとおりです:
1. 先頭の無駄なスペースを削除します
2. 最初の空でない文字が + または - 記号の場合、それが整数の符号として使用されます。符号がない場合は、デフォルトで正の値が使用されます。数値
3. 整数の有効な部分を決定する:
3.1 符号ビットを決定した後、それをできるだけ多くの連続する数値と結合して有効な整数になります。有効な整数部分がない場合は、直接 0 を返します。 3.2
取り出し文字列の前の整数部分、後で冗長なものが存在する可能性があります 文字 (文字、記号、スペースなど)、これらの文字は無視できますが、機能に影響を与えるべきではありません 3.3 整数が 32 を超えてい
ますビット符号付き整数の範囲 [−2 31 , 2 31  − 1] の場合、この範囲内に収まるように整数を切り捨てる必要があります。具体的には、-2 31未満の整数は-2 31に調整され、2 31 − 1 より大きい整数は2 31  − 1 4 に調整される必要があります。不要な末尾のスペースを削除します。

データ範囲:

1.0 <= 文字列長 <= 100

2. 文字列は、英字 (大文字と小文字)、数字 (0 ~ 9)、「 」、「+」、「-」、「.」で構成されます。

例:

入力:

「4396クリアラブ」

戻り値:

4396

例証します:

6 以降の文字は有効な整数部分に属さないため削除されますが、前に抽出した有効な部分が返されます。

問題解決のアイデア:

この質問では、アルゴリズム シナリオ シミュレーションについて調べます。問題を解決する 2 つの方法。

1) トラバース方式

       まず先頭のスペースをフィルタリングし、次に正負の符号を判定し、その過程で正負の限界判定に注意しながら連続する数値を判定し、新しい数値を見つけるたびに前の数値 * 10 を加算し、横断した後に答えが得られます。複雑さ O(n)。

2) ステートマシン

       状態遷移行列に基づいて文字列トラバーサル プロセスの状態を分析します。

       ステータスは0123に対応し、スペース、記号、数字、無効の4種類に分かれています。マトリックスは質問条件に応じて以下のように設定されています。

\begin{bmatrix} 0 & 1 & 2 & 3\\ 3 & 3& 2 & 3\\ 3& 3& 2 & 3 \end{bmatrix}

  1. 開始状態は 0 で、最初の行が分析されます。スペースが見つかった場合、次の状態は 0 のままです。記号が見つかった場合、状態は 1 に変わります。数字が見つかった場合、状態は 2 に変わります。無効な文字が見つかった場合、ステータスは 3 に変わります。
  2. ステータスが 1 に変化すると仮定して、2 行目を分析します。スペース、つまり + スペースが見つかった場合は無効であるため、2 行目の最初の列は 3 になります。+ などの記号が再び見つかった場合は、 -、これも無効であるため、2 行目の 2 列目は 3 になります。-3 などの数値が見つかった場合、ステータスは 2 に変更され、無効な文字が見つかった場合、ステータスは 3 に変更されます。
  3. ステータスが 2 に変化すると仮定して、3 行目を分析します。+8 スペースや 8 スペースなどのスペースが見つかった場合、後続の手順は無効になるため、3 行目の最初の列は 3 になります。シンボルが+8+ や 8+ などの数字が見つかった場合、後続のものも無効であるため、3 行目の 2 列目は 3 になります。 +89 や 89 などの数字が見つかった場合、後続のものは有効です。 3 行目の 3 列目は 2 で、無効な文字は同様に無効です。
  4. ステータスが2の場合は数値が蓄積されて場外判定が行われ、ステータスが3の場合はブレイクするだけで終了します。

       一般に、ステート マシンは、質問の要件に基づいて、考えられる状況と状態遷移をマトリックス形式で表し、問題を解決します。複雑さ O(n)。

テストコード:

1) 選別方法

#include <climits>
class Solution {
public:
    // 字符串转为整数
    int StrToInt(string s) {
        int sign = 1;
        int idx = 0;
        int size = int(s.size());
        // 前空格过滤,过滤完如果没有后续则退出
        while(idx < size){
            if(s[idx] == ' ')
                idx++;
            else
                break;
        }
        if(idx == size)
            return 0;
        // 判断符号,如果没有后续则退出
        if(s[idx] == '+')
            idx++;
        else if(s[idx] == '-'){
            idx++;
            sign = -1;
        }
        if(idx == size)
            return 0;
        // 继续遍历寻找目标数字
        int result = 0;
        while(idx < size){
            // 遇到非数字退出
            if(s[idx] < '0' || s[idx] > '9')
                break;
            // 判断极限
            if(result > INT_MAX / 10 || (result == INT_MAX / 10 && (s[idx] - '0') >= (INT_MAX % 10)))
                return INT_MAX;
            if(result < INT_MIN / 10 || (result == INT_MIN / 10 && (s[idx] - '0') >= -(INT_MIN % 10)))
                return INT_MIN;
            // 字符转为数字
            result = result * 10 + sign * (s[idx] - '0');
            idx++;
        }
        return result;
    }
};

2) ステートマシン

class Solution {
public:
    // 字符串转为整数
    int StrToInt(string s) {
        // 状态转移矩阵
        vector<vector<int>> states = {
            {0,1,2,3},
            {3,3,2,3},
            {3,3,2,3},
        }; 
        // 定义
        long result = 0;
        long top = INT_MAX;  
        long bottom = INT_MIN;
        int sign = 1;
        int size = int(s.length());
        // 状态从0开始
        int state = 0; 
        for(int i = 0; i < size; ++i){
            // 空格
            if(s[i] == ' '){
                state = states[state][0]; 
            }
            // 正负号 
            else if(s[i] == '-' || s[i] == '+'){ 
                state = states[state][1]; 
                if(state == 1){
                    sign = (s[i] == '-') ? -1 : 1;
                }    
            }
            // 数字
            else if(s[i] >= '0' && s[i] <= '9'){
                state = states[state][2]; 
            }   
            // 非法字符
            else{
                state = states[state][3]; 
            }
            // 状态为2时,表明在连续数字状态,进行数字累加
            if(state == 2){
                // 数字相加
                result = result * 10 + s[i] - '0'; 
                // 越界处理
                result = (sign == 1) ? min(result, top) : min(result, -bottom); 
            }
            // 状态为3时,说明后续无效,退出即可
            else if(state == 3)
                break;
        }
        return (int)sign * result;
    }
};

おすすめ

転載: blog.csdn.net/zhaitianbao/article/details/132844648