Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[pull] master from wisdompeak:master #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
pull merged 16 commits into AlgorithmAndLeetCode:master from wisdompeak:master
Jun 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
21c5983
Update 642.Design-Search-Autocomplete-System.cpp
wisdompeak Jun 19, 2022
8f5c9fb
Update Readme.md
wisdompeak Jun 19, 2022
57e78dd
Create 2311.Longest-Binary-Subsequence-Less-Than-or-Equal-to-K_v1.cpp
wisdompeak Jun 19, 2022
64d401c
Create 2311.Longest-Binary-Subsequence-Less-Than-or-Equal-to-K_v2.cpp
wisdompeak Jun 19, 2022
16bd37e
Update 2311.Longest-Binary-Subsequence-Less-Than-or-Equal-to-K_v1.cpp
wisdompeak Jun 19, 2022
99fca9d
Create Readme.md
wisdompeak Jun 19, 2022
655136c
Update Readme.md
wisdompeak Jun 19, 2022
36cd4a4
Create 2312.Selling-Pieces-of-Wood.cpp
wisdompeak Jun 19, 2022
99bb6dd
Update Readme.md
wisdompeak Jun 19, 2022
0cb6957
Create Readme.md
wisdompeak Jun 19, 2022
54e342b
Update Readme.md
wisdompeak Jun 19, 2022
94b6826
Create 2222.Number-of-Ways-to-Select-Buildings.cpp
wisdompeak Jun 19, 2022
fbf5e9a
Update Readme.md
wisdompeak Jun 19, 2022
99304f3
Create Readme.md
wisdompeak Jun 19, 2022
7d629b3
Update 2222.Number-of-Ways-to-Select-Buildings.cpp
wisdompeak Jun 19, 2022
f3ef226
Update Readme.md
wisdompeak Jun 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,70 +1,88 @@
class AutocompleteSystem {
unordered_map<string,int>Map;
string data;

struct cmp
class TrieNode
{
public:
TrieNode* next[128];
set<pair<int,string>>top;
TrieNode()
{
bool operator()(pair<string,int>a, pair<string,int>b)
{
if (a.second==b.second)
return a.first<b.first;
else
return a.second>b.second;
}
};
for (int i=0; i<128; i++)
next[i] = NULL;
}
};

class AutocompleteSystem {
TrieNode* root;
string inputStr;
TrieNode* cur;
int flag = 1;
public:
AutocompleteSystem(vector<string> sentences, vector<int> times)
AutocompleteSystem(vector<string>& sentences, vector<int>& times)
{
root = new TrieNode();
cur = root;
for (int i=0; i<sentences.size(); i++)
Map[sentences[i]]=times[i];
data.clear();
add(root, sentences[i], 0, -times[i]);
}

void add(TrieNode* node, const string sentence, int i, int freq)
{
if (i==sentence.size()) return;

int k = sentence[i];
if (node->next[k] == NULL)
node->next[k] = new TrieNode();
node = node->next[k];

int f = 0;
for (auto iter = node->top.begin(); iter!=node->top.end(); iter=next(iter))
{
if (iter->second == sentence)
f = iter->first;
}
if (f!=0) node->top.erase({f, sentence});
node->top.insert(make_pair(f+freq, sentence));

add(node, sentence, i+1, freq);
}

vector<string> input(char c)
{
inputStr.push_back(c);

if (c=='#')
{
Map[data]++;
data.clear();
inputStr.pop_back();
add(root, inputStr, 0, -1);
inputStr = "";
cur = root;
flag = 1;
return {};
}

data.push_back(c);
priority_queue<pair<string,int>,vector<pair<string,int>>,cmp>pq;

for (auto x:Map)
else if (flag==0)
{
string a=x.first;
if (match(data,a))
{
pq.push({a,Map[a]});
if (pq.size()>3) pq.pop();
}
return {};
}

vector<string>results;
while (!pq.empty())
else if (cur->next[c]==NULL)
{
results.push_back(pq.top().first);
pq.pop();
flag = 0;
return {};
}
reverse(results.begin(),results.end());
return results;
}

bool match(string a, string b)
{
for (int i=0; i<a.size(); i++)

cur = cur->next[c];
vector<string>rets;
for (auto iter = cur->top.begin(); iter!=cur->top.end(); iter=next(iter))
{
if (i>=b.size() || a[i]!=b[i])
return false;
rets.push_back(iter->second);
if (rets.size()==3) break;
}
return true;
return rets;

}

};

