表示數值的字符串(有限狀態自動機與搜索)

文章目錄

  • 題目
  • 思路一
  • 代碼一
  • 思路二
  • 代碼二


題目

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

思路一

考察有限狀態自動機(參考jyd):

字符類型:

空格 「 」、數字「 0—9 」 、正負號 「 ± 」 、小數點 「 . 」 、冪符號 「 eE 」 。

狀態定義:

按照字符串從左到右的順序,定義以下 9 種狀態:

  1. 開始的空格
  2. 冪符號前的正負號
  3. 小數點前的數字
  4. 小數點、小數點后的數字
  5. 當小數點前為空格時,小數點、小數點后的數字
  6. 冪符號
  7. 冪符號后的正負號
  8. 冪符號后的數字
  9. 結尾的空格

結束狀態:

合法的結束狀態有 2, 3, 7, 8 。
在這里插入圖片描述
算法流程:

  1. 初始化:

    1. 狀態轉移表 maps : 設 maps[i] ,其中 i 為所處狀態(9種之一), maps[i] 使用哈希表存儲可轉移至的狀態。鍵值對 (key, value) 含義:若此時的字符是 key ,則可從狀態 i 轉移至狀態 value 。
    2. 當前狀態 p : 起始狀態初始化為 p = 0 。
  2. 狀態轉移循環: 遍歷字符串 s 的每個字符 c 。

    1. 記錄字符類型 t : 分為四種情況。

      • 當 c 為正負號時,執行 t = 's' ;
      • 當 c 為數字時,執行 t = 'd' ;
      • 當 c 為 e , E 時,執行 t = 'e' ;
      • 當 c 為 . , 空格 時,執行 t = c (即用字符本身表示字符類型);
      • 否則,執行 t = ‘?’ ,代表為不屬于判斷范圍的非法字符,后續直接返回 false。
    2. 終止條件: 若字符類型 t 不在哈希表 maps[p] 中,說明無法轉移至下一狀態,因此直接返回 False 。

    3. 狀態轉移: 狀態 p 轉移至 maps[p][t]

  3. 返回值: 跳出循環后,若狀態 p∈2,3,7,8 ,說明結尾合法,返回 True ,否則返回 False 。

再詳細說一下狀態轉移表的作用(下面代碼部分的注釋中有結合實例進行詳解):

  • 處于第 i 行表明此時遍歷到的字符是第 i+1 種狀態(可以對照上文的狀態定義)
  • 那么我下一個字符可以是第 i 行中的各個 key 對應的字符。
  • 如果某字符沒有寫進第 i 行,表示 i+1 狀態的下一個字符不應是某字符

復雜度分析:

  1. 時間復雜度 O(N) : 其中 N 為字符串 s 的長度,判斷需遍歷字符串,每輪狀態轉移的使用 O(1) 時間。
  2. 空間復雜度 O(1) : maps 和 p 使用常數大小的額外空間。

代碼一

