删除有序数组重复项通解
class Solution {public: int work(vector<int>& nums, int k) { int len = 0; for(autonum : nums) if(len < k || nums[len-k] != num) nums[len++] = num; return len; } int removeDuplicates(vector<int>& nums) { return work(nums, 2); }};
链表相加
链接
class Solution{public: ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) { ListNode *pre = new ListNode(0); ListNode *cur = pre; int carry = 0; while (l1 || l2) { int n1 = l1 ? l1->val : 0; int n2 = l2 ? l2->val : 0; int sum = n1 + n2 + carry; cur->next = new ListNode(sum % 10); cur=cur->next; carry = sum / 10; if (l1) { ...
线程同步
互斥锁声明一把互斥锁注意:互斥锁是一个全局变量
pthread_mutex_t mutex;
初始化和释放// 初始化互斥锁 pthread_mutex_init(&mutex, NULL);// 线程销毁之后, 再去释放互斥锁 pthread_mutex_destroy(&mutex);
加锁&解锁pthread_mutex_lock(&mutex):
没有被锁定,是打开的,这个线程可以加锁成功,这个这个锁中会记录是哪个线程加锁成功了
如果被锁定了,其他线程加锁就失败了,这些线程都会阻塞在这把锁上
当这把锁被解开之后,这些阻塞在锁上的线程就解除阻塞了,并且这些线程是通过竞争的方式对这把锁加锁,没抢到锁的线程继续阻塞
pthread_mutex_trylock(&mutex):
如果这把锁没有被锁定是打开的,线程加锁成功
如果锁变量被锁住了,调用这个函数加锁的线程,不会被阻塞,加锁失败直接返回错误号
pthread_mutex_unlock(&mutex):
读写锁定义:读写锁是互斥锁的升级版,在做读操作的时候可以提高 ...
多线程
线程函数汇总返回当前线程的线程ID`pthread_t pthread_self(void);
创建线程int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
重要结论:在没有人为干预的情况下,虚拟地址空间的生命周期和主线程是一样的,与子线程无关。如果要让子线程执行完毕,主线程在推出,可以在主线程中添加sleep()。
线程退出作用:终止线程,并返回结果。
void pthread_exit(void *retval);
回收子线程数据如果还有子线程在运行,调用该函数就会阻塞,子线程退出函数解除阻塞进行资源的回收,函数被调用一次,只能回收一个子线程,如果有多个子线程则需要循环进行回收。
int pthread_join(pthread_t thread, void **retval);
使用子线程栈:如果多个线程共用同一个虚拟地址空间,每个线程在栈区都有一块属于自己的内存,相当于 ...
岛屿问题模板
#include<bits/stdc++.h>using namespace std;void dfs(vector<vector<int>> &grid, int r, int c){ // 判断边界是否合适 int row=grid.size(); int col=grid[0].size(); if(!(r>=0&&r<row&&c>=0&&c<col)) return ; //判断这个格子是不是岛屿 if(grid[r][c]!=1) return ; //将格子标记为已经遍历 grid[r][c]=2; //访问上、下、左、右四个相邻结点 dfs(grid,r-1,c); dfs(grid,r+1,c); dfs(grid,r,c-1); dfs(grid,r,c+1);}int main(){ return 0;}
双指针模板
#include<iostream>#include<map>using namespace std;int main(){ string s; int N= s.size(); int left=0; map<char,int> counter; //用于统计 子数组/子区间 是否有效 int res=0; //保存最大的满足题目要求的子数组 for(int right=0; right<N; right++) { counter[s[right]]++;//增加右边指针的计数 while() //[left,right]区间不满足题意 { counter[s[left]]--; left++; } //当while结束时,找到了一个符合要求的子串 res=max(res,right-left+1); } ret ...
埃氏筛法
埃氏筛一种求质数的高级算法
代码#include<bits/stdc++.h>using namespace std;int n=1000;vector<bool> isPrime(n,true);void isPrime_func(){ for(int i=2; i*i<n; i++) { if(isPrime[i]) { for(int j=i*i; j<n; j+=i) { isPrime[j]=false; } } }}int main(){ isPrime_func(); cout<<isPrime[17]<<endl; return 0;}
左值引用和右值引用
左值引用与右值引用的区别定义:左值引用是对左值的引用。右值引用是对右值的引用。
功能差异:
左值引用(避免对象拷贝)
函数传参
函数返回值(拷贝赋值函数)
右值引用
移动语义
完美转发
左值和右值的区别左值的特性:
可以放在=的左边
能够取地址
具备名字(可以有左引用)
左值举例:
变量名
返回值为引用的函数调用
前置自增/前置自减
赋值运算符或复合赋值运算
解引用
int main(){ // 先自增再赋值给i,再进行一个返回。所以++i这个表达式返回的还是i本身,可以取地址 int i=0; ++i=10; //赋值运算符|复合赋值运算 (i=9)=100; (i+=10)=100; //解引用 int *num = new int(10); *num=100; return 0;}
右值的特性:
只能在=右边
不能取地址
不具备名字(不能有左引用)
右值类型:
纯右值(不具备标识符的临时对象或表达式)
字面值
返回非引用类型的函数调用
...
GDB调试
源程序#include<iostream>using namespace std;#define NUM 10int main(int argc, char* argv[]){ cout<<"参数个数:"<<argc<<endl; for(int i=0; i<argc; i++) { cout<<"参数 "<<i<<": "<<argv[i]<<endl; } cout<<"宏变量 "<<NUM<<endl; return 0;}
gdb调试准备要进行调试首先要生成带调试信息的可执行文件,命令为g++ -g app.cpp -o app_g。通过列表查看带调试信息的可执行文件大小比较大。
gdb启动和退出注意gdb启动时,程序并没有运行
gdb app_g启动GDB命 ...