有限状态机、正则表达式、数字转字符串解密、字符串全排列、拼接数组中的数字

拼接数组中的数字( 有问题??? )

输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

  • 当仿函数中使用<=进行比较时, 如果有过多的0, 会造成溢出, 为什么?????
class Solution {
public:
    class Itos
    {
    public:
        string operator()(int val)
        {
            return to_string(val);
        }
    };
    class Cmp
    {
    public:
        bool operator()(string& s1, string& s2)
        {
            // 如果是<= 当有过多的0时, 会造成溢出
            if(s1 + s2 < s2 + s1)
                return true;
            else
                return false;
        }
    };
    string minNumber(vector<int>& nums) {
        vector<string> v;
        v.resize(nums.size());
        transform(nums.begin(), nums.end(), v.begin(), Itos());
        sort(v.begin(), v.end(), Cmp());
        string res = "";
        for(auto& s : v)
        {
            res = res + s;
        }
        return res;
    }
};

字符串全排列

  • 原来的思路是对每一个位, 都遍历所有字符, 但是会存在重复位需要用visited标记, 同时相同排列需要最后使用set去重.
  • 新思路 : 使用swap避免了visited标记, 将所需字母交换到当前位后, 每次只遍历当前需要确定的位到最后一位, 巧妙的进行了剪枝; 同时在每一位循环中, 使用一个set, 避免当前位出现重复字母的情况; 而且全程在原字符串s上操作, 避免了新建一个字符串记录.
class Solution {
public:
    vector<string> res;
    /*
    vector<bool> visited;
    void dfs(string& s, string& temp)
    {
        if(temp.size() == s.size())
        {
            res.push_back(temp);
            return ;
        }
        for(int i = 0; i < s.size(); i++)
        {
            if(visited[i] == false)
            {
                temp += s[i];
                visited[i] = true;
                dfs(s, temp);
                visited[i] = false;
                temp = temp.substr(0, temp.size()-1);
            }
        }
    }
    */
    void swap(int i, int j, string& s)
    {
        char temp = s[i];
        s[i] = s[j];
        s[j] = temp;
    }
    void dfs(int x, int n, string& s)
    {
        if(x == n-1)
        {
            res.push_back(s);
            return ;
        }

        set<char> st;
        for(int i = x; i < n; i++)
        {
            if(st.find(s[i]) != st.end()) continue;
            st.insert(s[i]);
            swap(i, x, s);
            dfs(x+1, n, s);
            swap(i, x, s);
        }
    }
    vector<string> permutation(string s) {
        // string temp = "";
        // visited.resize(s.size());
        dfs(0, s.size(), s);
        // set<string> ss(res.begin(), res.end());
        // res.assign(ss.begin(), ss.end());
        return res;
    }
};

数字转字符串解密

  • 向这种后面的需要依赖前面的, 递归 的优化就是 DP
  • DP空间再看是否可以进一步优化
  • 这一题从左往右解密 和 从右往左解密是一样的结果
class Solution {
public:
    char itos(int val)
    {
        char word = 'a' + val;
        return word;
    }
    set<string> st;
    
    void dfs(int x, string& s, string& temp)
    {
        if(x >= s.size())
        {
            st.insert(temp);
            return ;
        }
        for(int i = 1; i <= 2; i++)
        {
            if(i == 1 || (i == 2 && s[x] != '0'))
            {
                int num = stoi(s.substr(x, i));
                if(num <= 25)
                {
                    temp += itos(num);
                    dfs(x+i, s, temp);
                    temp = temp.substr(0, temp.size()-1);
                }
            }
        }
    }

