知识点笔记:哈希存储:字符串存储、数字存储
1 遍历
2 二分
模板
// 相等
int find_equ(int low, int high, int a[], int key){
int mid;
while(low<high){
mid = (low+high)/2;
if(a[mid] == key){
return mid; //mid
}else if(key < a[mid]){ //左边找
high = mid-1;
}else{
low = mid+1;
}
}
return -1;
}
// 第一个>=(升序)
int find_lower_bound(int low, int high, int a[], int key){
int mid;
while(low<high){
mid = (low+high)/2;
if(a[mid] >= key){ //因为a[mid]>=key,所以右边均>=key。第一个>=key的位置,在左边找[low, mid],可能在mid位置=,所以high不能为mid-1
high = mid;
}else{
low = mid+1;
}
}
if(a[low]>=key) return low; //low=high
else return -1;
}
// >
int find_lower(int low, int high, int a[], int key){
int mid;
while(low<high){
mid = (low+high)/2;
if(a[mid] > key){ // 左边找[low, mid], 可能在mid位置第一个>,所以high不能为mid-1
high = mid;
}else{
low = mid+1;
}
}
if(a[low]>key) return low; //low=high
else return -1;
}
int arr[3] = {5, 10, 15};
// >=
int *p, index;
p = lower_bound(arr, arr+3, 20); //不存在,返回假设存在arr[i]>=20应该在的位置,即index=3
index = p-arr;
int k = find_lower_bound(0,2,arr, 10); //k=1
// >
p = upper_bound(arr, arr+3,15); //不存在,返回假设存在arr[i]>15的位置,即index=3
index = p-arr;
k = find_lower(0,2,arr,10); // k=2
1044(25:连续子序列和)
(1)题目
求所有连续子序列和>=k的子序列
(2)代码
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1e+5+10;
const int INF=0x3f3f3f3f;
typedef struct Node{
int start;
int end;
}Node;
// >=
int find_lower_bound(int low, int high, int a[], int key){
int i=low;
int mid;
while(low<high){
mid = (low+high)/2;
if(a[mid]-a[i-1] >= key){
high = mid;
}else{
low = mid+1;
}
}
return low; //low=high
}
bool cmp(Node no1, Node no2){
return no1.start < no2.start;
}
vector<int> vect;
int sum[N]={0}; //sum[i]:vect[1] 到 vect[i]的和
int main(){
//freopen("in.txt", "r",stdin);
int n,m;
scanf("%d%d", &n, &m);
vect.resize(n+1);
for(int i=1; i<=n; i++){
scanf("%d", &vect[i]);
sum[i] = sum[i-1] + vect[i];
}
int tempSum,j;
int minSum=INF;
vector<Node> vect2;
Node node;
for(int i=1; i<vect.size(); i++){
j = find_lower_bound(i,vect.size()-1,sum,m); //第一个sum[j]-sum[i-1]>=m的j:即vect[i] +...+ vect[j]>=m
tempSum = sum[j] - sum[i-1];
if(tempSum < minSum && tempSum>=m){
vect2.clear();
node.start = i;
node.end = j;
vect2.push_back(node);
minSum = tempSum;
}else if(tempSum == minSum && tempSum>=m){
node.start = i;
node.end = j;
vect2.push_back(node);
}
}
sort(vect2.begin(), vect2.end(), cmp);
for(int i=0; i<vect2.size(); i++){
printf("%d-%d\n", vect2[i].start, vect2[i].end);
}
//fclose(stdin);
return 0;
}
(3)小结
- 连续子序列和,设置sum[N]
- 当外层循环为10^5时,内层查找用二分,不能用遍历(超时)
3 hash
3.1 数字存储
1121(25)
题目:
(2)代码
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int ID_MAX = 100000+10;
const int N = 50000+10;
int couple[ID_MAX]; //couple[i]=j,i和j是一对couples
bool party[ID_MAX]; //party[i]:id=i party[i]=true:出席了party
vector<int> alone; //第1种没有couple,第2种自己的couple没出席
int main()
{
//freopen("in.txt", "r", stdin);
fill(couple,couple+N, -1);
int n;
scanf("%d", &n);
for(int i=0; i<n; i++){
int a, b;
scanf("%d%d", &a,&b);
couple[a] = b;
couple[b] = a;
}
int m;
scanf("%d", &m);
for(int i=0; i<m; i++){
int g;
scanf("%d", &g);
party[g]=true;
}
for(int i=0; i<ID_MAX; i++){
if(party[i]){
int j=couple[i];
if(j==-1){ //没有couple
alone.push_back(i);
}else if(!party[j]){ //自己的couple没出席
alone.push_back(i);
}
}
}
sort(alone.begin(), alone.end());
printf("%d\n",alone.size());
for(int i=0; i<alone.size(); i++){
if(i!=0){
printf(" ");
}
printf("%05d", alone[i]);
}
//fclose(stdin);
return 0;
}
(3)小结
- 一对数字:a[i] = j(i和j是一对)
- 有时可用set,有时用hash更方便
如:bool party[ID_MAX]或int party[ID_MAX]
3.2 字符串存储
模板
- map<int, string> 和 map<string, int>(不同的字符串数<1000)
- 进制转换 + 直接定址法()
(进制转换:哈希存储:字符串存储、数字存储
)