Skip to content

Commit 8309c6b

Browse files
committed
up
1 parent 484b6ea commit 8309c6b

8 files changed

+231
-0
lines changed

analysis/all-oone-data-structure.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
## All O(1) Data Structrue [ [sourcecode](../src/all-oone-data-structure.cpp) | [problem](https://leetcode.com/problems/all-oone-data-structure/) ]
2+
3+
##解法分析
4+
加一,减一,获得最大值最小值的操作复杂度都是O(1)
5+
6+
用一个hashmap存储key-value(map),value是双端队列的value对应的node,然后用一个双端队列存储value-keyslist.即存储某个值对应的所有keys(deque)。双端队列的头和尾分别是最小值和最大值。
7+
8+
+ 加一:deque[val].remove(key), deque[val+1].add(key),如果deque中没有val+1则需要添加一个新的node。需要更新map[key]的node为deque[val+1]
9+
+ 减一:deque[val].remove(key), deque[val-1].add(key),如果val-1=0则不添加了。还需要更新map[key]的node为deque[val-1]
10+
+ GetMaxKey:根据最大值maxVal,从deque尾部获得最大值然后pop出来一个key
11+
+ GetMinKey:与GetMaxKey类似,只不过从deque头部取
12+
13+
LFUcache的题与此题基本完全一致,每次操作增加一次,cache用一个map来记录key-value键值对,然后双端队列存储访问次数为n的所有key的列表,
14+
15+
```
16+
1 -> a,b 访问过1次的key有a,b
17+
||
18+
2 -> c 访问过2次的key有c
19+
||
20+
4 -> d 访问过4次的key有d
21+
```
22+
23+
get(key)
24+
25+
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
26+
27+
put(key, value)
28+
29+
- Set or insert the value if the key is not already present. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when there is a tie (i.e., two or more keys that have the same frequency), the least recently used key would be evicted.
30+
31+
32+
##步骤或伪代码

analysis/count-of-range-sum.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## Count of Range Sum [ [sourcecode](../src/count-of-range-sum.cpp) | [problem](https://leetcode.com/problems/count-of-range-sum/) ]
2+
3+
##解法分析
4+
###方法1:分治法
5+
6+
1. mid将数组分为,[left,mid],[mid+1,right]两部分
7+
2. 分别求两个子数组符合条件的区间个数
8+
3. O(n)时间内求包括mid和mid+1两个数的区间个数
9+
10+
+ 用sum[i]先记录a[0]-a[i]的和,区间i,j的和等于sum[j]-sum[i]
11+
+ 将sum[left:mid]和sum[mid+1,right]分别递增排序,考虑merge sort,在求子数组[left,mid]的时候对sum[left:mid]排序,时间就是O(n)
12+
+ 遍历sum[left:mid],用l表示,找到sum[mid+1,right]中符合条件的个数,用r1,r2表示区间,由于是排序好的,l1增加时,sum[l]也是增长的,所以r1,r2也是递增或者是不变的,否则就不满足条件sum[r]-sum[l]<lower_bound了。所以l和r只需要遍历一遍,时间复杂度O(n)
13+
+ mergesort将sum[left:right]排序
14+
15+
###方法二:二叉搜索树
16+
依然用sum[i]先记录a[0]-a[i]的和,
17+
以i为结尾的区间,j属于0-(i-1),如果能在O(logn)时间找出来j的上界下界,那总的时间复杂度就是O(nlogn),可以用二叉搜索树来存储sum数组
18+
,查找和插入都是O(logn). 如果担心二叉搜索树退化,可以用平衡二叉搜索树。
19+
20+
1. 遍历数组a
21+
2. 计算sum[i]
22+
3. 在BST中查找sum[i]-upper_bound<sum[j]和sum[i]-lower_bound>sum[j],从而计算满足条件的j的数量
23+
4. 将sum[i]插入BST中
24+
25+
##步骤或伪代码

analysis/dungeon-game.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## Dungeon Game [ [sourcecode](../src/dungeon-game.cpp) | [problem](https://leetcode.com/problems/dungeon-game/) ]
2+
3+
##解法分析
4+
knight从左上角开始,每次向左或者向下走一次,走到右下角需要多少生命力。生命力为0时死亡。
5+
6+
解法1:假设knignt以0生命力一直走,health[i][j]表示knight走到map[i][j]之后可能保留的生命值的最大值,如果是负数-a就表示kngiht至少要a+1的生命值才能活着走到map[i][j]
7+
8+
health[i][j]=max(health[i-1][j], health[i][j-1])+map[i][j].
9+
10+
然后只需要遍历一遍health[i][j]找出最小值,时间空间,空间复杂度都是O(mn)。
11+
12+
优化空间复杂度:health[i][j]只与health[i-1][j], health[i][j-1]相关。从左上角开始一行一行扫描更新health,扫描到map[i][j]时,更新health[i][j+1],health[i+1][j], 更新之后health[i][j+1]的值就是最大生命值。简化成一维数组记录。
13+
health[j] = max(health[j-1],health[j])
14+
15+
16+
解法2:从右下角倒推。
17+
18+
##步骤或伪代码
19+
```
20+
health[0] = map[0][0];
21+
for (i,j) in map:
22+
health[j] = max(health[j-1], health[j]) + map[i][j]
23+
return health[m]
24+
```

