LintCode 解题记录 字符串处理1.0 17.7.29
来源:互联网 发布:数组词有哪些 编辑:程序博客网 时间:2024/05/18 13:27
Before: 按照难度做的
————————-Easy———————————
LintCode Add Binary
二进制求和。给定两个用字符串表示的二进制序列,求其和序列,同样以字符串表示。
1.思路
按照加法的规则来,从两个字符串的末尾(相当于最低位)开始加,维护进位位,把每次得到的结果顺序加在结果字符串上,最后利用reverse函数将结果字符串颠倒即为正确答案。
2.注意
要注意判断最高位是否有进位
3.代码
string addBinary(string& a, string& b) { // Write your code here string res; if (a.size() < b.size()) swap(a, b); //确保a是较长的那个字符串 reverse(a.begin(), a.end()); reverse(b.begin(), b.end()); int i = 0; int c = 0, sum = 0; for (; i < b.size(); i++) { sum = (a[i]-'0') + (b[i]-'0') + c; c = sum / 2; sum %= 2; res += sum + '0'; } while (i < a.size()) { sum = (a[i++]-'0') + c; c = sum / 2; sum %= 2; res += sum + '0'; } if (c) res += c + '0'; //判断最终的进位位 reverse(res.begin(), res.end()); return res; }
LintCode Compare String
比较字符串A和B,判断是不是A包含B
思路
典型的hash应用。用hash数组存储字符串A中字符出现的次数,先遍历一遍A更新hash,然后再遍历B,每遍历到一次字符其相应的hash值就减1。如果发现其hash值小于0,就说明A不包含B,返回false。
代码
bool compareStrings(string A, string B) { // write your code here unordered_map<char, int> hash; for (auto c: A) { hash[c]++; } for (auto c: B) { hash[c]--; if (hash[c] < 0) return false; } return true; }
LintCode Count and Say
对于一个字符串表示的数字序列”122123”,出现了一次1,即”11”,然后出现两次2,即”22”,接着一次1,一次2,一次3,即”111213”,得到下一个字符串是”1122111213”。再对新字符按照上面描述的规则”读”,即可得到又一新字符串,依次循环。
现在给定第一个字符串是”1”,问你第n个字符串是什么?
思路
按照上述读的规则进行。从第一个字符串开始计算,一直计算到第n个字符串即可。每次统计某一位出现字符串的次数,然后拼接形成新的字符串。
注意
C++字符串流stringstream在字符串转int,int转字符串的作用
代码
string int2string(int cnt) { stringstream ss; ss << cnt; string temp; ss >> temp; return temp; } string GenerateString(string res) { string temp; char pre = res[0]; int cnt = 1; for (int i = 1; i < res.size(); i++) { if (res[i] == pre) cnt++; else { temp += cnt + '0'; temp += pre; pre = res[i]; cnt = 1; } } temp += int2string(cnt); temp += pre; return temp; } string countAndSay(int n) { // Write your code here string res = "1"; while (--n) { res = GenerateString(res); } return res; }
LintCode Length of Last Word
给定一个字符串包含大小写字母和空格,返回最后一个单词的长度
思路
从末尾往前遍历,先去掉末尾空格,然后遍历到下一个空格或者字符串头结束,返回计数值。
代码
int res = 0; int p = s.size()-1; while (p >= 0 && s[p] == ' ') p--; for (; p >= 0; p--) { if (s[p] != ' ') { res++; } else { break; } } return res; }
LintCode Longest Word
给定一些单词,返回最长的单词的集合。要求一次遍历。
思路
用一个vector存储当前为止的最长单词集合。如果下一个单词的长度大于当前的长度,就把容器清空,把该单词加进去,如果相等则直接把该单词添加进去。最后返回该容器。
代码
vector<string> longestWords(vector<string> &dictionary) { // write your code here vector<string> res; for (int i = 0; i < dictionary.size(); i++) { if (res.empty() || dictionary[i].size() > res[0].size()) { res.clear(); res.push_back(dictionary[i]); } else if (dictionary[i].size() == res[0].size()) res.push_back(dictionary[i]); } return res; }
LintCode Palindrome Number
判断一个正数是不是回文数
思路
先把该数转换为字符串,然后从两边注意比较即可
代码
bool palindromeNumber(int num) { // Write your code here string res; while (num) { res += num % 10 + '0'; num /= 10; } bool flag = true; for (int i = 0; i < res.size()/2; i++) { if (res[i] != res[res.size()-1-i]) { flag = false; break; } } return flag; }
LintCode Reverse Words in a String
给定一个输入字符串,按照单词反转单词
思路
两次反转,先整体翻转,然后再单独把单词翻转,即能达到要求
注意
字符串有前导0与末尾0,但是翻转之后应该去掉。每个单词之间有可能有多个空格,翻转之后要求只有一个
代码
reverse(s.begin(), s.end()); string res,temp; int p = 0, first = 0; while (p < s.size() && s[p] == ' ') p++; //jump the leading zeroes. while (p < s.size()) { if (s[p] != ' ') { temp += s[p++]; first = true; } else if (first) { //遇到第一个空格 reverse(temp.begin(), temp.end()); res += temp + s[p++]; temp = ""; first = false; } else p++; } reverse(temp.begin(), temp.end()); res += temp; return res; }
后来想到了可以用stringstream从一个带空格的单词序列读取每一个单词,放在vec里,然后倒序遍历再拼接起来就好了。
string reverseWords(string s) { // write your code here string res; //if (s == "") return res; stringstream ss(s); vector<string> vec; string temp; while (ss >> temp) { vec.push_back(temp); } //vector的倒序迭代器rbegin(),rend() for (auto ite = vec.rbegin(); ite != vec.rend(); ite++) { if (ite != vec.rbegin()) res += " "; res += *ite; } return res; }
LintCode Rotate String
从左向右循环移动字符串n次,要求O(1)空间
思路
本来还在找移动了n次的规律,后来发现只需要每次移动一位,循环n次就可以了
代码
void rotateString(string &str,int offset){ //wirte your code here if (str.size() == 0) return; offset %= str.size(); for (int i = 0; i < offset; i++) { char temp = str[str.size()-1]; for (int j = str.size()-2; j >= 0; j--) { str[j+1] = str[j]; } str[0] = temp; } }
LintCode Space Replacement
将一个字符串中所有空格替换成”%20”,返回修改后的字符串的长度。
要求O(1)空间复杂度
思路
遍历,当遍历到一个空格后将空格后的有效字符均向右移动两位,然后添加”%20”,由于题目说明了空间是足够的,所以不用慌。
代码
int replaceBlank(char string[], int length) { // Write your code here int cnt = 0, i = 0; while (cnt < length) { if (string[i] != ' ') { cnt++; i++; } else { for (int j = length-cnt-1; j > 0; j--) { string[i+2+j] = string[i+j]; } string[i] = '%'; string[i+1] = '2'; string[i+2] = '0'; i += 3; cnt++; } } return i; }
九章做法是先求得新的长度,然后从原字符串的末尾开始遍历,同时修改新申请的长度空间。
代码
int replaceBlank(char string[], int length) { // Write your code here if(string == NULL && length <= 0) return 0; /*originalLength 为字符串string的实际长度*/ int originalLength = 0; int numberOfBlank = 0; int i = 0; while(string[i] != '\0') { ++ originalLength; if(string[i] == ' ') ++ numberOfBlank; ++ i; } /*newLength 为把空格替换成'%20'之后的长度*/ int newLength = originalLength + numberOfBlank * 2; int indexOfOriginal = originalLength; int indexOfNew = newLength; while(indexOfOriginal >= 0 && indexOfNew > indexOfOriginal) { if(string[indexOfOriginal] == ' ') { string[indexOfNew --] = '0'; string[indexOfNew --] = '2'; string[indexOfNew --] = '%'; } else { string[indexOfNew --] = string[indexOfOriginal]; } -- indexOfOriginal; } return newLength; }
LintCode String Permutation
给定两个字符串,判断其中一个是不是另一个的排列组合
思路
将两个字符串排序,若排序后相等就说明符合题意,否则就不符合。复杂度O(nlogn)
或者用hash统计字符出现次数,复杂度O(n)
代码
bool Permutation(string A, string B) { // write your code here sort(A.begin(), A.end()); sort(B.begin(), B.end()); return A == B; }
LintCode Two Strings Are Anagrams
Anagrams: They can be same after change the order of characters.
Challenge: O(n)时间复杂度,O(1)空间复杂度
思路
之前提到的是O(n)的时间复杂度,O(n)空间复杂度的方法,这里只不过将开辟的数组换成一个大小固定为26的数组,然后做同样的事情。
bool anagram(string s, string t) { // write your code here vector<int> hash(26, 0); for (auto c: s) { c = tolower(c); hash[c-'a']++; } for (auto c: t) { c = tolower(c); hash[c-'a']--; if (hash[c-'a'] < 0) return false; } return true; }
LintCode Valid Palindrome
给定一个字符串,判断其是不是一个有效的回文串,只考虑英文数字字母(alphanumeric characters)且忽略大小写。
Challenge: O(n) time without extra memory.
思路:
用两个指针从两端向中间遍历,只有在都是字母或数字的时候才判断其是否满足相等,相等则继续判断,不相等则不满足回文串要求。
代码
bool isPalindrome(string& s) { // Write your code here int l = 0, r = s.size()-1; while (l < r) { if (!isalpha(s[l]) && !isdigit(s[l])) l++; else if (!isalpha(s[r]) && !isdigit(s[r])) r--; else if (tolower(s[r]) == tolower(s[l])) { l++; r--; } else return false; } return true; }
LintCode strStr
对于一个给定的source string和一个target string,返回target string在source string中的起始下标,若source string不包含target,则返回-1。
思路:
这就是字符串查找的KMP算法,可以以O(n)的方式解决此问题。KMP算法我并不熟,所以这道题暂时是以O(n2)做的,有时间学习了KMP算法在来更新这道题。
代码
int strStr(const char *source, const char *target) { // write your code here if (source == NULL || target == NULL) return -1; if (target[0] == '\0') return 0; for (int i = 0; source[i] != '\0'; i++) { if (source[i] == target[0]) { bool find = true; for (int j = 1; target[j] != '\0'; j++) { if (source[i+j] == '\0' || source[i+j] != target[j]) { find = false; break; } } if (find) return i; } } return -1; }
LintCode Big Interger Multiplication
给定另个非负大整数(用字符串表示),求他们的乘积,结果也以字符串表示。
思路
按照正常乘法的思路,用一个vector存储所有的因子,最后把这些因子加起来就是想要的答案。
另外可以用一个result数组存储相乘得到的每一位,这种方法代码上更清晰一点。
string multiply(string& num1, string& num2) { // Write your code here if (num1 == "0" || num2 == "0") return "0"; int len1 = num1.size(), len2 = num2.size(); vector<char> result(len1+len2, '0'); int c; for (int i = len1-1; i >= 0; i--) { c = 0; for (int j = len2-1; j >= 0; j--) { int temp = (result[i+j+1]-'0')+(num1[i]-'0')*(num2[j]-'0')+c; c = temp/10; result[i+j+1] = temp%10 + '0'; } result[i] += c; } string res = ""; int cnt = 0; for (; cnt < len1+len2; cnt++) { if (result[cnt] != '0') break; } for (; cnt < len1+len2; cnt++) { res += result[cnt]; } return res; }
LintCode Decode Ways
给定一种编码方式,比如’A’ to ‘1’, ‘B’ to ‘2’,…,’Z’ to ‘26’,现在给你一数字序列,问你有多少种译码方式。
思路
从前往后遍历,假设当前位置i,既可以选择i+1位的单字符编码,也可以选择i+1、i+2位组成的双字符编码。当然存在组成的字符编码无法译码的情况,比如单字符为’0’就无法译码,或者双字符组成的数大于26或者’0x’这样的形式。这道题很像上楼梯问题:一共n个楼梯,一次可以选择走一步,也可以选择走两步,问一共有多少种上楼方式。
总结一下递推公式:
dp[i] = dp[i-1](if s[i] != ‘0’) + dp[i+2] (if 10*(s[i-1]-‘0’) + s[i]-‘0’ < 26 && s[i-1] != ‘0’)
初始条件 如果s != null && s[0] != ‘0’,那么s[0] = 1; s[1]的判断同理。
代码
int numDecodings(string& s) { // Write your code here if (s.size() == 0 || s[0] == '0') return 0; if (s.size() == 1) return 1; vector<int> res(s.size(), 0); res[0] = 1; int sum = 10*(s[0]-'0')+(s[1]-'0'); if (sum >= 1 && sum <= 26) res[1]++; if (s[1] != '0') res[1]++; for (int i = 2; i < s.size(); i++) { int sum = 10*(s[i-1]-'0')+(s[i]-'0'); if (s[i] != '0') res[i] += res[i-1]; if (sum >= 1 && sum <= 26 && s[i-1] != '0') { res[i] += res[i-2]; } } return res[s.size()-1]; }
- LintCode 解题记录 字符串处理1.0 17.7.29
- LintCode 解题记录17.8.4 字符串处理2
- LintCode 解题记录 17.8.7 字符串处理3
- LintCode 解题记录17.8.8 字符串处理4
- LintCode解题记录17.8.9 字符串处理5
- LintCode 解题记录17.8.19 字符串处理6
- LintCode 解题记录17.6.26 ~ 17.7.2
- LintCode 解题记录17.4.27
- LintCode解题记录17.4.28
- LintCode解题记录 17.5.3
- LintCode 解题记录 2017.6.3
- LintCode 解题记录 7.11 ~ 7.16
- LintCode 解题记录 Matrix专题
- LintCode解题记录17.9.9
- LintCode解题记录-Catalan Number
- LintCode 解题记录17.10.21
- LintCode 解题记录 17.11.11
- LintCode 解题记录 17.5.15 (tag: 哈希表)
- Android属性动画之ObjectAnimator和AnimatorSet
- idea-scala插件安装
- POJ 2288 状压DP
- 浮动
- asp连接access数据库
- LintCode 解题记录 字符串处理1.0 17.7.29
- 在NGUI使用图片文字(数字、美术字)(BMFont)
- 图文演示AIDL的使用全过程
- 主席树
- java开发系统内核:防范缓冲区溢出和强杀死循环程序
- bash: 一键安装pip & 一键设置pip永久镜像
- 1-5:HTML5新的语法规范
- ScrollView嵌套EditText的滑动冲突问题
- 《Java设计模式之模板模式》