[LEETCODE]算法进阶自练习13-14 Trie树&分治算法
13.Trie树
简单
- 词典中最长的单词 leetcode 720 暴力解法:
string longestWord(vector<string>& words) {
unordered_set<string> set;
for(string& word:words){
set.insert(word);
}
string ret = "";
for(string& word : words){
int wsize = word.size(), rsize = ret.size();
if(wsize>rsize || (wsize==rsize && word.compare(ret)<0)){
bool bfind = true;
for(int i=1; i<wsize; ++i){
string t = word.substr(0, i);
if(set.count(t)){
continue;
}
else{
bfind = false;
break;
}
}
if(bfind) ret = word;
}
}
return ret;
}
Trie树解法:
class TrieNode{
public:
vector<TrieNode*> child;
TrieNode(){
child = vector<TrieNode*>(26,nullptr);
}
};
class Solution {
private:
TrieNode* root;
string ret;
int len;
public:
Solution(){
root = new TrieNode();
ret = "";
len = 0;
}
void add(string word){
int wsize = word.size(), i=0;
TrieNode* p = root;
for(; i<wsize-1; i++){
if(p->child[word[i] - 'a'] == nullptr) return;
p = p->child[word[i]-'a'];
}
p->child[word[i]-'a'] = new TrieNode();
if(wsize>len || (wsize==len && word < ret)){
len = wsize;
ret = word;
}
}
string longestWord(vector<string>& words) {
sort(words.begin(),words.end());
for(string& word:words){
add(word);
}
return ret;
}
};
中等
- 实现Trie(前缀树) leetcode 208
class TrieNode{
public:
vector<TrieNode*> child;
bool isWord;
TrieNode(){
isWord = false;
child = vector<TrieNode*>(26,nullptr);
}
};
class Trie {
public:
TrieNode* root;
Trie() {
root = new TrieNode();
}
void insert(string word) {
int wsize = word.size();
TrieNode* p = root;
for(int i=0; i<wsize; i++){
if(p->child[word[i]-'a'] == nullptr){
p->child[word[i]-'a'] = new TrieNode();
}
p = p->child[word[i] - 'a'];
}
p->isWord = true;
}
bool search(string word) {
int wsize = word.size();
TrieNode* p = root;
for(int i=0; i<wsize && p; ++i){
p = p->child[word[i]-'a'];
}
return p && p->isWord;
}
bool startsWith(string prefix) {
int psize = prefix.size();
TrieNode* p = root;
for(int i=0; i<psize&&p; ++i){
p = p->child[prefix[i]-'a'];
}
return p != nullptr;
}
};
- 添加与搜索单词 - 数据结构设计 leetcode 211
class TrieNode{
public:
vector<TrieNode*> child;
bool isWord;
TrieNode(){
isWord = false;
child = vector<TrieNode*>(26,nullptr);
}
};
class WordDictionary {
public:
TrieNode* root;
WordDictionary() {
root = new TrieNode();
}
void addWord(string word) {
int wsize = word.size();
TrieNode* p = root;
for(int i=0; i<wsize&&p; ++i){
if(p->child[word[i]-'a'] == nullptr){
p->child[word[i]-'a'] = new TrieNode();
}
p = p->child[word[i]-'a'];
}
p->isWord = true;
}
bool subSearch(TrieNode* p, string word){
if(p == nullptr) return false;
int wsize = word.size();
for(int i=0; i<wsize; i++){
if(word[i] == '.'){
for(int j=0; j<26; j++){
if(subSearch(p->child[j], word.substr(i+1))) return true;
}
return false;
}
if(p->child[word[i] - 'a'] == nullptr) return false;
p = p->child[word[i]-'a'];
}
return p->isWord;
}
bool search(string word) {
return subSearch(root, word);
}
};
困难
1.单词搜索II leetcode 212
class TrieNode{
public:
string word;
vector<TrieNode*> child;
TrieNode(){
word = "";
child = vector<TrieNode*>(26, nullptr);
}
};
class Solution {
int m; // 行
int n; // 列
vector<string> ret;
public:
void checkWord(vector<vector<char>>& board, TrieNode* root, int i, int j){
char c = board[i][j];
if(c=='.' || root->child[c-'a'] == nullptr) return;
root = root->child[c-'a'];
if(root->word != ""){
ret.emplace_back(root->word);
root->word = "";
}
board[i][j] = '.';
if(i>0) checkWord(board,root,i-1,j);
if(j>0) checkWord(board,root,i,j-1);
if(i+1<m) checkWord(board,root,i+1,j);
if(j+1<n) checkWord(board,root,i,j+1);
board[i][j] = c;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
m = board.size();
n = (m == 0 ? 0 : board[0].size());
if(m ==0 || n == 0) return ret;
TrieNode* root = new TrieNode();
for(string& word:words){
TrieNode* p = root;
int wsize = word.size();
for(int i=0; i<wsize; i++){
if(p->child[word[i]-'a'] == nullptr) p->child[word[i]-'a'] = new TrieNode();
p = p->child[word[i]-'a'];
}
p->word = word;
}
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
checkWord(board, root, i, j);
}
}
return ret;
}
};
14.分治算法
简单
- 多数元素 leetcode 169 Boyer-Moore 投票算法:
int majorityElement(vector<int>& nums) {
int nsize = nums.size();
int candinate = -1, count = 0;
for(int i=0; i<nsize; i++){
if(candinate == nums[i]){
count++;
}
else{
count--;
if(count < 0){
candinate = nums[i];
count = 1;
}
}
}
return candinate;
}
排序解法:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[nums.size()/2];
}
哈希表解法:
int majorityElement(vector<int>& nums) {
map<int, int> mp;
int nsize = nums.size();
for(int i=0; i<nsize; i++) mp[nums[i]]++;
int ret = 0;
auto it = mp.begin();
while(it != mp.end()){
if(it->second > nsize/2){ // 注意这里是大于不包含等于
ret = it->first;
break;
}
it++;
}
return ret;
}
分治解法:
int countInRange(vector<int>& nums, int target, int low, int high){
int count = 0;
for(int i=low; i<=high; i++) if(nums[i] == target) count++;
return count;
}
int majorityElementRec(vector<int>& nums, int low, int high){
if(low == high) return nums[low];
int mid = low + (high-low)/2;
int left_m = majorityElementRec(nums, low, mid);
int right_m = majorityElementRec(nums, mid+1, high);
if(countInRange(nums, left_m, low, high) > (high - low + 1)/2) return left_m;
if(countInRange(nums, right_m, low, high) > (high -low + 1)/2) return right_m;
return -1;
}
int majorityElement(vector<int>& nums) {
return majorityElementRec(nums,0,nums.size()-1);
}
中等
- 最大子序和 leetcode 53 暴力解法:
int maxSubArray(vector<int>& nums) {
int nsize = nums.size(), max_n = INT_MIN;;
for(int i=0; i<nsize; i++){
int t_sum = 0;
for(int j=i; j<nsize; j++){
t_sum += nums[j];
max_n = max(t_sum,max_n);
}
}
return max_n;
}
动态规划解法:
int maxSubArray(vector<int>& nums) {
int nsize = nums.size(), pre = 0, ret = nums[0];
for(int i=0; i<nsize; i++){
pre = max(nums[i], pre + nums[i]);
ret = max(ret,pre);
}
return ret;
}
贪心解法:
int maxSubArray(vector<int>& nums) {
int nsize = nums.size(), sum = 0, ret = INT_MIN;
for(int i=0; i<nsize; i++){
sum += nums[i];
ret = max(ret,sum);
if(sum < 0) sum = 0;
}
return ret;
}
分治解法:
int maxSubArrayRange(vector<int>& nums, int left, int right){
if(left == right) return nums[left];
int mid = left + (right - left)/2;
int left_s = maxSubArrayRange(nums,left,mid);
int right_s = maxSubArrayRange(nums,mid+1,right);
int mid_s = maxSubArrayCrossRange(nums,left,mid,right);
return max(max(left_s, right_s),mid_s);
}
int maxSubArrayCrossRange(vector<int>& nums, int left, int mid, int right){
int left_s = INT_MIN, sum = 0;
for(int i=mid; i>=left; i--){
sum +=nums[i];
left_s = max(left_s,sum);
}
int right_s = INT_MIN; sum = 0;
for(int i=mid+1; i<=right; i++){
sum += nums[i];
right_s = max(right_s, sum);
}
return left_s + right_s;
}
int maxSubArray(vector<int>& nums) {
int nsize = nums.size();
int ret = maxSubArrayRange(nums,0,nsize-1);
return ret;
}
- 搜索二维矩阵 leetcode 240 二分法:
bool binarySearch(vector<vector<int>>& matrix, int target, int i, bool isV){
int l = i, h = isV ? matrix[0].size()-1 : matrix.size()-1;
while(l<=h){
int m = l + (h-l)/2;
if(isV){ // 垂直搜索
if(matrix[i][m] == target) return true;
if(matrix[i][m] < target){
l = m+1;
}
else{
h = m-1;
}
}
else{ // 水平搜索 搜索行
if(matrix[m][i] == target) return true;
if(matrix[m][i] < target){
l = m+1;
}
else{
h = m-1;
}
}
}
return false;
}
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size() == 0 || matrix[0].size() == 0) return false;
int shortdim = min(matrix.size(),matrix[0].size());
for(int i=0; i<shortdim; i++){
bool vFind = binarySearch(matrix, target, i, true);
bool hFind = binarySearch(matrix, target, i, false);
if(vFind || hFind) return true;
}
return false;
}
缩减搜索空间:
bool searchRec(vector<vector<int>>& matrix, int left, int right, int up, int down, int target){
if(left > right || up > down) return false;
if(matrix[up][left] > target || matrix[down][right] < target){
return false;
}
int mid = left + (right - left)/2;
int row = up;
while(row <= down && matrix[row][mid] <= target){
if(matrix[row][mid] == target) return true;
row++;
}
return searchRec(matrix, left, mid-1, row, down, target) || searchRec(matrix, mid+1, right, up, row-1, target);
}
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size() == 0 || matrix[0].size() == 0) return false;
return searchRec(matrix, 0, matrix[0].size()-1, 0, matrix.size()-1, target);
}
左下角开始遍历解法:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m = matrix.size();
int n = (m==0?0:matrix[0].size());
int i = m-1, j = 0;
while(i>=0 && j < matrix[0].size()){
if(matrix[i][j] == target) return true;
matrix[i][j] > target ? i-- : j++;
}
return false;
}