analysis/split-array-largest-sum.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
## Split Array Largest Sum [ [sourcecode](../src/split-array-largest-sum.cpp) | [problem](https://leetcode.com/problems/split-array-largest-sum/) ]
2+
3+
##解法分析
4+
给一个数组S,有n个元素,给定一个数m,将S分成m个连续子数组,使得m个子数组的和的最大值最小,求这个最大值
5+
6+
最开始错误的想法:
7+
将S分成n个组,然后依次merge和最小的两个组,直到剩下m个组。这样是有bug的,
8+
S=[9,3,6,9], m=2, 按照上面的思想就生成了=>[9,9,9]=>[18,9],
9+
但是最优结果是[12,15],所以最优结果是15,而不是18.
10+
11+
正确解法:
12+
首先遍历找到S中的最大值为x,这个是m=n的情况下的最大值,当m=1时,最大值为y=S所有的元素和。
13+
因为m在1-n之间,所以结果肯定介于[x,y]之间。那就二分去找。
14+
mid=(x+y)/2
15+
然后检查子数组最大和是否小于mid
16+
17+
检查方法:基于贪心思想,从左到右,尽量保证接近mid,记录当前累加值,如果小于mid,继续加,否则重新开始一个新的组。如果还没扫描完,组数量已经到m了,说明没法分成m个组使得最大值不大于mid。否则就是能解决。
18+
19+
例如[9,3,6,9],x=9,y=27, mid=18,扫描到9+3+6=18,这个组不能再继续加,从下一个9开始一个新的组,然后结束,正好两个组。
20+
21+
如果mid能达到,y=mid,否则x=mid+1,直到x>=y时,x的值就是最终结果。
22+
23+
复杂度:
24+
n<1000, 每个数最大值2^31,所以总和最大2^41,二分查找nlog(2^41)=41n,
25+
26+
##步骤或伪代码

src/all-oone-data-structure.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @author Brian
3+
* @version 1.0
4+
* @date
5+
*/
6+
7+
#include <iostream>
8+
#include <cstdio>
9+
#include <cstdlib>
10+
#include <cstring>
11+
#include <memory.h>
12+
#include <algorithm>
13+
#include <math.h>
14+
#include <queue>
15+
#include <vector>
16+
using namespace std;
17+
18+
#define fillzero(d) memset(d,0,sizeof(d))
19+
#define print(arr,n) for(int i=0;i<n;i++) printf("%d ",arr[i]);printf("\n");
20+
#define MAXINT 0x7fffffff
21+
#define read(c) scanf("%d",&(c))
22+
#define FOR(a,b) for(int i=(a);i<(b);i++)
23+
24+
class Solution {
25+
public:
26+
27+
};
28+
int main(){
29+
Solution s;
30+
return 0;
31+
}

src/count-of-range-sum.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @author Brian
3+
* @version 1.0
4+
* @date
5+
*/
6+
7+
#include <iostream>
8+
#include <cstdio>
9+
#include <cstdlib>
10+
#include <cstring>
11+
#include <memory.h>
12+
#include <algorithm>
13+
#include <math.h>
14+
#include <queue>
15+
#include <vector>
16+
using namespace std;
17+
18+
#define fillzero(d) memset(d,0,sizeof(d))
19+
#define print(arr,n) for(int i=0;i<n;i++) printf("%d ",arr[i]);printf("\n");
20+
#define MAXINT 0x7fffffff
21+
#define read(c) scanf("%d",&(c))
22+
#define FOR(a,b) for(int i=(a);i<(b);i++)
23+
24+
class Solution {
25+
public:
26+
27+
};
28+
int main(){
29+
Solution s;
30+
return 0;
31+
}

src/dungeon-game.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @author Brian
3+
* @version 1.0
4+
* @date
5+
*/
6+
7+
#include <iostream>
8+
#include <cstdio>
9+
#include <cstdlib>
10+
#include <cstring>
11+
#include <memory.h>
12+
#include <algorithm>
13+
#include <math.h>
14+
#include <queue>
15+
#include <vector>
16+
using namespace std;
17+
18+
#define fillzero(d) memset(d,0,sizeof(d))
19+
#define print(arr,n) for(int i=0;i<n;i++) printf("%d ",arr[i]);printf("\n");
20+
#define MAXINT 0x7fffffff
21+
#define read(c) scanf("%d",&(c))
22+
#define FOR(a,b) for(int i=(a);i<(b);i++)
23+
24+
class Solution {
25+
public:
26+
27+
};
28+
int main(){
29+
Solution s;
30+
return 0;
31+
}

src/split-array-largest-sum.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @author Brian
3+
* @version 1.0
4+
* @date
5+
*/
6+
7+
#include <iostream>
8+
#include <cstdio>
9+
#include <cstdlib>
10+
#include <cstring>
11+
#include <memory.h>
12+
#include <algorithm>
13+
#include <math.h>
14+
#include <queue>
15+
#include <vector>
16+
using namespace std;
17+
18+
#define fillzero(d) memset(d,0,sizeof(d))
19+
#define print(arr,n) for(int i=0;i<n;i++) printf("%d ",arr[i]);printf("\n");
20+
#define MAXINT 0x7fffffff
21+
#define read(c) scanf("%d",&(c))
22+
#define FOR(a,b) for(int i=(a);i<(b);i++)
23+
24+
class Solution {
25+
public:
26+
27+
};
28+
int main(){
29+
Solution s;
30+
return 0;
31+
}

0 commit comments

Comments
 (0)