Tag Archives: 字符串

LeetCode Reverse Words in a String III

LeetCode Reverse Words in a String III Given a string, you need to reverse the order of characters in each word within a sentence while still preserving whitespace and initial word order. Example 1:

Input: "Let's take LeetCode contest"
Output: "s'teL ekat edoCteeL tsetnoc"
Note: In the string, each word is separated by single space and there will not be any extra space in the string.
给定一个句子,要求把句子中的每个单词都逆序。 简单题,找空格,然后对每个单词reverse,直接调string::reverse或者自己写都可以。 代码如下: [cpp] class Solution { public: string reverseWords(string s) { int i = 0, j = 0, n = s.size(); while (j < n) { while (j < n&&s[j] != ‘ ‘)++j; reverse(s.begin() + i, s.begin() + j); i = ++j; } return s; } }; [/cpp] 本代码提交AC,用时23MS。]]>

hihoCoder 1501-风格不统一如何写程序

hihoCoder 1501-风格不统一如何写程序

#1501 : 风格不统一如何写程序

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

小Hi写程序时习惯用蛇形命名法(snake case)为变量起名字,即用下划线将单词连接起来,例如:file_name、 line_number。 小Ho写程序时习惯用驼峰命名法(camel case)为变量起名字,即第一个单词首字母小写,后面单词首字母大写,例如:fileName、lineNumber。 为了风格统一,他们决定邀请公正的第三方来编写一个转换程序,可以把一种命名法的变量名转换为另一种命名法的变量名。 你能帮助他们解决这一难题吗?

输入

第一行包含一个整数N,表示测试数据的组数。(1 <= N <= 10) 以下N行每行包含一个以某种命名法命名的变量名,长度不超过100。 输入保证组成变量名的单词只包含小写字母。

输出

对于每组数据,输出使用另一种命名法时对应的变量名。
样例输入
2
file_name
lineNumber
样例输出
fileName
line_number

本题要求把蛇形命名法和驼峰命名法相互转换。简单题,首先判断字符串中是否有下划线来区分原命名法,然后遍历字符串,找下划线或者大写字母,然后直接转换即可。 代码如下,注意在getline之前把换行符读了。 [cpp] #include<iostream> #include<cstdio> #include<vector> #include<algorithm> #include<unordered_map> #include<string> using namespace std; int main() { //freopen("input.txt", "r", stdin); int n; char c; scanf("%d", &n); scanf("%c", &c); // 读取换行符\n string line; while (n–) { getline(cin, line); if (line.find(‘_’) != string::npos) { string ans = ""; int len = line.size(), i = 0, j = 0; for (j = 0; j < len; ++j) { if (line[j] == ‘_’&&j + 1 < len) { line[j + 1] = toupper(line[j + 1]); ans += line.substr(i, j – i); i = j + 1; } } ans += line.substr(i, j – i); cout << ans << endl; } else { string ans = ""; int len = line.size(), i = 0, j = 0; for (j = 0; j < len; ++j) { if (isupper(line[j])) { line[j] = tolower(line[j]); if(ans=="") ans += line.substr(i, j – i); else ans += "_" + line.substr(i, j – i); i = j; } } ans += "_" + line.substr(i, j – i); cout << ans << endl; } } return 0; } [/cpp] 本代码提交AC,用时0MS。]]>

LeetCode Complex Number Multiplication

LeetCode Complex Number Multiplication Given two strings representing two complex numbers. You need to return a string representing their multiplication. Note i2 = -1 according to the definition. Example 1:

Input: "1+1i", "1+1i"
Output: "0+2i"
Explanation: (1 + i) * (1 + i) = 1 + i2 + 2 * i = 2i, and you need convert it to the form of 0+2i.
Example 2:
Input: "1+-1i", "1+-1i"
Output: "0+-2i"
Explanation: (1 - i) * (1 - i) = 1 + i2 - 2 * i = -2i, and you need convert it to the form of 0+-2i.
Note:
  1. The input strings will not have extra blank.
  2. The input strings will be given in the form of a+bi, where the integer a and b will both belong to the range of [-100, 100]. And the output should be also in this form.

