给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: "A man, a plan, a canal: Panama" 输出: true
示例 2:
输入: "race a car" 输出: false
注意:'0' + 'a' - 'A' = 'P'
class Solution
{
public:
bool isPalindrome(string s)
{
int len = s.size();
if(len <= 1)
{
return true;
}
int low = 0, high = len - 1;
while(low < high)
{
if(s[low] >= 'a' && s[low] <= 'z' || s[low] >= 'A' && s[low] <= 'Z' || s[low] >= '0' && s[low] <= '9')
{
if (s[high] >= 'a' && s[high] <= 'z' || s[high] >= 'A' && s[high] <= 'Z' || s[high] >= '0' && s[high] <= '9')
{
if((s[low] >= '0' && s[low] <= '9' && (s[high] < '0' || s[high] > '9')) || (s[high] >= '0' && s[high] <= '9' && (s[low] < '0' || s[low] > '9')))
{
return false;
}
else if (s[low] != s[high] && s[low] + 'a' - 'A' != s[high] && s[low] - 'a' + 'A' != s[high])
{
return false;
}
else
{
low++;
high--;
}
}
else
{
high--;
}
}
else
{
low++;
}
}
return true;
}
};
分割回文串
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
示例:
输入: "aab" 输出: [ ["aa","b"], ["a","a","b"] ]
DFS搜索
class Solution
{
vector> ans;
public:
vector> partition(string s)
{
vector arr;
GetAns(s, 0, arr);
return ans;
}
void GetAns(string s, int pos, vector &arr)
{
if(pos >= s.size())
{
ans.push_back(arr);
return;
}
for (int i = pos; i < s.size(); i++)
{
string temp(s.begin() + pos, s.begin() + i + 1);
if(Check(temp))
{
arr.push_back(temp);
GetAns(s, i + 1, arr);
arr.pop_back();
}
}
}
bool Check(string s)
{
if(s.size() <= 1)
return true;
for (int i = 0, j = s.size() - 1; i < j; i++, j--)
{
if(s[i] != s[j])
return false;
}
return true;
}
};
单词拆分
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"] 输出: true 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
示例 2:
输入: s = "applepenapple", wordDict = ["apple", "pen"] 输出: true 解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。 注意你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: false
DP
dp:
class Solution
{
public:
bool wordBreak(string s, vector &wordDict)
{
if(wordDict.size() <= 0)
{
return false;
}
if(s.size() <= 0)
{
return true;
}
map Check;
for (int i = 0; i < wordDict.size(); i++)
{
Check[wordDict[i]] = true;
}
vector dp(s.size(), false);
for (int i = 0; i < s.size(); i++)
{
string temp(s.begin(), s.begin() + i + 1);
if(Check[temp])
{
dp[i] = true;
continue;
}
for (int j = 0; j < i; j++)
{
if(dp[j] == true)
{
string temp2(s.begin() + j + 1, s.begin() + i + 1);
if(Check[temp2])
{
dp[i] = true;
break;
}
}
}
}
return dp[s.size() - 1];
}
};
单词拆分II
给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
说明:
示例 1:
输入: s = "catsanddog" wordDict = ["cat", "cats", "and", "sand", "dog"] 输出: [ "cats and dog", "cat sand dog" ]
示例 2:
输入: s = "pineapplepenapple" wordDict = ["apple", "pen", "applepen", "pine", "pineapple"] 输出: [ "pine apple pen apple", "pineapple pen apple", "pine applepen apple" ] 解释: 注意你可以重复使用字典中的单词。
示例 3:
输入: s = "catsandog" wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: []
DP加DFS
class Solution
{
map> save;
vector ans;
public:
vector wordBreak(string s, vector &wordDict)
{
if (wordDict.size() <= 0)
{
return ans;
}
if (s.size() <= 0)
{
return ans;
}
map Check;
for (int i = 0; i < wordDict.size(); i++)
{
Check[wordDict[i]] = true;
}
vector dp(s.size(), false);
for (int i = 0; i < s.size(); i++)
{
string temp(s.begin(), s.begin() + i + 1);
if (Check[temp])
{
dp[i] = true;
save[i].push_back(temp);
}
for (int j = 0; j < i; j++)
{
if (dp[j] == true)
{
string temp2(s.begin() + j + 1, s.begin() + i + 1);
if (Check[temp2])
{
dp[i] = true;
save[i].push_back(temp2);
}
}
}
}
if(!dp[s.size() - 1])
return ans;
DFS(s.size(), "");
return ans;
}
void DFS(int len, string s)
{
if(len == 0)
{
ans.push_back(s);
return;
}
for (int i = 0; i < save[len - 1].size(); i++)
{
DFS(len - save[len - 1][i].size(), save[len - 1][i]+ (s == ""? "" : " ") + s);
}
}
};
实现Trie字典树
实现一个 Trie (前缀树),包含 insert, search, 和 startsWith 这三个操作。
示例:
Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); // 返回 true trie.search("app"); // 返回 false trie.startsWith("app"); // 返回 true trie.insert("app"); trie.search("app"); // 返回 true
说明:
class Trie
{
struct TrieNode
{
bool isWord;
vector children;
TrieNode()
{
isWord = false;
children = vector(26, NULL);
}
~TrieNode()
{
for (int i = 0; i < 26; i++)
{
if (children[i] != NULL)
{
delete children[i];
}
}
}
};
private:
TrieNode *root;
public:
Trie()
{
root = new TrieNode();
}
~Trie()
{
delete root;
}
bool find(string word, TrieNode *&newRoot)
{
for (int i = 0; i < word.size(); i++)
{
if (newRoot->children[word[i] - 'a'] == NULL)
{
return false;
}
newRoot = newRoot->children[word[i] - 'a'];
}
return true;
}
void insert(string word)
{
TrieNode* newRoot = root;
for (int i = 0; i < word.size(); i++)
{
if (newRoot->children[word[i] - 'a'] == NULL)
{
newRoot->children[word[i] - 'a'] = new TrieNode();
}
newRoot = newRoot->children[word[i] - 'a'];
}
newRoot->isWord = true;
}
bool search(string word)
{
TrieNode *newRoot = root;
return (find(word, newRoot) && newRoot->isWord);
}
bool startsWith(string prefix)
{
TrieNode *newRoot = root;
return find(prefix, newRoot);
}
};
有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram" 输出: true
示例 2:
输入: s = "rat", t = "car" 输出: false
说明:
你可以假设字符串只包含小写字母。
class Solution
{
public:
bool isAnagram(string s, string t)
{
map str1;
map str2;
if(s.size() != t.size())
return false;
for(char c : s)
{
str1[c]++;
}
for(char c : t)
{
str2[c]++;
}
for(char c : s)
{
if(str1[c] != str2[c])
return false;
}
return true;
}
};
字符串中的第一个唯一字符
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
案例:
s = "leetcode" 返回 0. s = "loveleetcode", 返回 2.
注意事项:您可以假定该字符串只包含小写字母。
class Solution
{
public:
int firstUniqChar(string s)
{
map save;
for(char c : s)
{
save[c]++;
}
for (int i = 0; i < s.size(); i++)
{
if(save[s[i]] == 1)
return i;
}
return -1;
}
};
反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII码表中的可打印字符。
示例 1:
输入:["h","e","l","l","o"] 输出:["o","l","l","e","h"]
示例 2:
输入:["H","a","n","n","a","h"] 输出:["h","a","n","n","a","H"]
class Solution
{
public:
void reverseString(vector &s)
{
int i = 0, j = s.size() - 1;
for (; i < j; i++, j--)
{
swap(s[i], s[j]);
}
}
};
单词搜索II
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例:
输入: words = ["oath","pea","eat","rain"] and board = [ ['o','a','a','n'], ['e','t','a','e'], ['i','h','k','r'], ['i','f','l','v'] ] 输出: ["eat","oath"]
说明:
你可以假设所有输入都由小写字母 a-z 组成。
提示:
前缀数加DFS
class Solution
{
public:
struct TrieNode
{
vector children;
bool isWord;
TrieNode()
{
children = vector(26, NULL);
isWord = false;
}
~TrieNode()
{
for (int i = 0; i < 26; i++)
{
if (children[i] != NULL)
{
delete children[i];
}
}
}
};
class Trie
{
public:
TrieNode *root;
Trie()
{
root = new TrieNode();
}
~Trie()
{
delete root;
}
void insert(string word)
{
TrieNode *newRoot = root;
for (int i = 0; i < word.size(); i++)
{
if (newRoot->children[word[i] - 'a'] == NULL)
{
newRoot->children[word[i] - 'a'] = new TrieNode();
}
newRoot = newRoot->children[word[i] - 'a'];
}
newRoot->isWord = true;
}
};
void DFS(vector> &board, vector> &visit, TrieNode *newRoot, int row, int col, string str)
{
if (newRoot == NULL)
return;
if (newRoot->isWord)
{
//标记为false,防止出现重复的答案
newRoot->isWord = false;
ans.push_back(str);
//注意如果这里return的话,某些案例下会少答案,原因可想而知
}
for (int i = 0; i < 4; i++)
{
int newRow = row + dx[i];
int newCol = col + dy[i];
if (newRow < 0 || newRow >= borderRow || newCol < 0 || newCol >= borderCol)
continue;
if (visit[newRow][newCol])
continue;
if (newRoot->children[board[newRow][newCol] - 'a'] == NULL)
continue;
visit[newRow][newCol] = true;
DFS(board, visit, newRoot->children[board[newRow][newCol] - 'a'], newRow, newCol, str + board[newRow][newCol]);
visit[newRow][newCol] = false;
}
}
vector findWords(vector> &board, vector &words)
{
t = new Trie();
borderRow = board.size();
if (borderRow == 0 || words.size() == 0)
{
return ans;
}
borderCol = board[0].size();
vector> visit(borderRow, vector(borderCol, false));
map check;
string str = "";
for(string s : words)
{
t->insert(s);
}
for (int r = 0; r < borderRow; r++)
{
for (int c = 0; c < borderCol; c++)
{
if (t ->root ->children[board[r][c] - 'a'] != NULL)
{
visit[r][c] = true;
TrieNode *newRoot = t->root->children[board[r][c] - 'a'];
DFS(board, visit, newRoot, r, c, str + board[r][c]);
visit[r][c] = false;
}
}
}
return ans;
}
private:
Trie *t;
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
int borderRow;
int borderCol;
vector ans;
};