pat 甲级 知识积累

断断续续也做了30多个题了,不总结一下乱做也没效果,有一些还是要背一背的

♦ 1002 有一个输出问题, 注意输出格式, 尽量多用scanf printf ,做到现在基本只有在用到string的时候只能cin cout 。

♦ 开数组大小的时候要考虑全面,有些时候不通过或者显示段错误的话就把数组再开大点。。

♦ 目前遇到的dijkstra题都还没去研究,,接下来这几天的目标就是继续刷题,然后像动态规划,图论,贪心算法这种还没学模板性质的题学习一下。

♦ string
巧妙应用string,好多题都可以直接用string简化运算,string可以用数组下标访问,可以直接比较大小,直接进行加减法,reverse函数可以吧把string直接反转。
reverse(string.begin(), string.end()) 反转
string.erase 删除某一位置上的字符
stoi(string) // 把string转换为int
atoi(string.string_str()) // 把string转换为int
to_string(int) //把int转为string
string = string.substr(i,j) //取子串

♦ 有几次编译器报错的时候,是变量名的问题,目前遇到的有begin,rank ,都是不可以拿来做变量名的。

♦取整,四舍五入。之前有过的坑点是有一些会5舍6入,解决的办法是+0.001。还有几个函数在cmath里面

ceil(a)  向上取整
floor(a) 向下取整
round(a) 四舍五入

♦ 结构体排序,常见题型。1028, 1012

自定义比较函数,从大到小排就‘>’。
当出现 “如果分数相同,就按学号升序输出” 类似问题,就在比较函数里排序就可以。

bool myscore(stu a, stu b){
    if(a.score == b.score) return a.num < b.num;
    else return a.score < b.score;
}

排名名次问题

arr[0].rank = 1;
for(int i=1; i<l; i++){
    if(arr[i].score == arr[i-1].score) arr[i].rank = arr[i-1].rank;
    else arr[i].rank = i+1;
}

♦ dfs求连通分量问题

int arr[100][100];
int brr[100];

void dfs(int i){
    brr[i] = 1; //表示走过了这个点;
    for(int j=0; j<n; j++){
        if(arr[i][j] == 1 && brr[j] == 0)
        dfs(j);
    }   
}

int main(){

    for(int i=0; i<n; i++){
        if(brr[i] == 0){
            dfs(i);
            sum++;
        }
    }
    return 0;
}

♦ 模拟的题还没咋再练练,就是对STL的熟练运用吧。

♦ 素数判断,注意等号

int isprime(int a){
    for(int i=2; i*i <= a; i++){
        if(a%i==0) return 不是素数;
    }
    return 是素数;
}

♦ 进制转换

do{
    arr[l++] = n%d;
    n /= d;
  }while(n != 0);
  for(int i=0; i<l; i++){
      n = n*d + arr[i];
  }

写累了,还有十多道题没总结完。。

♦ 用cin cout超时又需要存储字符串的话用char数组,比较用 strcmp() , 大小用 strlen()。

strcmp( a, b );

a == b 返回  0
a > b  返回 >0
a < b  返回 <0

♦ 根据后序中序求前序(多理解几次!)

void pre(int root,int start, int end){
    if(start > end) return;
    int i = start;
    while(i < end && 中序[i] != 后序[root]) i++;
    printf("%d ",后序[root]);
    pre(root - 1 - end + i,start,i-1);
    pre(root - 1, i + 1, end);
}

♦ STL指针
个人理解为模板形式

set/vector...<int>::iterator it;
for(it = s.begin(); it != s.end(); it++)
    printf("%d",*it);

♦ STL模板 nth_element
可以用来取中间数

#include <algorithm>

nth_element(arr.begin(),arr.begin+(l-1)/2,arr.end());

♦ vector 初始化用resize();

——8.14 总结到1037——

♦哈希散列
见收藏文章

