Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
14905de
Update Readme.md
wisdompeak May 14, 2022
bf36143
Update Readme.md
wisdompeak May 14, 2022
f4c967f
Update 732.My-Calendar-III.cpp
wisdompeak May 14, 2022
8f0936e
Update Readme.md
wisdompeak May 14, 2022
4f2379f
Update 253.Meeting-Rooms-II_v2.cpp
wisdompeak May 14, 2022
6b48384
Update Readme.md
wisdompeak May 14, 2022
0e98ccd
Update Readme.md
wisdompeak May 14, 2022
4674eea
Create 2272.Substring-With-Largest-Variance.cpp
wisdompeak May 15, 2022
1c66e00
Update Readme.md
wisdompeak May 15, 2022
af821e3
Create Readme.md
wisdompeak May 15, 2022
63cba92
Update Readme.md
wisdompeak May 15, 2022
ed7bc1e
Update 493.Reverse-Pairs_v1.cpp
wisdompeak May 15, 2022
ef946d6
Create 2272.Substring-With-Largest-Variance_v2.cpp
wisdompeak May 15, 2022
c3ede06
Update Readme.md
wisdompeak May 15, 2022
e22071e
Update Readme.md
wisdompeak May 15, 2022
91f879a
Create 2271.Maximum-White-Tiles-Covered-by-a-Carpet.cpp
wisdompeak May 15, 2022
6ffef9d
Update Readme.md
wisdompeak May 15, 2022
5457818
Create Readme.md
wisdompeak May 15, 2022
cc1fd3d
Create 2275.Largest-Combination-With-Bitwise-AND-Greater-Than-Zero.cpp
wisdompeak May 15, 2022
b4faf37
Update Readme.md
wisdompeak May 15, 2022
f2d87dd
Create Readme.md
wisdompeak May 16, 2022
646a399
Create 2276.Count-Integers-in-Intervals.cpp
wisdompeak May 16, 2022
2d20c78
Update Readme.md
wisdompeak May 16, 2022
219555d
Update Readme.md
wisdompeak May 16, 2022
677cff4
Update Readme.md
wisdompeak May 16, 2022
0df9bde
Update Readme.md
wisdompeak May 16, 2022
8c34a2b
Create Readme.md
wisdompeak May 16, 2022
3fa97d9
Create 1893.Check-if-All-the-Integers-in-a-Range-Are-Covered.cpp
wisdompeak May 16, 2022
5e1f37b
Update Readme.md
wisdompeak May 16, 2022
8619c6d
Create Readme.md
wisdompeak May 16, 2022
dccf2d9
Update Readme.md
wisdompeak May 18, 2022
0626bc0
Update 351.Android-Unlock-Patterns.cpp
wisdompeak May 18, 2022
7b1f152
Update 2015.Average-Height-of-Buildings-in-Each-Segment.cpp
wisdompeak May 19, 2022
91c33cf
Update Readme.md
wisdompeak May 19, 2022
cfdfb66
Update 2015.Average-Height-of-Buildings-in-Each-Segment.cpp
wisdompeak May 19, 2022
d4c4f58
Update 2158.Amount-of-New-Area-Painted-Each-Day.cpp
wisdompeak May 20, 2022
7545bae
Update Readme.md
wisdompeak May 21, 2022
3a30051
Create 930.Binary-Subarrays-With-Sum_v2.cpp
wisdompeak May 21, 2022
188a295
Update Readme.md
wisdompeak May 21, 2022
74d918a
Update Readme.md
wisdompeak May 21, 2022
416f6d1
Update 218.The-Skyline-Problem.cpp
wisdompeak May 21, 2022
0518651
Update Readme.md
wisdompeak May 21, 2022
bb6a000
Update Readme.md
wisdompeak May 21, 2022
322c53c
Create 2237.Count-Positions-on-Street-With-Required-Brightness.cpp
wisdompeak May 22, 2022
98a3d37
Update Readme.md
wisdompeak May 22, 2022
280e09c
Create Readme.md
wisdompeak May 22, 2022
240128f
Create 490.The-Maze.cpp
wisdompeak May 22, 2022
9461f77
Update Readme.md
wisdompeak May 22, 2022
1af2dae
Create Readme.md
wisdompeak May 22, 2022
fef2ba8
Create 6077.Sum-of-Total-Strength-of-Wizards.cpp
wisdompeak May 22, 2022
afcbc26
Update Readme.md
wisdompeak May 22, 2022
d7b3e14
Create Readme.md
wisdompeak May 23, 2022
cf23f97
Update Readme.md
wisdompeak May 23, 2022
668082c
Update Readme.md
wisdompeak May 23, 2022
c84c8d2
Update and rename Others/6077.Sum-of-Total-Strength-of-Wizards/6077.S…
wisdompeak May 23, 2022
89d0265
Rename Others/6077.Sum-of-Total-Strength-of-Wizards/Readme.md to Othe…
wisdompeak May 23, 2022
78d4974
Update Readme.md
wisdompeak May 23, 2022
6e82c3f
Update Readme.md
wisdompeak May 23, 2022
6b77c0c
Update Readme.md
wisdompeak May 23, 2022
19a16e8
Create 2280.Minimum-Lines-to-Represent-a-Line-Chart.cpp
wisdompeak May 23, 2022
7c5183f
Update Readme.md
wisdompeak May 23, 2022
3b50e51
Create Readme.md
wisdompeak May 23, 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
49 changes: 49 additions & 0 deletions BFS/490.The-Maze/490.The-Maze.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
class Solution {
int M,N;
vector<pair<int,int>> dir = {{1,0},{-1,0},{0,1},{0,-1}};

public:
bool hasPath(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination)
{
if (start==destination) return true;

M = maze.size();
N = maze[0].size();

auto visited=vector<vector<int>>(M,vector<int>(N,0));

queue<pair<int,int>>q;
q.push({start[0],start[1]});
visited[start[0]][start[1]] = 1;

while (!q.empty())
{
int x0 = q.front().first;
int y0 = q.front().second;
q.pop();

for (int k=0; k<4; k++)
{
auto [x,y] = nextPos(maze,x0,y0,k);
if (x==destination[0] && y==destination[1]) return true;
if (visited[x][y]==1) continue;
visited[x][y]=1;
q.push({x,y});
}
}
return false;
}

pair<int,int> nextPos(vector<vector<int>>& maze, int x0, int y0, int k)
{
int x = x0, y = y0;
while (x>=0 && x<M && y>=0 && y<N && maze[x][y]!=1)
{
x+=dir[k].first;
y+=dir[k].second;
}
x-=dir[k].first;
y-=dir[k].second;
return {x,y};
}
};
3 changes: 3 additions & 0 deletions BFS/490.The-Maze/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### 490.The-Maze