/**
* Your AutocompleteSystem object will be instantiated and called as such:
* AutocompleteSystem obj = new AutocompleteSystem(sentences, times);
* vector<string> param_1 = obj.input(c);
* AutocompleteSystem* obj = new AutocompleteSystem(sentences, times);
* vector<string> param_1 = obj->input(c);
*/
30 changes: 5 additions & 25 deletions Design/642.Design-Search-Autocomplete-System/Readme.md
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -1,30 +1,10 @@
### 642.Design-Search-Autocomplete-System

如果不用trie来做的话,可以比较简单地用priority_queue来实现对所有候选语句的排序,选择最终未被弹出的三个字符串。
我们将所有的句子都构建入一棵字典树。对于每个节点(字母),我们都维护一个```句子-频次```的统计。也就是说,注入句子S时,我们将沿途经过的节点都标记上```freq[S]+=1```.

核心代码非常简单:
```
struct cmp
{
bool operator()(pair<string,int>a, pair<string,int>b)
{
if (a.second==b.second)
return a.first<b.first;
else
return a.second>b.second;
}
};
priority_queue<pair<string,int>,vector<pair<string,int>>,cmp>pq;
for (auto x:Map)
{
string a=x.first;
if (match(data,a))
{
pq.push({a,Map[a]});
if (pq.size()>3) pq.pop();
}
}
```
当依次读入input时,我们维护从root往下走的指针,移动至该单词对应的节点,读取它的freq取出前三名即可。freq需要使用一个自动排序的数据结构。

记得当input遇到#时,要将之前input的完整句子,从root开始再次构建入这棵字典树。