class Solution {
public:bool isNumber(string s) {vector<map<char,int>> maps = {
// 狀態轉移表
// 以第一行為例,狀態轉移表的含義為:
// 開始的空格其下一個字符可以繼續是空格,也可以是符號、數字、小數點,
// 但不可是第0行不存在的e。
// 也就是為了保證字符串是數值,空格后面不能直接跟一個冪符號。{{' ', 0},  {'s', 1},  {'d', 2},  {'.', 4}}, // 開始的空格{{'d', 2}, {'.', 4}}, // 冪符號前的正負號{{'d', 2}, {'.', 3}, {'e', 5}, {' ', 8}}, // 小數點前的數字{{'d', 3}, {'e', 5}, {' ', 8}}, // 小數點、小數點后的數字{{'d', 3}}, // 當小數點前為空格時,小數點、小數點后的數字{{'s', 6}, {'d', 7}}, // 冪符號{{'d', 7}}, // 冪符號后的正負號{{'d', 7}, {' ', 8}}, // 冪符號后的數字{{' ', 8}} // 結尾的空格};int p = 0; //起始狀態char t;for(char c : s) {if(c >= '0' && c <= '9') t = 'd';else if(c == '+' || c == '-') t = 's';else if(c == 'e' || c == 'E') t = 'e';else if(c == '.' || c == ' ') t = c;else t = '?';if(maps[p].find(t) == maps[p].end()) return false;p = maps[p][t];}return p == 2 || p == 3 || p == 7 || p == 8;}
};

思路二

用 bool 類型變量 ret 存儲搜索過程中的結果,整個搜索過程如下:

  1. 過濾首部空格
  2. 過濾正負號,緊接著檢查是否有數字
  3. 遇到第一個不是數字的字符,應為 '.' 或者 e
  4. '.' 的后面可以有 e,但 e 的后面不能有 '.' ,所以先處理 '.' 再處理 e
  5. '.' 前面可以什么都沒有,后面也可以什么都沒有,只要有一邊有數據就行
  6. e 的前后必須都要有數據,并且后面可以存在正負號,所以需要過濾正負號
  7. 過濾尾部空格
  8. 檢查 ret 狀態以及是否已經遍歷完字符串

關于第8點檢查是否已經遍歷完字符串:

因為如果字符串是數值,尾部空格應該是字符串的末尾部分倒數幾個字符,空格完了字符串應該也就結束了。如果過濾完了尾部空格還有字符,說明該字符串不是數值。

代碼二

class Solution {
public:bool scanDigit(string s, int& i){int count = i;while(i != s.size()){if(isdigit(s[i]))++i;elsebreak;}return i > count;//如果數據中沒有一個數字,則直接返回false,有則返回true}bool scanSign(string s, int& i){if(i < s.size() && s[i] == '+' || s[i] == '-'){++i;}//過濾正負號return scanDigit(s, i);}bool isNumber(string s) {if(s.empty())return false;int i = 0;while(s[i] == ' ')++i;//過濾首部空格bool ret = scanSign(s, i);//第一遍搜索,先走完.或者e前的所有數字//.的后面可以有e,但e的后面不能有.,所以先處理.再處理eif(i < s.size() && s[i] == '.'){ret = scanDigit(s, ++i) || ret;//.前面可以什么都沒有,后面也可以什么都沒有,只要有一邊有數據就行}if(i < s.size() && (s[i] == 'e' || s[i] == 'E')){ret = scanSign(s, ++i) && ret;//e的前后必須都要有數據,并且e后面可以存在正負號,所以需要過濾正負號}while(s[i] == ' ')++i;//因為空格只能出現在末尾和首部,過濾空格return ret && (i == s.size());//當e后面有數據,并且字符串全部走完,說明數據成立}
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443793.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443793.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443793.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

樹的子結構

文章目錄題目深搜深搜代碼廣搜廣搜代碼題目 輸入兩棵二叉樹A和B&#xff0c;判斷B是不是A的子結構。(約定空樹不是任意一個樹的子結構) B是A的子結構&#xff0c; 即 A中有出現和B相同的結構和節點值。 例如: 給定的樹 A: 給定的樹 B&#xff1a; 返回 true&#xff0c;因為…

寫題過程中碰見的小問題

文章目錄和--vector二維vector的初始化數組中最大的數max_element()數組所有元素之和accumulate()vector數組去重對pair類型的vector排序對元素都為正整數的vector利用sort默認的升序排列進行降序排列一維數組轉二維數組size_t和int如何不用臨時變量交換兩個數?將類函數的形參…

LeetCode——二叉樹序列化與反序列化

文章目錄題目思路問題一問題二代碼實現題目 請實現兩個函數&#xff0c;分別用來序列化和反序列化二叉樹。 設計一個算法來實現二叉樹的序列化與反序列化。不限定序列 / 反序列化算法執行邏輯&#xff0c;你只需要保證一個二叉樹可以被序列化為一個字符串并且將這個字符串反序…

jsp中生成的驗證碼和存在session里面的驗證碼不一致的處理

今天在調試項目的時候發現&#xff0c;在提交表單的時候的驗證碼有問題&#xff0c;問題是這樣的&#xff1a;就是通過debug模式查看得知&#xff1a;jsp頁面生成的驗證碼和表單輸入的頁面輸入的一樣&#xff0c;但是到后臺執行的時候&#xff0c;你會發現他們是不一樣的&#…

求1~n這n個整數十進制表示中1出現的次數

文章目錄題目思路代碼復雜度分析題目 輸入一個整數 n &#xff0c;求1&#xff5e;n這n個整數的十進制表示中1出現的次數。 例如&#xff0c;輸入12&#xff0c;那么1&#xff5e;12這些整數中包含1 的數字有1、10、11和12。可得1一共出現了5次。 思路 將個位、十位……每位…

求數字序列中的第n位對應的數字

文章目錄題目思路代碼復雜度分析致謝題目 數字以0123456789101112131415…的格式序列化到一個字符序列中。在這個序列中&#xff0c;第5位&#xff08;從下標0開始計數&#xff09;是5&#xff0c;第13位是1&#xff0c;第19位是4&#xff0c;等等。 請寫一個函數&#xff0c…

一學就廢的歸并排序

文章目錄其他與排序有關的文章原理代碼實現復雜度分析其他與排序有關的文章 一學就廢的三種簡單排序【冒泡、插入、選擇】 原理 歸并排序&#xff08;Merge sort&#xff09;&#xff1a; 歸并排序對元素 遞歸地 進行 逐層折半分組&#xff0c;然后從最小分組開始&#xff0c…

神奇的x -x,Lowbit函數的實現方式!

文章目錄-xx & -x&#xff0c;當x為偶數時x & -x&#xff0c;當x為奇數時x&-x 的實際用途-x -x 在二進制里表示對 x 的二進制按位取反(~x)之后再加 1 &#xff0c;即 -x ~x1x & -x&#xff0c;當x為偶數時 在執行 x & -x 時&#xff0c;若 x 為偶數&am…

JAVA實現把指定文件夾下的所有文件壓縮成zip包

1.代碼如下&#xff1a; package cn.gov.csrc.base.util;import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import…

樹狀數組的相關知識 及 求逆序對的運用

文章目錄樹狀數組概念前綴和和區間和樹狀數組原理區間和——單點更新前綴和——區間查詢完整代碼離散化sort函數unique函數去重erase函數僅保留不重復元素通過樹狀數組求逆序對樹狀數組概念 樹狀數組又名二叉索引樹&#xff0c;其查詢與插入的復雜度都為 O(logN)&#xff0c;其…

二叉搜索樹相關知識及應用操作

文章目錄概念查找二叉搜索樹的第k大節點概念 二叉查找樹&#xff08;Binary Search Tree&#xff09;&#xff0c;&#xff08;又名&#xff1a;二叉搜索樹&#xff0c;二叉排序樹&#xff09;——它或者是一棵空樹&#xff0c;或者是具有下列性質的二叉樹&#xff1a; 若它的…

二叉樹相關知識及求深度的代碼實現

文章目錄樹二叉樹滿二叉樹和完全二叉樹二叉樹的性質代碼實現求二叉樹的深度樹 樹是一種非線性的數據結構&#xff0c;它是由n個有限結點組成一個具有層次關系的集合。 樹的相關名詞&#xff1a; 根節點&#xff1a;沒有前驅結點的結點。父節點&#xff0c;子節點&#xff1a…

平衡樹相關知識及如何判斷一棵樹是否平衡

文章目錄概念代碼實現判斷一棵二叉樹是否為平衡樹概念 平衡樹(Balance Tree&#xff0c;BT) 指的是&#xff0c;任意節點的子樹的高度差都小于等于1。 常見的符合平衡樹的有&#xff1a; B樹&#xff08;多路平衡搜索樹&#xff09;AVL樹&#xff08;二叉平衡搜索樹&#xf…

大端小端存儲模式詳解及判斷方法

文章目錄大小端模式的概念兩種模式出現原因兩種模式的優劣大小端的應用情景判斷機器的字節序大小端模式的概念 當我們查看數據在內存中的存儲情況時&#xff0c;我們經常會發現一個很奇怪的現象&#xff0c;什么現象呢&#xff1f; int main() {int i 12;return 0; }數據在內…

Linux 內存管理 | 物理內存、內存碎片、伙伴系統、SLAB分配器

文章目錄物理內存物理內存分配外部碎片內部碎片伙伴系統(buddy system)slab分配器物理內存 在Linux中&#xff0c;內核將物理內存劃分為三個區域。 在解釋DMA內存區域之前解釋一下什么是DMA&#xff1a; DMA&#xff08;直接存儲器訪問&#xff09; 使用物理地址訪問內存&am…

Linux 內存管理 | 虛擬內存管理:虛擬內存空間、虛擬內存分配

文章目錄虛擬地址空間用戶空間內核空間用戶空間內存分配malloc內核空間內存分配kmallocvmalloc虛擬地址空間 在早期的計算機中&#xff0c;程序是直接運行在物理內存上的&#xff0c;而直接使用物理內存&#xff0c;通常都會面臨以下幾種問題&#xff1a; 內存缺乏訪問控制&a…

Linux | 編譯原理、gcc的命令參數、自動化構建工具 make/Makefile

文章目錄編譯原理預處理編譯匯編鏈接gcc的常用命令參數make 和 Makefile 的概念make的運行通配符自動化變量偽目標.PHONE:【命令】編譯原理 在解釋 makefile 前&#xff0c;首先解釋一下 .c 文件變成 .exe 文件要經過的四個步驟——預處理、編譯、匯編和鏈接&#xff08;參考來…

全排列變種:限定 排列的差值范圍 及 排列中的元素個數

文章目錄題目描述思路代碼實現題目描述 詳細描述&#xff1a;字節跳動2019春招研發部分編程題——萬萬沒想到之抓捕孔連順 輸入描述&#xff1a; 第一行包含空格分隔的兩個數字 N和D(1?≤?N?≤?1000000; 1?≤?D?≤?1000000) 第二行包含N個整數&#xff08;取值區間為…

Linux | 進程概念、進程狀態(僵尸進程、孤兒進程、守護進程)、進程地址空間

文章目錄進程和程序操作系統如何控制和調度程序進程控制塊–PCB子進程進程狀態僵尸進程孤兒進程守護進程&#xff08;精靈進程&#xff09;進程地址空間引言頁表進程和程序 程序&#xff1a; 一系列有序的指令集合&#xff08;就是我們寫的代碼&#xff09;。進程&#xff1a;…

Linux 進程控制 :進程創建,進程終止,進程等待,程序替換

文章目錄進程創建進程等待程序替換進程終止進程創建 fork函數&#xff1a; 操作系統提供的創建新進程的方法&#xff0c;父進程通過調用 fork函數 創建一個子進程&#xff0c;父子進程代碼共享&#xff0c;數據獨有。 當調用 fork函數 時&#xff0c;通過 寫時拷貝技術 來拷貝…