常规的BFS。只不过以往是“每个回合朝一个方向走一步”,现在是“每个回合朝一个方向走到底”。
4 changes: 2 additions & 2 deletions DFS/1192.Critical-Connections-in-a-Network/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

简单地说,我们可以以任意一个未访问过的节点作为根节点,用DFS的顺序来进行搜索,即永远深度优先,然后回溯再搜索其他分支。如果碰到访问过的节点,就停止,保证不行成环。

我们在dfs的过程中维护两个数组,一个是dfs[u],表示节点u被第一次访问时的顺序(可以理解为时间戳),这个是唯一且不变的量。另一个数组low[u]比较关键,初始的时候```low[u]=dfn[u]```。我们以u为节点的开始dfs(注意抵达u之前可能还有u的父节点,但我们dfs的时候不走回头路),想象它最终形成一棵搜索树,那么u的所有子节点中止的条件不外乎有两个:一个是走进了死胡同;另一个就是遇到了已经访问过的节点,特别的,这个已经访问过的节点有可能是u的祖先节点!所以,有了这样的搜索树之后,low[u]可以有机会更新为它所有的子节点v可以接触到的最小时间戳low[v]。
我们在dfs的过程中维护两个数组,一个是dfn[u],表示节点u被第一次访问时的顺序(可以理解为时间戳),这个是唯一且不变的量。另一个数组low[u]比较关键,初始的时候```low[u]=dfn[u]```。我们以u为节点的开始dfs(注意抵达u之前可能还有u的父节点,但我们dfs的时候不走回头路),想象它最终形成一棵搜索树,那么u的所有子节点中止的条件不外乎有两个:一个是走进了死胡同;另一个就是遇到了已经访问过的节点,特别的,这个已经访问过的节点有可能是u的祖先节点!所以,有了这样的搜索树之后,low[u]可以有机会更新为它所有的子节点v可以接触到的最小时间戳low[v]。

