【3】Longest Substring Without Repeating Characters (2019年1月22日,複習)html
【5】Longest Palindromic Substring (2019年1月22日,複習)node
【6】ZigZag Conversion (2019年1月22日,複習)git
【8】String to Integer (atoi) (2019年1月22日,複習)面試
【10】Regular Expression Matching (2019年1月22日,複習)算法
【12】Integer to Roman (2019年1月22日,複習)express
【13】Roman to Integer (2019年1月22日,複習)api
羅馬數字轉換成整數。數組
題解:用一個map來存儲映射關係。緩存
1 class Solution { 2 public: 3 int romanToInt(string s) { 4 const int n = s.size(); 5 initMap(); 6 int idx = 0; 7 int ret = 0; 8 while (idx < n) { 9 if (idx + 1 == n) { 10 string temp = string(1, s[idx]); 11 ret += mp[temp]; 12 idx++; 13 continue; 14 } 15 string str = s.substr(idx, 2); 16 if (mp.find(str) != mp.end()) { 17 ret += mp[str]; 18 idx += 2; 19 } else { 20 string temp = string(1, s[idx]); 21 ret += mp[temp]; 22 idx++; 23 } 24 } 25 return ret; 26 } 27 unordered_map<string, int> mp; 28 void initMap() { 29 mp["IV"] = 4, mp["IX"] = 9; 30 mp["XL"] = 40, mp["XC"] = 90; 31 mp["CD"] = 400, mp["CM"] = 900; 32 mp["I"] = 1, mp["V"] = 5, mp["X"] = 10, 33 mp["L"] = 50, mp["C"] = 100, mp["D"] = 500, 34 mp["M"] = 1000; 35 } 36 };
【14】Longest Common Prefix (2019年1月22日,複習)ide
給了一組單詞,由小寫字母構成,找他們的公共前綴,返回這個字符串。
題解:能夠暴力解,能夠trie樹。
1 class Solution { 2 public: 3 string longestCommonPrefix(vector<string>& strs) { 4 if(strs.empty()) return ""; 5 for(int i=0; i<strs[0].size(); ++i){ 6 for(int j=1; j<strs.size(); ++j){ 7 if(strs[0][i] != strs[j][i]){ 8 return strs[0].substr(0,i); 9 } 10 } 11 } 12 return strs[0]; 13 } 14 };
1 class Solution { 2 public: 3 struct TrieNode { 4 char c; 5 vector<TrieNode*> children; 6 bool isEndingChar = false; 7 int cntChildrenNotNull = 0; 8 TrieNode(char t): c(t) { 9 children = vector<TrieNode*>(26, nullptr); 10 } 11 }; 12 class Trie { 13 public: 14 void insert(string s) { 15 TrieNode * node = root; 16 for (int i = 0; i < s.size(); ++i) { 17 char c = s[i]; 18 if (node->children[c-'a'] == nullptr) { 19 node->children[c-'a'] = new TrieNode(c); 20 node->cntChildrenNotNull++; 21 } 22 node = node->children[c-'a']; 23 } 24 node->isEndingChar = true; 25 return; 26 } 27 string getCommonPrefix() { 28 TrieNode* node = root; 29 string ret = ""; 30 while (node->cntChildrenNotNull == 1 && node->isEndingChar == false) { 31 for (int i = 0; i < 26; ++i) { 32 if (node->children[i]) { 33 node = node->children[i]; 34 break; 35 } 36 } 37 ret += string(1, node->c); 38 } 39 return ret; 40 } 41 TrieNode* root = new TrieNode('/'); 42 }; 43 string longestCommonPrefix(vector<string>& strs) { 44 const int n = strs.size(); 45 Trie trie; 46 for (auto s : strs) { 47 if (s.empty()) { 48 return s; 49 } 50 trie.insert(s); 51 } 52 return trie.getCommonPrefix(); 53 } 54 };
【17】Letter Combinations of a Phone Number (2019年1月22日,複習)
給了一個座機電話, 給了一個數字的字符串 digits,返回全部的數字對應的字母排列。
題解:map + dfs
1 class Solution { 2 public: 3 vector<string> letterCombinations(string digits) { 4 n = digits.size(); 5 if (n == 0) { return vector<string>{}; } 6 initMap(); 7 string s = ""; 8 dfs(digits, 0, s); 9 return ret; 10 } 11 int n; 12 unordered_map<int, vector<string>> mp; 13 vector<string> ret; 14 void dfs(string digits, int cur, string& s) { 15 if (cur == n) { 16 ret.push_back(s); 17 return; 18 } 19 int num = digits[cur] - '0'; 20 for (auto ele : mp[num]) { 21 string ori = s; 22 s += ele; 23 dfs(digits, cur + 1, s); 24 s = ori; 25 } 26 return; 27 } 28 void initMap() { 29 mp[2] = {"a", "b", "c"}; 30 mp[3] = {"d", "e", "f"}; 31 mp[4] = {"g", "h", "i"}; 32 mp[5] = {"j", "k", "l"}; 33 mp[6] = {"m", "n", "o"}; 34 mp[7] = {"p", "q", "r", "s"}; 35 mp[8] = {"t", "u", "v"}; 36 mp[9] = {"w", "x", "y", "z"}; 37 } 38 };
【20】Valid Parentheses (2019年1月22日,複習)
Given a string containing just the characters '('
, ')'
, '{'
, '}'
, '['
and ']'
, determine if the input string is valid. 判斷一個字符串中的括號是否是合法的。
題解:用棧作。
代碼不貼了。
【22】Generate Parentheses (2019年1月22日,複習)
【28】Implement strStr() (算法羣,2018年11月4日,練習kmp)
實如今字符串 s 中找到 模式串 p, (kmp)
題解:暴力O(N*M) 能夠解, kmp O(N+M) 也能夠解 ,kmp務必再深刻理解一下 next 數組的求法。否則面試不給筆記看就涼涼了。(還有一個注意點是 p 爲空串的時候要特判)
1 class Solution { 2 public: 3 int strStr(string haystack, string needle) { 4 return kmp(haystack, needle); 5 } 6 int kmp(string& s, string& p) { 7 const int n = s.size(), m = p.size(); 8 if (m == 0) {return 0;} //p empty 9 vector<int> next = getNext(p); 10 int i = 0, j = 0; 11 while (i < n && j < m) { 12 if (j == -1 || s[i] == p[j]) { 13 ++i, ++j; 14 } else { 15 j = next[j]; 16 } 17 } 18 if (j == m) { 19 return i - j; 20 } 21 return -1; 22 } 23 vector<int> getNext(string& p) { 24 const int n = p.size(); 25 vector<int> next(n, 0); 26 next[0] = -1; 27 int j = 0, k = -1; 28 while (j < n - 1) { 29 if (k == -1 || p[j] == p[k]) { 30 ++k, ++j; 31 next[j] = p[j] == p[k] ? next[k] : k; 32 } else { 33 k = next[k]; 34 } 35 } 36 return next; 37 } 38 };
1 //暴力解法 O(N*M) 2 class Solution { 3 public: 4 int strStr(string haystack, string needle) { 5 const int n = haystack.size(), m = needle.size(); 6 if (m == 0) {return 0;} 7 for (int i = 0; i + m <= n; ) { // 判斷條件要不要取等號,而後下面作了++i, ++j, for循環裏面就別作了,尷尬,這都能錯 8 int j; int oldi = i; 9 for (j = 0; j < m;) { 10 if (haystack[i] == needle[j]) { 11 ++i, ++j; 12 } else { 13 break; 14 } 15 } 16 if (j == m) { 17 return i - j; 18 } else { 19 i = oldi + 1; 20 } 21 } 22 return -1; 23 } 24 };
【30】Substring with Concatenation of All Words
【32】Longest Valid Parentheses
【38】Count and Say
【43】Multiply Strings (2018年11月27日,高精度乘法) (2019年3月5日更新)
給了兩個string類型的數字,num1 和 num2, 用string的形式返回 num1 * num2。(num1, num2 的長度都小於等於110)
題解:咱們能夠不作翻轉的操做,從 num1 和 num2 的末尾開始計算,num1[i], num2[j] 的乘積要放在 nums[i+j+1] 的位置,進位放在 nums[i+j] 的位置。返回結果的字符串的長度確定是 nums1.size() + nums2.size() 的長度。
1 class Solution { 2 public: 3 string multiply(string num1, string num2) { 4 const int size1 = num1.size(), size2 = num2.size(); 5 vector<int> nums(size1 + size2, 0); 6 for (int i = size1 - 1; i >= 0; --i) { 7 for (int j = size2 - 1; j >= 0; --j) { 8 int temp = (num1[i] - '0') * (num2[j] - '0') + (nums[i+j+1]); 9 nums[i+j+1] = temp % 10; 10 nums[i+j] += temp / 10 ; 11 } 12 } 13 string res = ""; 14 for (auto num : nums) { 15 if (num == 0 && res.empty()) { 16 continue; 17 } 18 res += num + '0'; 19 } 20 if (res.empty()) { res = "0"; } 21 return res; 22 } 23 };
【44】Wildcard Matching
【49】Group Anagrams (2019年1月23日,谷歌tag複習)
給了一個單詞列表,給全部的異構詞分組。
Input: ["eat", "tea", "tan", "ate", "nat", "bat"],
Output:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
題解:個人解法,hashmap + sort。不是最優秀的解法。還有什麼用 26個素數代替法,這個更快吧。
代碼不貼了。
【58】Length of Last Word
【65】Valid Number
【67】Add Binary
【68】Text Justification
【71】Simplify Path
【72】Edit Distance
【76】Minimum Window Substring
【87】Scramble String
【91】Decode Ways
【93】Restore IP Addresses
【97】Interleaving String
【115】Distinct Subsequences
【125】Valid Palindrome
【126】Word Ladder II
【151】Reverse Words in a String (2018年11月8日, 原地翻轉字符串)
Input: "the sky is blue
",
Output: "blue is sky the
".
題解:用stringstream能作。
1 class Solution { 2 public: 3 void reverseWords(string &s) { 4 stringstream iss(s); 5 string temp; 6 iss >> s; 7 while (iss >> temp) { 8 s = temp + " " + s; 9 } 10 if (isspace(s[0])) {s = "";} 11 return; 12 } 13 };
【157】Read N Characters Given Read4
【158】Read N Characters Given Read4 II - Call multiple times
【159】Longest Substring with At Most Two Distinct Characters (2019年1月29日,谷歌tag複習)
給定一個字符串 s,返回它最長的子串的長度,子串要求只能有兩個distinct characters。
題解:sliding window。(time complexity is O(N))
1 class Solution { 2 public: 3 int lengthOfLongestSubstringTwoDistinct(string s) { 4 const int n = s.size(); 5 int ans = 0; 6 int begin = 0, end = 0, cnt = 0; 7 unordered_map<char, int> mp; 8 while (end < n) { 9 mp[s[end]]++; 10 if (mp[s[end]] == 1) { 11 ++cnt; 12 } 13 if (cnt <= 2) { 14 ans = max(ans, end - begin + 1); 15 } 16 while (cnt > 2) { 17 mp[s[begin]]--; 18 if (mp[s[begin]] == 0) { 19 --cnt; 20 } 21 ++begin; 22 } 23 end++; 24 } 25 return ans; 26 } 27 };
【161】One Edit Distance (2018年11月24日,刷題數)
給了兩個字符串 s 和 t,問 s 能不能經過 增長一個字符, 刪除一個字符,替換一個字符 這三種操做裏面的任意一個變成 t。能的話返回 true, 不能的話返回 false。
題解:感受是基礎版的編輯距離。直接經過模擬來作。beats 36%。時間複雜度是 O(N).
1 class Solution { 2 public: 3 bool isOneEditDistance(string s, string t) { 4 if (s == t) {return false;} 5 const int ssize = s.size(), tsize = t.size(); 6 int cnt = 0; 7 if (ssize == tsize) { //check replace; 8 int idx = findfirstidx(s, t); 9 if (idx == ssize || s.substr(idx+1) == t.substr(idx+1)) { 10 return true; 11 } 12 } else if (ssize == tsize - 1) { //check insert 13 int idx = findfirstidx(s, t); 14 if (idx == tsize || s.substr(idx) == t.substr(idx+1)) { 15 return true; 16 } 17 18 } else if (ssize == tsize + 1){ //check delete 19 int idx = findfirstidx(s, t); 20 if (idx == ssize || s.substr(idx+1) == t.substr(idx)) { 21 return true; 22 } 23 } 24 return false; 25 } 26 inline int findfirstidx (string s, string t) { 27 const int ssize = s.size(), tsize = t.size(); 28 int tot = min(ssize, tsize); 29 for (int i = 0; i < tot; ++i) { 30 if (s[i] != t[i]) { 31 return i; 32 } 33 } 34 return max(ssize, tsize); 35 } 36 };
【165】Compare Version Numbers (2019年5月5日, 字符處理類型的題目)
比較兩個字符串版本號的大小。input 是 version1 和 version2。
比較規則是: ‘.’ 做爲分隔符,若是同一層級的 version1 的number 小於 version2 的 number,返回 -1, 反之,若是大於,返回 1. 若是相等的話,繼續比較下一個層級。
題解:直接模擬法作。時間複雜度是O(N).
1 class Solution { 2 public: 3 int compareVersion(string version1, string version2) { 4 int size1 = version1.size(), size2 = version2.size(); 5 int p1 = 0, p2 = 0; 6 int num1 = 0, num2 = 0; 7 while (p1 < size1 || p2 < size2) { 8 if (p1 < size1 && version1[p1] == '.') {++p1;} 9 if (p2 < size2 && version2[p2] == '.') {++p2;} 10 while (p1 < size1 && isdigit(version1[p1])) { 11 num1 = num1 * 10 + (version1[p1] - '0'); 12 ++p1; 13 } 14 while (p2 < size2 && isdigit(version2[p2])) { 15 num2 = num2 * 10 + (version2[p2] - '0'); 16 ++p2; 17 } 18 if (num1 < num2) {return -1;} 19 if (num1 > num2) {return 1;} 20 num1 = 0, num2 = 0; 21 } 22 return 0; 23 } 24 };
【186】Reverse Words in a String II (2018年11月8日, 原地翻轉字符串)
Given an input string , reverse the string word by word.
Example: Input: ["t","h","e"," ","s","k","y"," ","i","s"," ","b","l","u","e"] Output: ["b","l","u","e"," ","i","s"," ","s","k","y"," ","t","h","e"] Note: A word is defined as a sequence of non-space characters. The input string does not contain leading or trailing spaces. The words are always separated by a single space.
題解:無。
1 class Solution { 2 public: 3 void reverseWords(vector<char>& str) { 4 reverse(str.begin(), str.end()); 5 const int n = str.size(); 6 int p1 = 0, p2 = 0; 7 while (p2 < n) { 8 while (p1 < n && str[p1] == ' ') {p1++;} 9 p2 = p1; 10 while (p2 < n && str[p2] != ' ') {p2++;} 11 reverse(str.begin() + p1, str.begin() + p2); 12 p1 = p2; 13 } 14 return; 15 } 16 };
【214】Shortest Palindrome (2018年11月2日,週五,算法羣)
給了一個字符串 S,爲了使得 S 變成迴文串能夠在前面增長字符,在增長最少的字符的前提下返回新的迴文 S。
題解:個人作法跟昨天的題同樣(366)就是找從第一個字符開始最長的迴文串,而後把後面的那小段翻轉一下,拼到前面。時間複雜度是O(N^2)
1 //相似的題目能夠見 336 Palindrome Pairs 2 class Solution { 3 public: 4 string shortestPalindrome(string s) { 5 const int n = s.size(); 6 string ans = ""; 7 for (int j = n; j >= 0; --j) { 8 if (isPalindrome(s, 0, j-1)) { 9 string str = s.substr(j); 10 reverse(str.begin(), str.end()); 11 ans = str + s; 12 break; 13 } 14 } 15 return ans; 16 } 17 bool isPalindrome(const string& s, int start, int end) { //[start, end] 18 while (start < end) { 19 if (s[start] != s[end]) {return false;} 20 start++, end--; 21 } 22 return true; 23 } 24 };
應該還有更好的解法:(學習學習學習)。
【227】Basic Calculator II (2019年3月18日)
給了一個字符串,包含數字,+,-,*,/,和空格,求字符串表達式的值。
Example 1:
Input: "3+2*2" Output: 7
Example 2:
Input: " 3/2 " Output: 1
Example 3:
Input: " 3+5 / 2 " Output: 5
題解:本題大爺他們說用狀態機的方法來作。狀態機的方法就是遍歷字符串,若是碰到 digit 應該怎麼作,若是碰到 + - * / 應該怎麼作,若是碰到 空格 應該怎麼作。
用一個 vector<int> 作爲 cache 緩存前面的只用 +,- 的值。
1 class Solution { 2 public: 3 int calculate(string s) { 4 const int n = s.size(); 5 int num = 0; 6 char sign = '+'; 7 vector<int> cache; 8 for (int i = 0; i < n; ++i) { 9 if (isdigit(s[i])) { 10 num = num * 10 + (s[i] - '0'); 11 } 12 if (i == n-1 || !isdigit(s[i]) && s[i] != ' '){ 13 if (sign == '+') {cache.push_back(num);} 14 if (sign == '-') {cache.push_back(-num);} 15 if (sign == '*' || sign == '/') { 16 int last = cache.back(); 17 cache.pop_back(); 18 if (sign == '*') {cache.push_back(last * num);} 19 else if (sign == '/') {cache.push_back(last / num);} 20 } 21 num = 0; 22 if (!isdigit(s[i])) { sign = s[i]; } 23 } 24 } 25 int res = 0; 26 for (auto& e : cache) { 27 res += e; 28 } 29 return res; 30 } 31 };
【249】Group Shifted Strings
【271】Encode and Decode Strings
【273】Integer to English Words
【293】Flip Game
【336】Palindrome Pairs (2018年11月1日,週四,算法羣)
給了一組字符串words,找出全部的pair (i,j),使得 words[i] + words[j] 這個新的字符串是迴文串。
題解:這題WA出了天際。由於map彷佛一旦訪問了某個不存在的key,這個key就變的存在了。。一開始我想暴力,暴力超時,暴力時間的時間複雜度是O(N^2*K)。後來認真思考了一下一個字符串是怎麼變成迴文的。若是一個字符串word,他的長度是n,若是它的前半段 word[0..j] 是個迴文串,那麼咱們須要匹配它後面那段 word[j+1..n-1], 咱們把後半段reverse一下, 查找字符串集合(map)裏面有沒有對應的這段。同理,若是它的後半段 word[j+1..n-1] 是個迴文串,那麼咱們把前半段 reverse一下,在 map 裏面查找有沒有前半段就能夠了。特別注意這個前半段和後半段均可以包含空串,因此 j 的範圍是[0, n]。
1 class Solution { 2 public: 3 vector<vector<int>> palindromePairs(vector<string>& words) { 4 const int n = words.size(); 5 unordered_map<string, int> mp; 6 for (int i = 0; i < n; ++i) { 7 mp[words[i]] = i; 8 } 9 vector<vector<int>> ans; 10 set<vector<int>> st; 11 for (int i = 0; i < n; ++i) { 12 string word = words[i]; 13 int size = word.size(); 14 for (int j = 0; j <= size; ++j) { 15 if (isPalindrome(word, 0, j-1)) { 16 string str = word.substr(j); 17 reverse(str.begin(), str.end()); 18 //vector<int> candidate = vector<int>{mp[str], i}; 這個不能放在外面,否則mp[str]可能不存在 19 if (mp.find(str) != mp.end() && mp[str] != i) { 20 vector<int> candidate = vector<int>{mp[str], i}; 21 if (st.find(candidate) == st.end()) { 22 ans.push_back(candidate); 23 st.insert(candidate); 24 } 25 } 26 } 27 if (isPalindrome(word, j, size-1)) { 28 string str = word.substr(0, j); 29 reverse(str.begin(), str.end()); 30 //vector<int> candidate = vector<int>{i, mp[str]}; 31 if (mp.find(str) != mp.end() && mp[str] != i) { 32 vector<int> candidate = vector<int>{i, mp[str]}; 33 if (st.find(candidate) == st.end()) { 34 ans.push_back(candidate); 35 st.insert(candidate); 36 } 37 } 38 } 39 } 40 } 41 return ans; 42 } 43 bool isPalindrome(const string& word, int start, int end) { // [start, end] 44 while (start < end) { 45 if (word[start++] != word[end--]) { return false; } 46 } 47 return true; 48 } 49 };
據說這題還能用 trie 解,有空要看答案啊。
【340】Longest Substring with At Most K Distinct Characters (2019年1月29日,谷歌tag複習)
相似題:159. Longest Substring with At Most 2 Distinct Characters, sliding window 如出一轍的。時間複雜度是O(N)
1 class Solution { 2 public: 3 int lengthOfLongestSubstringKDistinct(string s, int k) { 4 const int n = s.size(); 5 if (n <= k) {return n;} 6 int begin = 0, end = 0, cnt = 0; 7 unordered_map<char, int> mp; 8 int ans = 0; 9 while (end < n) { 10 mp[s[end]]++; 11 if (mp[s[end]] == 1) { 12 ++cnt; 13 } 14 if (cnt <= k) { 15 ans = max(ans, end - begin + 1); 16 } 17 while (cnt > k) { 18 mp[s[begin]]--; 19 if (mp[s[begin]] == 0) { 20 --cnt; 21 } 22 ++begin; 23 } 24 ++end; 25 } 26 return ans; 27 } 28 };
【344】Reverse String (2018年12月3日,第一次review,ko)
逆序一個字符串。
題解:直接reverse,或者 2 pointers
1 class Solution { 2 public: 3 string reverseString(string s) { 4 int start = 0, end = s.size() - 1; 5 while (start < end) { 6 swap(s[start++], s[end--]); 7 } 8 return s; 9 } 10 };
【345】Reverse Vowels of a String (2018年12月4日,第一次review,ko)
逆序一個字符串的元音字母。
題解:2 pointers
1 class Solution { 2 public: 3 string reverseVowels(string s) { 4 set<char> setVowels = {'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'}; 5 int left = 0, right = s.size()-1; 6 while (left < right) { 7 while (setVowels.find(s[left]) == setVowels.end()) {++left;} 8 while (setVowels.find(s[right]) == setVowels.end()) {--right;} 9 if (left < right) { //這裏須要再次判斷 10 swap(s[left++], s[right--]); 11 } 12 } 13 return s; 14 } 15 };
【383】Ransom Note
【385】Mini Parser
【387】First Unique Character in a String
【408】Valid Word Abbreviation
【434】Number of Segments in a String
【443】String Compression (2019年2月12日)
壓縮一個字符數組,"aaa" -> "a3", "bb" -> "b2", "c" -> "c"。要求 in-place。space複雜度爲O(1).
題解:用指針作。用一個index指針記錄當前新字符串的末尾的位置。
1 class Solution { 2 public: 3 int compress(vector<char>& chars) { 4 const int n = chars.size(); 5 int idx = 0; 6 int begin = 0, end = 0, cnt = 0; 7 while (end < n) { 8 if (chars[begin] == chars[end]) { 9 ++cnt; ++end; 10 } 11 if (end == n || (end < n && chars[begin] != chars[end])) { 12 chars[idx++] = chars[begin]; 13 if (cnt > 1) { 14 string s = to_string(cnt); 15 for (auto c : s) { chars[idx++] = c; } 16 } 17 begin = end; 18 cnt = 0; 19 } 20 } 21 return idx; 22 } 23 };
【459】Repeated Substring Pattern
【468】Validate IP Address (2018年12月7日)
判斷一個字符串是否是有效的 IP 地址,區分 IPv4 和 IPv6, 都不是的話返回 Neither。IPv4 的判斷很簡單,就是用 ‘.’ 隔開的四段數字,而後每段數字都在0~255中間,數字沒有前導 0。 IPv6 的判斷比較麻煩,是八段用 ‘:’ 隔開是數字,每段數字都是四位十六進制數。四位數字若是有前置 0 的話,能夠省略,以及大小寫均可以忽略不一樣。
題解:比較複雜的模擬題。我用 getline 分割字符串,注意若是 它已經有 7 個 ‘:’ 分割八段十六進制數以後,若是在尾部還有一個 ‘:’ ,那麼這個要特判。
1 #define NEITHER "Neither" 2 #define IPV4 "IPv4" 3 #define IPV6 "IPv6" 4 5 class Solution { 6 public: 7 string validIPAddress(string IP) { 8 if (IP.find(':') != string::npos) { 9 return checkIPV6(IP); 10 } 11 return checkIPV4(IP); 12 } 13 string checkIPV4(string IP) { 14 int cnt = 0; 15 string word; 16 stringstream ss; 17 ss << IP; 18 if (IP.front() == '.' || IP.back() == '.') {return NEITHER;} 19 while (getline(ss, word, '.')) { 20 cnt++; 21 if (word.size() > 3 || word.empty()) {return NEITHER;} 22 for (int i = 0; i < word.size(); ++i) { 23 if (i == 0 && word[i] == '0' && word.size() > 1 || !isdigit(word[i])) { 24 return NEITHER; 25 } 26 } 27 int num = stoi(word); 28 if (num < 0 || num > 255) {return NEITHER;} 29 } 30 if (cnt != 4) { 31 return NEITHER; 32 } 33 return IPV4; 34 } 35 string checkIPV6(string IP) { 36 int cnt = 0; 37 string word; 38 stringstream ss; 39 ss << IP; 40 if (IP.front() == ':' || IP.back() == ':') {return NEITHER;} 41 while (getline(ss, word, ':')) { 42 cnt++; 43 printf("word = %s \n", word.c_str()); 44 if (word.size() > 4 || word.empty()) {return NEITHER;} 45 for (int i = 0; i < word.size(); ++i) { 46 char c = word[i]; 47 if (!isalnum(c) || c > 'f' && c <= 'z' || c > 'F' && c <= 'Z') { 48 return NEITHER; 49 } 50 } 51 } 52 if (cnt != 8) { 53 return NEITHER; 54 } 55 return IPV6; 56 } 57 };
【520】Detect Capital
【521】Longest Uncommon Subsequence I
【522】Longest Uncommon Subsequence II
【527】Word Abbreviation
【536】Construct Binary Tree from String
【537】Complex Number Multiplication (2018年11月27日)
給了兩個字符串,表明兩個 complex, 返回這兩個complex 的乘積(用字符串表示)。
題解:見math分類:http://www.javashuo.com/article/p-wvoulkgj-kc.html
【539】Minimum Time Difference (2019年2月11日)
給了一個字符串list,表明時間,返回最小的時間差(分鐘爲單位)。
Input: ["23:59","00:00"] Output: 1
題解:先排序,而後兩兩相鄰的相減。還有第一個和最後一個相減。
1 class Solution { 2 public: 3 int findMinDifference(vector<string>& timePoints) { 4 sort(timePoints.begin(), timePoints.end()); 5 int ret = calDiff(timePoints[0], timePoints.back()); 6 for (int i = 0; i < timePoints.size() - 1; ++i) { 7 ret = min(ret, calDiff(timePoints[i], timePoints[i+1])); 8 } 9 return ret; 10 } 11 int calDiff(string s1, string s2) { 12 int num1 = trans(s1), num2 = trans(s2); 13 if (num1 < num2) { swap(num1, num2); } 14 return min(num1 - num2, num2 + 1440 - num1); 15 } 16 int trans(string s) { 17 int hour = stoi(s.substr(0, 2)); 18 int min = stoi(s.substr(3)); 19 return hour * 60 + min; 20 } 21 };
【541】Reverse String II
【544】Output Contest Matches
【551】Student Attendance Record I
【553】Optimal Division
【555】Split Concatenated Strings
【556】Next Greater Element III
【557】Reverse Words in a String III
【564】Find the Closest Palindrome (2019年3月3日,H)
給定一個字符串 N, 求距離 N 最近的迴文數。
Input: "123" Output: "121"
題解:唔,這個題看了awice的思路。就是說,咱們先把這個數分紅前面一半和後面一半,好比「23456」,一半就是「234」,用前面一半分別 +{-1, 0 ,1}, 而後生成對應的迴文(注意原數字長度的奇偶性)。這樣能生成3個candidate。
可是其實還有兩個數字,就是比給定數字長度少一位的最大回文,9999...999,和比給定數字長度多一位的最小回文,10...01。一共五個candidate。
若是candidate中有N自己,就忽略掉。從candidate中選出距離最近的那個。
1 class Solution { 2 public: 3 string nearestPalindromic(string n) { 4 const int size = n.size(); 5 string strHalf = n.substr(0, (size + 1)/ 2); 6 long long half = stoll(strHalf); 7 set<string> st; 8 long long biggest = pow(10LL, size) + 1, smallest = pow(10LL, size - 1) - 1; 9 st.insert(to_string(smallest)); 10 st.insert(to_string(biggest)); 11 for (int i = -1; i <= 1; ++i) { 12 string p = to_string(half + i); 13 string pp = p; 14 if (size & 1) { 15 pp += string(p.rbegin() + 1, p.rend()); 16 } else { 17 pp += string(p.rbegin(), p.rend()); 18 } 19 st.insert(pp); 20 } 21 st.erase(n); 22 string res = ""; 23 long long absMinDiff = LLONG_MAX; 24 for (auto& s : st) { 25 long long num = stoll(s), target = stoll(n); 26 if (abs(num - target) < absMinDiff) { 27 res = s; 28 absMinDiff = abs(num - target); 29 } else if (abs(num - target) == absMinDiff && num < target) { 30 res = s; 31 } 32 } 33 return res; 34 } 35 };
【583】Delete Operation for Two Strings
【591】Tag Validator
【606】Construct String from Binary Tree
2018年11月14日,樹的分類裏面作了:http://www.javashuo.com/article/p-qokilyny-mq.html
【609】Find Duplicate File in System
【616】Add Bold Tag in String
【632】Smallest Range
【635】Design Log Storage System
【647】Palindromic Substrings
【657】Robot Return to Origin
【678】Valid Parenthesis String
【680】Valid Palindrome II (2019年2月12日)
輸入是一個字符串,問字符串最多刪除一個字符,看能不能變成迴文字符串。
題解:2 pointers 先遍歷,找到第一個失配的地方,而後分別從左右去查找跳過這個字符,剩下的字符串是否是能成迴文。
1 class Solution { 2 public: 3 bool validPalindrome(string s) { 4 int begin = 0, end = s.size() - 1; 5 while (begin < end) { 6 if (s[begin] != s[end]) { 7 if (isValid(s, begin+1, end) || isValid(s, begin, end-1)) { 8 return true; 9 } 10 return false; 11 } 12 ++begin, --end; 13 } 14 return true; 15 } 16 bool isValid(string s, int begin, int end) { 17 while (begin < end) { 18 if (s[begin++] != s[end--]) {return false;} 19 } 20 return true; 21 } 22 };
【681】Next Closest Time (2019年1月29日,谷歌tag複習)
給了一個字符串,表明時間,HH:MM,返回用當前數字組成的合法的下一個時間。There is no limit on how many times a digit can be reused.
Input: "19:34" Output: "19:39" Explanation: The next closest time choosing from digits 1, 9, 3, 4, is 19:39, which occurs 5 minutes later. It is not 19:33, because this occurs 23 hours and 59 minutes later.
Input: "23:59" Output: "22:22" Explanation: The next closest time choosing from digits 2, 3, 5, 9, is 22:22. It may be assumed that the returned time is next day's time since it is smaller than the input time numerically.
題解:思路就是先把全部的四個數字存下來,從最小的(分針)開始往前找,若是找到了比當前位置更大的一個數的話,就用這個更大的數字去代替當前的數字。(前提是這個更大的數字代替完了以後這個時間得合法。)若是找到最大的位置都沒有找到的話,那就用最小的數字生成一個次日的時間來做爲新的數字。
1 class Solution { 2 public: 3 string nextClosestTime(string time) { 4 set<int> st; 5 int minn = 10; 6 for (int i = 0; i < 5; ++i) { 7 if (isdigit(time[i])) { 8 int t = time[i] - '0'; 9 minn = min(t, minn); 10 st.insert(t); 11 } 12 } 13 if (st.size() == 1) {return time;} //invalid 14 string ret = time; 15 for (int i = 4; i >= 0; --i) { 16 char c = ret[i]; 17 int t = c - '0'; 18 auto iter = upper_bound(st.begin(), st.end(), t); 19 if (iter == st.end()) {continue;} 20 if (i == 0 && *iter > 2) { 21 continue; 22 } 23 if (i == 1 && *iter > 4 && ret[0] == '2') { 24 continue; 25 } 26 if (i == 3 && *iter > 5) { 27 continue; 28 } 29 ret[i] = (*iter) + '0'; 30 for (int k = i + 1; k < 5; ++k) { 31 if (isdigit(ret[k])) { 32 ret[k] = minn + '0'; 33 } 34 } 35 break; 36 } 37 if (ret == time) { 38 for (auto& c : ret) { 39 if (isdigit(c)) { 40 c = minn + '0'; 41 } 42 } 43 } 44 return ret; 45 46 } 47 };
【686】Repeated String Match
【696】Count Binary Substrings
【709】To Lower Case
【722】Remove Comments (2019年2月16日, M)
給了一個字符串的數組,每一個字符串代碼一行代碼,裏面'//', '/*', '*/' 分別表明一行和多行註釋。返回去掉註釋後的代碼段。
題解:用兩個bool變量記錄,inline記錄是否當前在//註釋裏面,inBlock記錄是否當前在 /**/ 裏面。而後業務邏輯比較一下。
1 class Solution { 2 public: 3 vector<string> removeComments(vector<string>& source) { 4 vector<string> res; 5 bool inBlock = false; 6 string s = ""; 7 for (auto& line : source) { 8 const int n = line.size(); 9 bool inLine = false; 10 for (int i = 0; i < n; ++i) { 11 if (i + 1 < n && line[i] == '/') { 12 if (line[i+1] == '/' && !inBlock) { 13 inLine = true; 14 } else if (line[i+1] == '*' && !inLine && !inBlock) { 15 ++i, inBlock = true; 16 } else if (!inBlock && !inLine) { 17 s += string(1, line[i]); 18 } 19 } else if (i + 1 < n && line[i] == '*' && line[i+1] == '/') { 20 if (inBlock) { 21 ++i, inBlock = false; 22 } else if (!inLine){ 23 s += string(1, line[i]); 24 } 25 } else { 26 if (inBlock || inLine) {continue;} 27 s += string(1, line[i]); 28 } 29 } 30 if (!inBlock && !s.empty()) { 31 res.push_back(s); 32 s.clear(); 33 } 34 } 35 return res; 36 } 37 };
【730】Count Different Palindromic Subsequences
【736】Parse Lisp Expression
【758】Bold Words in String
【761】Special Binary String
【767】Reorganize String
【770】Basic Calculator IV
【772】Basic Calculator III
【788】Rotated Digits
【791】Custom Sort String (2018年11月27日)
給了兩個字符串 S 和 T, S中最多有 26個小寫字母,給 T 從新排序,若是字母 x, y 在 S 中出現,且在 T 中出現,若是在 S 中 x 出如今 y 以前, 那麼在 T 中 x 也要出如今 y 以前。沒有在 S 中出現的字符就隨便放哪裏均可以。
題解:直接 unordered_map
1 class Solution { 2 public: 3 string customSortString(string S, string T) { 4 const int n = T.size(); 5 unordered_map<char, int> mp; 6 for (int i = 0; i < n; ++i) { 7 mp[T[i]]++; 8 } 9 string ret; 10 for (auto c : S) { 11 if (mp.find(c) == mp.end() || mp[c] == 0) {continue;} 12 ret += string(mp[c], c); 13 mp[c] = 0; 14 } 15 for (auto ele : mp) { 16 if (ele.second > 0) { 17 ret += string(ele.second, ele.first); 18 } 19 } 20 return ret; 21 } 22 };
【800】Similar RGB Color
【804】Unique Morse Code Words
【809】Expressive Words (2019年2月13日,google tag)
給了一個word S和一個word list,問word list中有多少pattern符合S。一個 pattern w 符合 S 的條件是,w extend以後能夠變成 S。w 中的一個字母能夠extend成三個或者三個以上相同的字母。問word list中有多少個這樣的pattern。
題解:個人解法時間複雜度是O(NM),空間複雜度使用了一個map,仍是比較高的。個人解法的說明以下:對於S中每個小段重複序列,計算當前字符重複了多少次。根據不一樣重複的次數獲得pattern中的相同字符的範圍,而後去對比pattern。
1 class Solution { 2 public: 3 int expressiveWords(string S, vector<string>& words) { 4 const int n = S.size(); 5 unordered_map<string, int> mp; 6 for (auto& w : words) { mp[w] = 0; } 7 int begin = 0, end = 0, cnt = 0; 8 int res = 0; 9 while (end < n) { 10 while (end < n && S[begin] == S[end]) { 11 ++end; 12 } 13 cnt = end - begin; 14 pair<int, int> range(0, 0); 15 if (cnt <= 2) { 16 range = make_pair(cnt, cnt); 17 } else { 18 range = make_pair(1, cnt + 1 - 3); 19 } 20 res = 0; 21 for (auto& p : mp) { 22 string pattern = p.first; 23 int start = p.second, end1 = start, size = pattern.size(); 24 if (start < 0) {continue;} 25 while (end1 < size && pattern[end1] == pattern[start]) { 26 ++end1; 27 } 28 int sameSize = end1 - start; 29 if (sameSize >= range.first && sameSize <= range.second) { 30 p.second = end1; 31 ++res; 32 } else { 33 p.second = -1; 34 } 35 } 36 begin = end; 37 } 38 return res; 39 } 40 };
還有lee215的解法。寫的很短,也很好理解。須要好好複習學習。
用word list中每一個單詞和S作一個比較,比較規則以下:
Loop through all words. check(string S, string W)
checks if W
is stretchy to S
.
In check
function, use two pointer:
S[i] == W[j]
, i++, j++
S[i - 2] == S[i - 1] == S[i]
or S[i - 1] == S[i] == S[i + 1]
, i++
1 class Solution { 2 public: 3 int expressiveWords(string S, vector<string>& words) { 4 int res = 0; 5 for (auto& w : words) { 6 if (check(S, w)) {++res;} 7 } 8 return res; 9 } 10 bool check(const string& s, const string& w) { 11 int n = s.size(), m = w.size(); 12 int j = 0; 13 for (int i = 0; i < n; ++i) { 14 if (j < m && s[i] == w[j]) {++j;} 15 else if (i - 2 >= 0 && s[i] == s[i-1] && s[i] == s[i-2]) {;} 16 else if (i - 1 >= 0 && i + 1 < n && s[i] == s[i-1] && s[i] == s[i+1]) {;} 17 else { return false; } 18 } 19 return j == m; 20 } 21 };
【816】Ambiguous Coordinates
【819】Most Common Word
【824】Goat Latin
【831】Masking Personal Information
【833】Find And Replace in String
【842】Split Array into Fibonacci Sequence
【848】Shifting Letters
【856】Score of Parentheses
【859】Buddy Strings
【890】Find and Replace Pattern
【893】Groups of Special-Equivalent Strings
【899】Orderly Queue