[Leetcode Link](https://leetcode.com/problems/design-search-autocomplete-system)

[Leetcode Link](https://leetcode.com/problems/design-search-autocomplete-system)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using LL = long long;
class Solution {
LL dp[100005][4][2];
public:
long long numberOfWays(string s)
{
int n = s.size();
s = "#"+s;

dp[0][0][0] = 1;
dp[0][0][1] = 1;

for (int i=1; i<=n; i++)
for (int j=0; j<=3; j++)
for (int k=0; k<2; k++)
{
dp[i][j][k] = dp[i-1][j][k];

if (j>=1 && k==(s[i]-'0'))
dp[i][j][k] += dp[i-1][j-1][1-k];
}

return dp[n][3][0] + dp[n][3][1];
}
};
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
### 2222.Number-of-Ways-to-Select-Buildings

我们在考虑第i个建筑是否被选中时,需要考虑的因素有:我们已经选中了多少?上一个选中的和当前这个是否是同一个类型?

想清楚这些,我们就可以设计状态:dp[i][j][k]表示考虑完第i幢建筑时,如果已经选中了j个,并且最近一个被选中的建筑类别是k时,总共有多少种方案。

状态转移时需要分两种情况:如果我们不选第i个建筑,那么自然dp[i][j][k] = dp[i-1][j][k]。如果我们选中第i个建筑,那么需要保证第i个建筑与类别k是匹配的,于是这就取决于之前解决过的一个问题:在前i-1个建筑里,选择j-1个,并且最近一个选中的建筑类别是1-k,这样的方案有多少。依据dp[i-1][j][1-k],再选中第i个建筑,就是dp[i][j][k]。

最终答案是dp[n][3][0]+dp[n][3][1].
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using LL = long long;
class Solution {
LL dp[201][201];
public:
long long sellingWood(int m, int n, vector<vector<int>>& prices)
{
for (auto x: prices)
dp[x[0]][x[1]] = x[2];

for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
{
for (int k=1; k<i; k++)
dp[i][j] = max(dp[i][j], dp[k][j]+dp[i-k][j]);

for (int k=1; k<j; k++)
dp[i][j] = max(dp[i][j], dp[i][k]+dp[i][j-k]);
}

return dp[m][n];
}
};
7 changes: 7 additions & 0 deletions Dynamic_Programming/2312.Selling-Pieces-of-Wood/Readme.md
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
### 2312.Selling-Pieces-of-Wood

令dp[i][j]表示高度为i、宽度为j的矩形所能得到的最大收益。因为任何一刀必须贯穿整块木板,并且两块木板可以继续各自独立地做进一步操作。显然这就是状态的转移。

假设这一刀是竖切,那么假设左半部分的宽度是k,那么就分成了大小为[i,k]和[i,j-k]的两部分。类似的,如果这一刀是横切,假设上半部分的高度是k,那么就分成了大小为[k,j]和[i-k,j]的两部分。所以我们只要从小到大遍历高和宽,就可以求出所有的dp[i][j].

边界条件是某些特定的高和宽恰好对应了prices里面的形状,那么他们的dp值除了可以通过上述分割的转移方程进行推导,也可以从prices里面得到。两者取大即可。
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
class Solution {
public:
int longestSubsequence(string s, int k)
{
string t;
while (k>0)
{
if (k%2==0)
t.push_back('0');
else
t.push_back('1');
k/=2;
}
reverse(t.begin(), t.end());

int m = s.size();
int n = t.size();

if (m<n) return m;

int ret = n-1;
ret = max(ret, countZeros(s, m-n+1) + n-1);

for (int i=m-1; i>=0; i--)
{
if (check(s,i,t, 0))
{
ret = max(ret, countZeros(s, i) + n);
break;
}
}

return ret ;
}

int countZeros(string&s, int k)
{
int count = 0;
for (int i=0; i<k; i++)
count+= s[i]=='0';
return count;
}

bool check(string& s, int i, string& t, int j)
{
if (j==t.size()) return true;
if (i==s.size()) return false;

if (t[j]=='1')
{
if (s[i]=='1')
return check(s, i+1, t, j+1);
else
return (int)s.size() - i >= (int)t.size() - j;
}
else
{
while (i<s.size() && s[i]=='1')
i++;
if (i==s.size()) return false;
else return check(s, i+1, t, j+1);
}
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class Solution {
public:
int longestSubsequence(string s, int k)
{
string t;
while (k>0)
{
if (k%2==0)
t.push_back('0');
else
t.push_back('1');
k/=2;
}
reverse(t.begin(), t.end());

int m = s.size();
int n = t.size();

if (m<n) return m;

int ret = n-1;
ret = max(ret, countZeros(s, m-n+1) + n-1);

int i = m-n;
if (s.substr(i) <= t)
{
ret = max(ret, countZeros(s, i) + n);
}

return ret ;
}

int countZeros(string&s, int k)
{
int count = 0;
for (int i=0; i<k; i++)
count+= s[i]=='0';
return count;
}
};
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### 2311.Longest-Binary-Subsequence-Less-Than-or-Equal-to-K

#### 解法1:
我们将k同样也转化为二进制的字符串,标记为t。我们令s的长度是m,t的长度为n。注意,因为k是个整形,n的长度不会超过32.

接下来考虑题目中说的"最长"是什么意思。通常情况下,长度小于n的二进制数一定小于k,长度大于n的二进制数一定会大于k,"最长"不就是n吗?本题的关键点在于leading zeros。所以,我们希望尽可能地在期望的subsequence前面堆积0,这就意味着我们希望将subsequence放在s里尽量靠后的位置。

所以我们本题的做法就是:在s里从后往前依次寻找一个起点位置i,判断是否存在一个从i开始的subsequence,使其小于等于t,有的话就再加上s[0:i-1]里的所有0的个数,就是期望的总长度。最后,我们在所有的i的选择里面挑一个答案最长的。

那么指定了起点i,如何判断是否存在一个subsequence小于等于t呢?用递归的方法贪心地扫描即可。如果t[j]是0,那么s[i]必须是0,于是移动i直至找到0,与之match,双指针再自增1。如果t[j]是1,那么如果s[i]是0,直接OK;如果s[j]是1,那么与之match,双指针都自增1.

这种方法的时间复杂度是o(N^2)

#### 解法2:
在解法1的基础上,事实上我们不需要遍历所有起点位置,只需要考察一个位置i=m-n,也就是只需要考察最后一个长度为n的substring即可。这是为什么呢?

先考虑basic plan:只看最后n-1长度的substring(必然小于t),再加上[0:m-n]之间的所有的0. 这显然是一个合法的解。

再考虑如果以i=m-n为起点、长度为n的substring,如果大于t的话(显然s的第i位必然是1),那么说明什么?说明缺0。我们必须将i往前移,目的是为了能够引入0,这样才可能将之后的subsequence的大小降下来。但是一旦真的能引入一个0进入subsequence,那么代价就是损失了一个leading zero。那么收益呢?收益就是将subsequence的匹配度从n-1提升到n而已,并没有优势。

所以本题非常简单,在考察完basic plan之后,只需要查看取最后长度n的substring是否为另一个plan即可。时间复杂度是o(N).
5 changes: 4 additions & 1 deletion Readme.md
View file Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,6 @@

#### [Priority Queue](https://github.com/wisdompeak/LeetCode/tree/master/Priority_Queue)
[004.Median-of-Two-Sorted-Arrays](https://github.com/wisdompeak/LeetCode/tree/master/Priority_Queue/004.Median-of-Two-Sorted-Arrays) (H)
[642.Design-Search-Autocomplete-System](https://github.com/wisdompeak/LeetCode/tree/master/Design/642.Design-Search-Autocomplete-System) (M+)
[774.Minimize-Max-Distance-to-Gas-Station](https://github.com/wisdompeak/LeetCode/tree/master/Priority_Queue/774.Minimize-Max-Distance-to-Gas-Station) (H)
[871.Minimum-Number-of-Refueling-Stops](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/871.Minimum-Number-of-Refueling-Stops) (H-)
[1057.Campus-Bikes](https://github.com/wisdompeak/LeetCode/tree/master/Priority_Queue/1057.Campus-Bikes) (H-)
Expand Down Expand Up @@ -538,6 +537,7 @@
[1804.Implement-Trie-II-(Prefix-Tree)](https://github.com/wisdompeak/LeetCode/tree/master/Trie/1804.Implement-Trie-II-(Prefix-Tree)) (M+)
[211.Add-and-Search-Word](https://github.com/wisdompeak/LeetCode/tree/master/Trie/211.Add-and-Search-Word) (H-)
[472.Concatenated-Words](https://github.com/wisdompeak/LeetCode/tree/master/Trie/472.Concatenated-Words) (H-)
[642.Design-Search-Autocomplete-System](https://github.com/wisdompeak/LeetCode/tree/master/Design/642.Design-Search-Autocomplete-System) (H-)
[648.Replace-Words](https://github.com/wisdompeak/LeetCode/tree/master/Trie/648.Replace-Words) (H)
[588.Design-In-Memory-File-System](https://github.com/wisdompeak/LeetCode/tree/master/Trie/588.Design-In-Memory-File-System) (H-)
[677.Map-Sum-Pairs](https://github.com/wisdompeak/LeetCode/tree/master/Trie/677.Map-Sum-Pairs) (M)
Expand Down Expand Up @@ -615,6 +615,8 @@
[2140.Solving-Questions-With-Brainpower](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/2140.Solving-Questions-With-Brainpower) (H)
[2189.Number-of-Ways-to-Build-House-of-Cards](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/2189.Number-of-Ways-to-Build-House-of-Cards) (H-)
[2218.Maximum-Value-of-K-Coins-From-Piles](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/2218.Maximum-Value-of-K-Coins-From-Piles) (H-)
[2222.Number-of-Ways-to-Select-Buildings](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/2222.Number-of-Ways-to-Select-Buildings) (M+)
[2312.Selling-Pieces-of-Wood](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/2312.Selling-Pieces-of-Wood) (M+)
* ``基本型 I``
[198.House-Robber](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/198.House-Robber) (E)
[213.House-Robber-II](https://github.com/wisdompeak/LeetCode/tree/master/Dynamic_Programming/213.House-Robber-II) (M+)
Expand Down Expand Up @@ -1097,6 +1099,7 @@
[2271.Maximum-White-Tiles-Covered-by-a-Carpet](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/2271.Maximum-White-Tiles-Covered-by-a-Carpet) (M+)
[2275.Largest-Combination-With-Bitwise-AND-Greater-Than-Zero](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/2275.Largest-Combination-With-Bitwise-AND-Greater-Than-Zero) (M+)
[2306.Naming-a-Company](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/2306.Naming-a-Company) (H-)
[2311.Longest-Binary-Subsequence-Less-Than-or-Equal-to-K](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/2311.Longest-Binary-Subsequence-Less-Than-or-Equal-to-K) (H-)
* ``LIS``
[300.Longest-Increasing-Subsequence](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/300.Longest-Increasing-Subsequence) (M+)
[354.Russian-Doll-Envelopes](https://github.com/wisdompeak/LeetCode/tree/master/Greedy/354.Russian-Doll-Envelopes) (H-)
Expand Down

AltStyle によって変換されたページ (->オリジナル) /