给定两个复数字符串,要求计算它们的乘积。 简单题,展开之后是:(a1+a2i)(b1+b2i)=(a1*b1-a2*b2)+(a1*b2+a2*b1)i。所以只需要提取出a1,a2,b1,b2,然后代入公式计算到c1和c2,最后用to_string转换为字符串即可。 代码如下: [cpp] class Solution { void str2cpx(const string& s, int& c1, int&c2) { int i = 0, j = 0; while (s[j] != ‘+’)++j; c1 = atoi(s.substr(i, j – i).c_str()); i = ++j; while (s[j] != ‘i’)++j; c2 = atoi(s.substr(i, j – i).c_str()); } public: string complexNumberMultiply(string a, string b) { int a1 = 0, a2 = 0, b1 = 0, b2 = 0, c1 = 0, c2 = 0; str2cpx(a, a1, a2); str2cpx(b, b1, b2); c1 = a1*b1 – a2*b2; c2 = a1*b2 + a2*b1; return to_string(c1) + "+" + to_string(c2) + "i"; } }; [/cpp] 本代码提交AC,用时3MS。]]>

LeetCode Longest Absolute File Path

LeetCode Longest Absolute File Path Suppose we abstract our file system by a string in the following manner: The string "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext" represents:

dir
    subdir1
    subdir2
        file.ext
The directory dir contains an empty sub-directory subdir1 and a sub-directory subdir2 containing a file file.ext. The string "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext" represents:
dir
    subdir1
        file1.ext
        subsubdir1
    subdir2
        subsubdir2
            file2.ext
The directory dir contains two sub-directories subdir1 and subdir2. subdir1 contains a file file1.ext and an empty second-level sub-directory subsubdir1. subdir2contains a second-level sub-directory subsubdir2 containing a file file2.ext. We are interested in finding the longest (number of characters) absolute path to a file within our file system. For example, in the second example above, the longest absolute path is "dir/subdir2/subsubdir2/file2.ext", and its length is 32 (not including the double quotes). Given a string representing the file system in the above format, return the length of the longest absolute path to file in the abstracted file system. If there is no file in the system, return 0. Note:
  • The name of a file contains at least a . and an extension.
  • The name of a directory or sub-directory will not contain a ..
Time complexity required: O(n) where n is the size of the input string. Notice that a/aa/aaa/file1.txt is not the longest file path, if there is another path aaaaaaaaaaaaaaaaaaaaa/sth.png.
给定一个文件系统的树形结构,要求以O(n)的复杂度找出最长路径的文件的路径长度,这里的长度包括分隔符’/’。 一开始我没有清晰的思路,后来在暗时间会拿出来思考,今天早上刷牙的时候想到了大概的解法。 遍历一次字符串,用一个vector保存当前看到的文件系统的最深层次,用level保存当前进入到的文件系统的深度。vector初始为空,level初始为0。每次我们找’\n’,因为’\n’表示一层文件系统的结束。每层文件系统level都从0开始。 比如第一个例子(如下),看到dir时,vector还是空的,所以vector.push_back(dir)。回车之后是’\t’,此时的level为0,且vector[0]有东西,说明要进入vector[0]表示的文件夹的下一层,level++。又遇到subdir1,此时的level=1了,已经大于等于vector的长度,说明目前进入到的深度已经超过了vector的表示范围,所以vector.push_back(subdir1)。 遇到’\n’又重新开始了,level为0。遇到’\t’,vector有,进入vector[0],level++。遇到subdir2,此时level=1,但vector[1]有东西,此时需要把vector[1]覆盖为subdir2,因为目前看到的第1层已经是新的了。 遇到’\n’又重新开始,level为0。后面连遇到两个’\t’,且vector中都有对应,说明是在之前的路径里面,即dir/subdir2/。最后遇到file.ext文件,就能算到该文件的路径长度了。
dir
    subdir1
    subdir2
        file.ext
