题意整理:
凯撒密码既对原字符串进行字符移位得到新的字符串的简单加密算法,题目给出加密后的字符串和移动位数,要求算出原字符串。
下图简单描述的凯撒密码的加密算法
方法一:构造字符串序列后移位计算
核心思想:
构造出一个表示序列的字符串,既构成的字符串,然后进行移位计算即可,需要对溢出进行处理,既小于d位置的字符移位d位后,不足部分从字符串尾端开始处理,既将序列视为循环序列
核心代码:
class Solution { public: string decode(string str, int d) { string s; //构造字符串序列 for(int i = 0; i <= 9; ++i) { s.push_back(i + '0'); } for(int i = 0; i < 26; ++i) { s.push_back(i + 'A'); } for(int i = 0; i < 26; ++i) { s.push_back(i + 'a'); } for(char& w : str) { int p = s.find(w); w = d > p ? s[62 - d + p] : s[p - d];//如果超过字符串头部则不足部分从尾部获取 } return str; } };
复杂度分析:
时间复杂度:。其中n为密码序列长度,m为字符串序列长度,此处m固定为62.需要对每个密码字符处理,每次的函数开销为
空间复杂度:,m为字符串序列长度,此处m固定为62,既可以视为,其他部分使用的都是常数个变量
方法二:时间优化
核心思想:
方法一每次都需对密码字符位置和d进行比较后确定解密字符,这会增加时间开销。而这种判断是为了处理字符解码越过首字符的问题,所以可以通过双倍长的字符串序列解决,相当于是空间换时间的策略
核心代码:
class Solution { public: string decode(string str, int d) { string s; //构造字符串序列 for(int i = 0; i <= 9; ++i) { s.push_back(i + '0'); } for(int i = 0; i < 26; ++i) { s.push_back(i + 'A'); } for(int i = 0; i < 26; ++i) { s.push_back(i + 'a'); } s += s;//双倍序列,无需处理越界 for(char& w : str) { int p = s.find(w) + 62;//获取后半部位置 w = s[p - d]; } return str; } };
复杂度分析:
时间复杂度:。其中n为密码序列长度,m为字符串序列长度的一半(因为必然在前半部找到所需字符),故此处m仍然固定为62.需要对每个密码字符处理,每次的函数开销为
空间复杂度:,m为字符串序列长度,此处m固定为124,既可以视为,其他部分使用的都是常数个变量