前言
欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
今天是七月集训第九天:二分查找
一、练习题目
1146. 快照数组
1498. 满足条件的子序列数目
1802. 有界数组中指定下标处的最大值
2040. 两个有序数组的第 K 小乘积
二、算法思路
- 1、1146. 快照数组:🔥🔥🔥🔥参考了别人的思路,本题其实并没有完全说明题意,所谓的快照数组就是每次插入一个数都是一个新的编号,并且插入的时候又需要按照索引来进行插入,所以这里图省事的话可以直接建一个50000的三维数组,第一维为索引,第二维为快照编号,第三维为值。插入,初始化都没有什么说的必要,snap返回编号+1即可,get操作就直接在index索引的数组里面二分查找出对应的snap_id即可。
- 2、1498. 满足条件的子序列数目:🔥🔥🔥🔥🔥
- 3、1802. 有界数组中指定下标处的最大值:🔥🔥🔥🔥🔥
- 4、2040. 两个有序数组的第 K 小乘积:🔥🔥🔥🔥🔥
三、源码剖析
// 1146. 快照数组
class SnapshotArray {
vector<vector<int> > arr[50010];
int snapId, len;
public:
SnapshotArray(int length) {
snapId = -1;
len = length;
for(int i = 0; i < length; ++i) {
arr[i].push_back({snapId, 0});
}
}
void set(int index, int val) {
arr[index].push_back({snapId, val});
}
int snap() {
return ++snapId;
}
int get(int index, int snap_id) {
int l = 0, r = arr[index].size() - 1;
int ans;
while(l <= r) {
int mid = (l + r) >> 1;
if(arr[index][mid][0] < snap_id) {
l = mid + 1;
ans = arr[index][mid][1];
} else {
r = mid - 1;
}
}
return ans;
}
};
/**
* Your SnapshotArray object will be instantiated and called as such:
* SnapshotArray* obj = new SnapshotArray(length);
* obj->set(index,val);
* int param_2 = obj->snap();
* int param_3 = obj->get(index,snap_id);
*/
- 1、见思路详解。