代码如下。需要注意一点,如果一个string为”dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext”,里面的’\n’和’\t’虽然看起来是两个字符\加n或者t,但是实际是一个char为’\n’或’\t’,内存中只用一个字符char来表示,所以直接判断input[i]==’\n’即可。 [cpp] class Solution { public: int lengthLongestPath(string input) { vector<string> paths; int maxLen = 0, n = input.size(), i = 0, j = 0; while (j < n) { bool isfile = false; int curLen = 0, level = 0; while (j < n&&input[j] != ‘\n’) { if (input[j] == ‘.’)isfile = true; else if (input[j] == ‘\t’) { if (paths.size() <= level)paths.push_back(input.substr(i, j – i)); curLen += paths[level++].size() + 1; // +1指分隔符’/’ i = j + 1; } ++j; } if (paths.size() <= level)paths.push_back(input.substr(i, j – i)); else paths[level] = input.substr(i, j – i); curLen += paths[level++].size(); // 末尾不需要分隔符’/’ i = ++j; if (isfile)maxLen = max(maxLen, curLen); } return maxLen; } }; [/cpp] 本代码提交AC,用时3MS。]]>

LeetCode Additive Number

LeetCode Additive Number Additive number is a string whose digits can form additive sequence. A valid additive sequence should contain at least three numbers. Except for the first two numbers, each subsequent number in the sequence must be the sum of the preceding two. For example: "112358" is an additive number because the digits can form an additive sequence: 1, 1, 2, 3, 5, 8.

1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5, 3 + 5 = 8
"199100199" is also an additive number, the additive sequence is: 1, 99, 100, 199.
1 + 99 = 100, 99 + 100 = 199
Note: Numbers in the additive sequence cannot have leading zeros, so sequence 1, 2, 03 or 1, 02, 3 is invalid. Given a string containing only digits '0'-'9', write a function to determine if it’s an additive number. Follow up: How would you handle overflow for very large input integers?
给定一个数字字符串,问这个字符串是否是可加的数。一个可加的数是指它可以分割成若干个字符串,每个字符串代表一个数,且这个数列满足斐波那契数列的规律,即后一个数等于前两个数之和。 明显的DFS题。从起点枚举所有可能的长度,转换成数字,然后判断是否等于前两个数字之和。 需要注意的是数组至少要有3个数,且每个数不能有前导0。另外字符串可能很长,导致转换成的数超过int范围,所以用long long和atoll函数。 代码如下: [cpp] typedef long long LL; class Solution { private: bool dfs(const string& num, int start, LL last1, LL last2, int cnt) { int n = num.size(); if (start == n&&cnt >= 3)return true; //if (start < n&&num[start] == ‘0’)return false; // "101" is true int m = num.size() – start; // left length bool ans = false; for (int i = 1; i <= m; ++i) { if (i != 1 && num[start] == ‘0’)continue; // leading zero LL sum = atoll(num.substr(start, i).c_str()); if (cnt >= 2) { if (last1 + last2 > sum)continue; else if (last1 + last2 < sum)return false; else ans = dfs(num, start + i, last2, sum, cnt + 1); } else if (cnt == 0)ans = dfs(num, start + i, sum, last2, cnt + 1); else if(cnt==1)ans= dfs(num, start + i, last1, sum, cnt + 1); if (ans)return true; } return false; } public: bool isAdditiveNumber(string num) { return dfs(num, 0, 0, 0, 0); } }; [/cpp] 本代码提交AC,用时0MS。]]>

LeetCode Longest Word in Dictionary through Deleting

LeetCode Longest Word in Dictionary through Deleting Given a string and a string dictionary, find the longest string in the dictionary that can be formed by deleting some characters of the given string. If there are more than one possible results, return the longest word with the smallest lexicographical order. If there is no possible result, return the empty string. Example 1:

Input:
s = "abpcplea", d = ["ale","apple","monkey","plea"]
Output:
"apple"
Example 2:
Input:
s = "abpcplea", d = ["a","b","c"]
Output:
"a"
Note:
  1. All the strings in the input will only contain lower-case letters.
  2. The size of the dictionary won’t exceed 1,000.
  3. The length of all the strings in the input won’t exceed 1,000.

给定一个字典d和字符串s,问d中哪些字符串可以通过s删除若干个字符得到,要求输出满足条件的最长字符串,如果有多个,则输出字典序最小的。 本题有两个考点,一是判断t是否能通过删除s中的若干个字符得到。使用两个指向s,t的指针i,j,j不断后移找t[i],找到之后i,j都后移。最终如果找到t中所有字符,则成功,否则失败。 另一个考点是,找出所有满足条件的字符串之后,怎样找到长度最长且字典序最小的字符串。这可以通过自定义string的比较函数,然后sort得到。具体看代码: [cpp] bool comp(const string& s1, const string& s2) { return s1.size() > s2.size() || (s1.size() == s2.size() && s1 < s2); } class Solution { private: bool convert(const string& src, const string& dest){ int m = src.size(), n = dest.size(); if (m < n)return false; int i = 0, j = 0; while (i < m) { while (i < m && src[i] != dest[j])++i; if (i >= m)break; ++i; ++j; if (j == n)break; } return j == n; } public: string findLongestWord(string s, vector<string>& d) { vector<string> cand; for (int i = 0; i < d.size(); ++i) { if (convert(s, d[i]))cand.push_back(d[i]); } sort(cand.begin(), cand.end(), comp); if (cand.size() > 0)return cand[0]; else return ""; } }; [/cpp] 本代码提交AC,用时135MS。]]>

hihoCoder 1485-hiho字符串

hihoCoder 1485-hiho字符串

#1485 : hiho字符串

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

如果一个字符串恰好包含2个’h’、1个’i’和1个’o’,我们就称这个字符串是hiho字符串。 例如”oihateher”、”hugeinputhugeoutput”都是hiho字符串。 现在给定一个只包含小写字母的字符串S,小Hi想知道S的所有子串中,最短的hiho字符串是哪个。

输入

字符串S 对于80%的数据,S的长度不超过1000 对于100%的数据,S的长度不超过100000

输出

找到S的所有子串中,最短的hiho字符串是哪个,输出该子串的长度。如果S的子串中没有hiho字符串,输出-1。
样例输入
happyhahaiohell
样例输出
5

如果字符串中包含2个h,1个i和1个o,则称该子串为hiho字符串。给定一个字符串s,问s中最短的hiho子串长度是多少。如果不存在hiho子串,则输出-1。 首先,肯定不能用两层循环暴力解法,这样的话需要$$O(n^3)$$,因为判断子串是否是hiho串还需要O(n),所以乘起来就是$$O(n^3)$$。 我当时的解法是,首先扫一遍字符串,记录下每个位置及其前面出现的h,i,o字符总数。然后我使用两层循环,把对应位置的h,i,o数目作差,如果等于2,1,1,则更新结果。但是$$O(n^2)$$的复杂度还是TLE了。 看了下第一名的解法,虽然复杂度也是$$O(n^2)$$,但是高明许多。设置两个指针i,j,区间[i,j]相当于一个滑动窗口,对于每个i,j往后走,直到h,i,o次数不低于2,1,1,如果正好是2,1,1,则把当前长度j-i和结果比较。i往后走时,对应的s[i]频率要减1。 代码如下,注意第23行,必须是大于号,不能是大于等于,因为如果只是hash[‘o’]==1就跳出的话,假设输入字符串是”oihateher”,则第0位时hash[‘o’]==1,此时跳出,导致起点i变成了1而找不到正确结果。具体用这个样例测试一下就知道。 [cpp] #include<iostream> #include<string> #include<vector> #include<algorithm> using namespace std; const int MAXN = 100005; int main() { string s; cin >> s; //s = "oihateher"; int n = s.size(); if (n < 4) { cout << -1; return 0; } vector<int> hash(256, 0); int ans = MAXN; for (int i = 0, j = 0; i < n; ++i) { while (j < n && (hash[‘h’] < 2 || hash[‘i’] < 1 || hash[‘o’] < 1)) { ++hash[s[j++]]; if (hash[‘h’] > 2 || hash[‘i’] > 1 || hash[‘o’] > 1)break; } if (hash[‘h’] == 2 && hash[‘i’] == 1 && hash[‘o’] == 1) ans = min(ans, j – i); –hash[s[i]]; } if (ans == MAXN)cout << -1; else cout << ans; return 0; } [/cpp] 本代码提交AC,用时13MS。]]>

LeetCode Is Subsequence

LeetCode Is Subsequence Given a string s and a string t, check if s is subsequence of t. You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100). A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ace" is a subsequence of "abcde" while "aec" is not). Example 1: s = "abc", t = "ahbgdc" Return true. Example 2: s = "axc", t = "ahbgdc" Return false. Follow up: If there are lots of incoming S, say S1, S2, … , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?


给定两个字符串s和t,判断s是否是t的子序列。子序列的概念和子串不一样,如果s是t的子串,则s必须是t中连续的一段;而如果是子序列的话,则s只需要是t中若干个字符,但这些字符顺序必须和t中的一样。 比如t=”abcdefghijk”,则”cdef”既可以是t的子串,也可以是t的子序列;而”bfjk”只能是t的子序列。 本题很简单,维护两个指针i,j,分别指向s和t,从t中不断找字符s[i],没找到只递增j,找到的话同时递增i和j。如果最后i到达s的末尾了,说明s是t的子序列,否则不是。 代码如下: [cpp] class Solution { public: bool isSubsequence(string s, string t) { int m = s.size(), n = t.size(); if (m > n)return false; int i = 0, j = 0; while (i < m&&j < n) { while (j < n&&s[i] != t[j])++j; if (j >= n)return false; ++i; ++j; } return i == m; } }; [/cpp] 本代码提交AC,用时73MS。]]>

LeetCode Minimum Time Difference

LeetCode Minimum Time Difference Given a list of 24-hour clock time points in “Hour:Minutes” format, find the minimum minutes difference between any two time points in the list. Example 1:

Input: ["23:59","00:00"]
Output: 1
Note:
  1. The number of time points in the given list is at least 2 and won’t exceed 20000.
  2. The input time is legal and ranges from 00:00 to 23:59.

给定一个时间字符串数组,问数组中任意两个时间之差最小是多少分钟。 本题的基本思路是把数组中所有的时间表示转换为分钟,然后排序求相邻两个分钟之间的最小差。 本题的一个小难点是时间是循环的,比如01:30和06:30差5小时,但01:30和23:30差几小时呢?如果顺着看差22小时,好像比前一个差要大,但是逆着看,实际上只差2小时。所以分立0点两边的两个时间差其实有两个。处理办法是把0~12点之间的时间转换为两个分钟数,一个是0~12以内的,另一个是12~24以内的。 代码如下: [cpp] class Solution { private: void convertToMinutes(const string& s, vector<int>& minutes) { int pos = s.find(‘:’); int hour = atoi(s.substr(0, pos).c_str()), minute = atoi(s.substr(pos + 1).c_str()); int m = hour * 60 + minute; minutes.push_back(m); if (hour < 12)minutes.push_back(m + 24 * 60); } public: int findMinDifference(vector<string>& timePoints) { vector<int> minutes; for (int i = 0; i < timePoints.size(); ++i) { convertToMinutes(timePoints[i], minutes); } sort(minutes.begin(), minutes.end()); int ans = INT_MAX; for (int i = 1; i < minutes.size(); ++i) { ans = min(ans, minutes[i] – minutes[i – 1]); } return ans; } }; [/cpp] 本代码提交AC,用时19MS。]]>