int hashfunc(char s[],int len){
int id = 0;
for (int i = 0;i <= len;i++){
if (s[i] >= 'A' && s[i] <= 'Z'){
id = id * 62 + (s[i] - 'A');
}
else if (s[i] >= 'a' && s[i] <= 'z'){
id = id * 62 + (s[i] - 'a');
}
else if (s[i] >= '0' && s[i] <= '9'){
id = id * 62 + (s[i] - '0);
}
}
return id;
}

二次方探测法
key1:hash(key)+0
key2:hash(key)+1^2
key3:hash(key)+2^2

♦二分查找

while(left < right){
        mid = (left + right)/2;
        if(arr[mid]  >= m)
            right = mid;        
        else left = mid + 1;
    }

♦树

二叉树层序遍历不用queue方法:

void level(int root){
    if(num[root] == -1) return ;
    level(root*2+1);//左子树 下标 738194 
    num[root] = tree[pos]; // 0
    pos++;
    level(root*2+2);//右子树 下标 256
}

♦pat的链表问题
用结构体存储
注意节点是否在链上,经常考察这个点

while(start != -1){
        number[num].kai = all[start].kai;
        number[num].key = all[start].key;
        number[num].end = all[start].end;
        start = all[start].end;
        num++;
}

♦树状数组
这里写图片描述
lowbit函数理解:返回数转化为二进制后从末尾开始第一个1
比如: 3 二进制是 0011 lowbit(3)返回 0001
10 二进制是1010 lowbit(10)返回 0010

定义:#define lowbit(i) ((i)&(-i))
求区间和:

int Sum(int x){//前x项的和
    int ANS=0;
    while(x>0){
        ANS+=C[x];
        x-=lowbit(x);
    }
    return ANS;
}

因为数据之间是有关联性的
所以要有更新函数,也就是存储函数吧:

void update (int i,int x){  //i点增加x 
    while (i <= N){         //N为原数组长度 
        tree[i] += x;
        i += Lowbit(i);
    }
}

♦用scanf读入特殊格式

♦ set.find()找到此数的的话就返回他在的位置
所以如果最后返回了结尾的end,说明没有相等的值

♦字母,数字判断

inlcude <cctype>

isupper(c) 是否为大写
islower(c) 是否为小写
isdigit(c) 是否为数字
isalpha(c) 是否为字母
isalnum(c) 是否为字母或数字
tolower() 大写字母转换为小写字母
toupper() 小写字母转换为大写字母

♦打印素数表

for(int i = 2; i * i < 500000; i++)
        for(int j = 2; j * i < 500000; j++)
            arr[j * i] = 0;

♦最大公约数

long long gcd(long long a ,long long b){
    return b==0 ? a : gcd(b, a%b);
}

♦最小公倍数

long long lcm(long long a, long long b){
    return a*b/gcd(a,b);
}

♦溢出
正数加正数溢出 为负
负数加负数溢出 为正

♦int 数组也可以用reverse 在algorithm里

♦bfs
用变量控制层数
last是下一层的最后一个,node是当前点,now是当前层的最后一个
所以如果node和now相等了说明此层结束,更新now,去下一层

void bfs(int num, int level){

    memset(arr,0,sizeof(arr));
    queue<int> q;
    q.push(num);
    arr[num] = 1;
    int last, now = num;

    while(q.empty() == 0){
        int node = q.front();
        q.pop();
        for(int i=0; i<tu[node].size(); i++){
            int y = tu[node][i];
            if(arr[y] != 1 ){
                q.push(y);
                arr[y] = 1;
                last = y;
                ans++;              
            }           
        }
        if(node == now) {           
            now = last; 
            level++;
            if(level == l) break;
        }
    }
}

♦优先队列初始化

 priority_queue<int> qi;//普通的优先级队列,按从大到小排序

priority_queue<int, vector<int>, greater<int> > qi2; 
//从小到大的优先级队列,可将greater改为less,即为从大到小

写太多了不让写了?
目前就是这些吧,树的单独写一个,
下午pat,奶一口吧。
——9.08 总结到1085——

原文链接:加载失败,请重新获取