    int dp_f(int num)
    {
        string s = to_string(num);
        int n = s.size();
        vector<int> dp(n+1, 1); // 因为dp数组只和前面两个状态有关, 只用两个变量记住前两个状态即可
        for(int i = 2; i <= n; i++)
        {
            dp[i] = dp[i-1];
            // "05"这种情况去除
            if(i-2>=0 && s[i-2] !='0' && s.substr(i-2, 2) >= "0" && s.substr(i-2, 2) <= "25" )
                dp[i] += dp[i-2];
        }
        return dp[n];
    }
    int dp_youhua(int num)
    {
        string s = to_string(num);
        int n = s.size();
        int a = 1;
        int b = 1;
        for(int i = 2; i <= n; i++)
        {
            // "05"这种情况去除
            if(i-2>=0 && s[i-2] !='0' && s.substr(i-2, 2) >= "0" && s.substr(i-2, 2) <= "25" )
            {
                b = a + b;
                a = b - a;
            }
            else
                a = b;
        }
        return b;
    }
    // 从左往右 和 从右往左 解密结果是一样的
    int mod_f(int num)
    {
        int a = 1;
        int b = 1;
        int x = num%10, y = num%10;
        while(num)
        {
            num /= 10;
            x = num % 10;
            int temp = x * 10 + y;
            int c = (temp >= 10 && temp <= 25)?a + b: b;
            a = b;
            b = c;
            y = x;
        }
        return b;
    }
    int translateNum(int num) {
        /*
        string s = to_string(num);
        string temp = "";
        dfs(0, s, temp);
        return st.size();
        */
        return mod_f(num);
    }
};

正则表达式

  • 正则表达式需要反着匹配思考, 因为* 会把前面一个重复任意次.
class Solution {
public:
    bool isMatch(string s, string p) {
        int n = s.size();
        int m = p.size();
        // 数组不能动态分配大小, int arr[n] n必须是一个常量表达式, 任何在运行阶段才能确定的值都不可以
        vector<vector<bool>> dp(n+1, vector<bool>(m+1, false));
        dp[0][0] = true;
        // 处理特殊情况的*
        for(int j = 1; j <= m; j++)
        {
            if(p[j-1] == '*')
                dp[0][j] = dp[0][j-2];
        }
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= m; j++)
            {
                if(p[j-1] != '.' && p[j-1] != '*')
                    dp[i][j] = s[i-1] == p[j-1] && dp[i-1][j-1];
                else if (p[j-1] == '.')
                    dp[i][j] = dp[i-1][j-1];
                else if (p[j-2] == s[i-1] || p[j-2] == '.')
                    dp[i][j] = (dp[i-1][j] || dp[i][j-2]);
                else
                    dp[i][j] = dp[i][j-2];
            }
        }
        return dp[n][m];
    }
};

有限状态机

  • 使用vector的下标表示状态, vector中存放map, 表示该状态下遇到key, 需要跳转到value状态

图片来源力扣用户@Krahets

在这里插入图片描述

class Solution {
public:
    void init_states(vector<map<char, int>>& states)
    {
        map<char, int> mp;
        mp[' '] = 0;
        mp['s'] = 1;
        mp['d'] = 2;
        mp['.'] = 4;
        states.push_back(mp);
        mp.clear();

        mp['d'] = 2;
        mp['.'] = 4;
        states.push_back(mp);
        mp.clear();

        mp['d'] = 2;
        mp['.'] = 3;
        mp['e'] = 5;
        mp[' '] = 8;
        states.push_back(mp);
        mp.clear();

        mp['d'] = 3;
        mp['e'] = 5;
        mp[' '] = 8;
        states.push_back(mp);
        mp.clear();

        mp['d'] = 3;
        states.push_back(mp);
        mp.clear();

        mp['s'] = 6;
        mp['d'] = 7;
        states.push_back(mp);
        mp.clear();

        mp['d'] = 7;
        states.push_back(mp);
        mp.clear();

        mp['d'] = 7;
        mp[' '] = 8;
        states.push_back(mp);
        mp.clear();

        mp[' '] = 8;
        states.push_back(mp);
        mp.clear();
    }
    bool isNumber(string s) {
        vector<map<char, int>> states;
        init_states(states);

        int p = 0;
        char t;
        for(auto& 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(states[p].find(t) == states[p].end()) return false;
            p = states[p][t];
        }
    return p == 2 || p == 3 || p == 7 || p == 8;
    }
};
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页