LeetCode Encode and Decode TinyURL

LeetCode Encode and Decode TinyURL

Note: This is a companion problem to the System Design problem: Design TinyURL.
TinyURL is a URL shortening service where you enter a URL such as https://leetcode.com/problems/design-tinyurl and it returns a short URL such as http://tinyurl.com/4e9iAk. Design the encode and decode methods for the TinyURL service. There is no restriction on how your encode/decode algorithm should work. You just need to ensure that a URL can be encoded to a tiny URL and the tiny URL can be decoded to the original URL.
实现短网址的功能,即把一个长的网址加密成短网址,并且能够把短网址还原为原来的长网址。 显然要用Hash,有多种方法,参考:https://leetcode.com/articles/encode-and-decode-tinyurl/ 直接用一个计数器当key,相当于自己维护了一个长的url池,给每个url编了一个号。加密的时候把号码给他,解密的时候根据编号找到原始的url。代码如下: [cpp] class Solution { private: unsigned long long m_ullCnt; unordered_map<unsigned long long, string> m_umHash; public: Solution() :m_ullCnt(0) {}; // Encodes a URL to a shortened URL. string encode(string longUrl) { m_umHash[m_ullCnt] = longUrl; return "http://tinyurl.com/" + to_string(m_ullCnt++); } // Decodes a shortened URL to its original URL. string decode(string shortUrl) { int id = atoi(shortUrl.substr(19).c_str()); return m_umHash[id]; } }; [/cpp] 本代码提交AC,用时9MS。 既然可以用计数器,也可以生成不重复的随机数作为key,不断random,和上面的解法类似。 还有一种生成key的方法,就是用STL自带的hash函数,把string hash成一个size_t作为key。注意要从短url中还原回hash值时,不能用atoi和atol,因为size_t可能是unsigned int,也可能和平台有关,所以必须用sscanf “%zu”的形式转换成size_t。 代码如下: [cpp] class Solution { private: unordered_map<size_t, string> m_umHash; public: // Encodes a URL to a shortened URL. string encode(string longUrl) { hash<string> h; m_umHash[h(longUrl)] = longUrl; return "http://tinyurl.com/" + to_string(h(longUrl)); } // Decodes a shortened URL to its original URL. string decode(string shortUrl) { size_t id = 0; sscanf(shortUrl.substr(19).c_str(), "%zu", &id); return m_umHash[id]; } }; [/cpp] 本代码提交AC,用时6MS。]]>