令v是u的一个子节点,且有```low[v]>dfn[u]```,这说明什么呢?说明从v出发最终无法绕道u的前面去。因此(v,u)就是割边。如果消除了这条边,v及其子树就是一个孤岛,无法与u或u的祖先相通。同理,如果```low[v]>=dfn[u]```,说明u是一个割点,如果消除了这个点,那么v及其子树也是一个孤岛。

本题中我们还设置了一个parent,其实是为了标记dfs过程中的搜索顺序。因为无向图```for auto v: next[u]```的遍历过程中,v可能是u的父节点,这种情况下v其实不能作为从u开始dfs的下一个目的地(否则就是走回头路了),所以得排除。


[Leetcode Link](https://leetcode.com/problems/critical-connections-in-a-network)
[Leetcode Link](https://leetcode.com/problems/critical-connections-in-a-network)
16 changes: 8 additions & 8 deletions DFS/351.Android-Unlock-Patterns/351.Android-Unlock-Patterns.cpp
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
class Solution {
int count = 0;
int m,n;
int visited[3][3];
vector<pair<int,int>>dir = {{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,1},{1,-1},{-1,-1},{-1,2},{1,2},{-2,1},{2,1},{-1,-2},{1,-2},{-2,-1},{2,-1}};
public:
int numberOfPatterns(int m, int n)
{
this->m = m;
this->n = n;
auto visited = vector<vector<int>>(3, vector<int>(3,0));


for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
{
visited[i][j] = 1;
dfs(i,j,1,visited);
dfs(i,j,1);
visited[i][j] = 0;
}
return count;
}

void dfs(int x, int y, int r, vector<vector<int>>&visited)
{
auto dir = vector<pair<int,int>>({{1,0},{-1,0},{0,1},{0,-1},{1,1},{-1,1},{1,-1},{-1,-1},{-1,2},{1,2},{-2,1},{2,1},{-1,-2},{1,-2},{-2,-1},{2,-1}});
void dfs(int x, int y, int r)
{
if (r>=m && r<=n)
count++;
if (r>n) return;
Expand All @@ -34,7 +34,7 @@ class Solution {
if (visited[i][j] == 0)
{
visited[i][j] = 1;
dfs(i,j,r+1,visited);
dfs(i,j,r+1);
visited[i][j] = 0;
}
else
Expand All @@ -45,7 +45,7 @@ class Solution {
continue;
if (visited[i][j]==1) continue;
visited[i][j] = 1;
dfs(i,j,r+1,visited);
dfs(i,j,r+1);
visited[i][j] = 0;
}
}
Expand Down
62 changes: 32 additions & 30 deletions Divide_Conquer/493.Reverse-Pairs/493.Reverse-Pairs_v1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,38 @@ class Solution {
auto iter = upper_bound(sorted.begin()+a, sorted.begin()+mid+1, 2*(long)nums[j]);
ret += sorted.begin()+mid+1 - iter;
}
// sort(sorted.begin()+a, sorted.begin()+b+1);
int i=a, j=mid+1, p = 0;
while (i<=mid && j<=b)
{
if (sorted[i]<=sorted[j])
{
temp[p] = sorted[i];
i++;
}
else
{
temp[p] = sorted[j];
j++;
}
p++;
}
while (i<=mid)
{
temp[p] = sorted[i];
i++;
p++;
}
while (j<=b)
{
temp[p] = sorted[j];
j++;
p++;
}
for (int i=0; i<b-a+1; i++)
sorted[a+i] = temp[i];

inplace_merge(sorted.begin()+a, sorted.begin()+mid+1, sorted.begin()+b+1);

// int i=a, j=mid+1, p = 0;
// while (i<=mid && j<=b)
// {
// if (sorted[i]<=sorted[j])
// {
// temp[p] = sorted[i];
// i++;
// }
// else
// {
// temp[p] = sorted[j];
// j++;
// }
// p++;
// }
// while (i<=mid)
// {
// temp[p] = sorted[i];
// i++;
// p++;
// }
// while (j<=b)
// {
// temp[p] = sorted[j];
// j++;
// p++;
// }
// for (int i=0; i<b-a+1; i++)
// sorted[a+i] = temp[i];

return ret;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class Solution {
public:
int largestVariance(string s)
{
vector<int>count(26,0);
for (auto x: s)
count[x-'a']++;

int ret = 0;
int n = s.size();
for (int i=0; i<26; i++)
for (int j=0; j<26; j++)
{
if (i==j) continue;
if (count[i]==0 || count[j]==0) continue;
vector<int>arr(n, 0);
for (int k=0; k<n; k++)
{
if (s[k]=='a'+i)
arr[k] = 1;
else if (s[k]=='a'+j)
arr[k] = -1;
}
ret = max(ret, helper(arr));
}

return ret;
}

int helper(vector<int>&nums)
{
int n = nums.size();
vector<int>dp(n);
int curSum = 0;

for (int i = 0; i < n; i++)
{
curSum = max(curSum+nums[i], nums[i]);
dp[i] = curSum;
}

curSum = 0;
int ret = 0;
for (int i=n-1; i>=0; i--)
{
curSum = max(curSum+nums[i], nums[i]);
if (nums[i]==-1)
ret = max(ret, curSum + dp[i] - nums[i]);
}
return ret;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class Solution {
public:
int largestVariance(string s)
{
vector<int>count(26,0);
for (auto x: s)
count[x-'a']++;

int ret = 0;
int n = s.size();
for (int i=0; i<26; i++)
for (int j=0; j<26; j++)
{
if (i==j) continue;
if (count[i]==0 || count[j]==0) continue;
vector<int>arr(n, 0);
for (int k=0; k<n; k++)
{
if (s[k]=='a'+i)
arr[k] = 1;
else if (s[k]=='a'+j)
arr[k] = -1;
}
ret = max(ret, helper(arr));
}

return ret;
}

int helper(vector<int>&nums)
{
int n = nums.size();
int curSum0 = 0;
int curSum1 = INT_MIN/2;
int ret = 0;

for (int i = 0; i < n; i++)
{
if (nums[i]==1)
{
curSum1 = curSum1+nums[i];
curSum0 = max(curSum0+nums[i], nums[i]);
}
else if (nums[i] == -1)
{
curSum1 = max(nums[i], max(curSum0, curSum1)+nums[i]);
curSum0 = 0;
}

ret = max(ret, curSum1);
}

return ret;
}
};
31 changes: 31 additions & 0 deletions Dynamic_Programming/2272.Substring-With-Largest-Variance/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
### 2272.Substring-With-Largest-Variance

本题的突破口是数据范围n=1e4.这是一个比较奇怪的数字。通常来说如果允许nlogn的复杂度,那么n可以达到1e5;类似的,如果是n^2的复杂度,那么n大概就是1000. 在这里,很可能是一个大概是存在100的常数k,使得复杂度的限制在o(kn)。于是我们大概可以猜到,这个k就是跟26或者26^2相关,也就是英文字母的个数。

于是我们就想到了穷举本题中的最大频次字符x和最小频次字母y。这样的话,我们需要在原字符串里面找一个滑窗,使得x的频次与y的频次之差最大,而其他字母都没有任何作用。这就联想到,如果将x的字符都替换为1,y的字符都替换为-1,其他字符都替换为0,那么不就是变成了寻找```max subarray sum```的题目了吗?

但是注意,这里有一点不同,根据题意,我们想要找的subarray必须至少包含一个-1. 传统的kadane算法,我们很有可能找出只有+1的subarray。那么怎么办呢?有两种方法。

#### 解法1
我们可以找那个-1为突破口。根据Kadane的思想,我们找到以每个元素为结尾的最大subarray sum记做dp1[i],那么反过来走一遍就可以得到以每个元素为开头的最大subarray sum记做dp2[i]。那么我们再遍历所有的-1元素i,那么dp1[i]+dp2[i]-nums[i]必然是包含了至少一个-1的max subarray sum。我们再全局找一个最大值即可。

#### 解法2
我们依然按照kadane算法的思路,但是设置两个临时变量:curSum0表示以当前元素为结尾、不包含-1的最大subarray sum,另外用curSum1表示以当前元素为结尾、已经包含-1的最大subarray sum。转移方程如下:
```cpp
for (int i = 0; i < n; i++)
{
if (nums[i] == 1)
{
curSum1 = curSum1+nums[i];
curSum0 = max(curSum0+nums[i], nums[i]);
}
else if (nums[i] == -1)
{
curSum1 = max(nums[i], max(curSum0, curSum1)+nums[i]); // 三种情况可以转移到新的curSum1
curSum0 = 0; // 因为nums[i]是-1,curSum0没有意义,只能置零
}

ret = max(ret, curSum1);
}
```
特别注意,curSum0的初始值可以是0,但是curSum1的初始值必须设置为INT_MIN.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class Solution {
vector<int>presum;
public:
int maximumWhiteTiles(vector<vector<int>>& tiles, int carpetLen)
{
sort(tiles.begin(), tiles.end());
int n = tiles.size();
presum.resize(n);
for (int i=0; i<n; i++)
presum[i] = (i==0?0:presum[i-1]) + (tiles[i][1]-tiles[i][0]+1);
int ret = 0;

int j = 0;
for (int i=0; i<n; i++)
{
while (j<n && tiles[i][0]+carpetLen-1 >= tiles[j][1])
j++;
int len = presum[j-1] - (i==0?0:presum[i-1]);
if (j<n)
len += max(0, tiles[i][0]+carpetLen-1 - tiles[j][0] + 1);
ret = max(ret, len);
}

return ret;
}
};
15 changes: 15 additions & 0 deletions Greedy/2271.Maximum-White-Tiles-Covered-by-a-Carpet/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
### 2271.Maximum-White-Tiles-Covered-by-a-Carpet

本题有非常直观的一种方案。我们放毯子,必然会把毯子的左边界和某一段tile的左边界对齐,以最大化毯子的覆盖(或者说最小化毯子的浪费)。假想我们把毯子的左边界与某tile的中段对齐,直觉上我们不妨将毯子再往左边拉一拉:这个过程中我们本质上,挪用了一部分毯子右侧的空间来覆盖了左边一部分瓷砖,而这个操作肯定是不亏的,甚至还可能赚(因为毯子右侧有可能覆盖的是空隙)。

所以本题我们只要逐一考察毯子的左边界应该对齐哪个tile的左边界即可。在这个过程中,毯子的右边界的位置自然也是单调递增的。所以本题就是维护一个双指针的滑窗。

假设毯子的左边界对应的是tiles[i][0],那么我们向右移动指针j来定位毯子右边界解出的是哪个tile,直至```tiles[i][0]+carpetLen-1 < tiles[j][1]```。如图
```
carpet ____________________________
tiles _____ ________ ________ _______
i j
```
此时tiles[i: j-1]这部分的瓷砖是完全被覆盖的,我们可以用前缀和之差来计算这些tiles的瓷砖总数。另外我们需要计算第j个tile被额外覆盖了多少,这也容易得到:```tiles[i][0]+carpetLen-1 - tiles[j][0] + 1```. 两部分相加就是地毯在这个位置的覆盖面积。

随着地毯移动n次,取全局的最大值即可。
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class Solution {
public:
int largestCombination(vector<int>& candidates)
{
int ret = 0;
for (int i=0; i<31; i++)
{
int count = 0;
for (int x: candidates)
{
if ((x>>i)&1)
count++;
}
ret = max(ret, count);
}
return ret;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### 2275.Largest-Combination-With-Bitwise-AND-Greater-Than-Zero

将若干个数Bitwise AND之后的结果S如果不为零,说明S至少有一个bit位不为零,也就是说所有的数在该bit位上不能有0存在。于是我们可以检查每个bit,统计有多少元素在该bit位上非零。假设有M个元素在某个二进制位上都是1,那么他们的AND结果必然就不是零。

显然,对于32bit的整形,我们检查每个位置之后,可以找到这样一个最大的M。但M是否是最终的答案呢,有没有可能更多呢?答案是否定的。如果有M+1个元素的AND结果非零,必然有一个bit位上该M+1个元素都非零。这和之前的假设“M是所有bit位上我们找到的非零元素最多的那个”相矛盾。
Loading