1.笔试题思路
1. 合并两个有序数组到其中一个数组中
将一个数据插入另外一个数据尾部,然后排序 sort(a.begin(), a.end())。
双指针法把两个数组中的数据存入一个临时数组中,然后将临时数组中的值赋值给指定数组。
2. 寻找链表中间节点
快慢指针都指向head节点,慢指针前进一个,快指针前进两个。
3. 有序链表或数组转换为平衡二叉树,也就是中序遍历数组回复为平衡二叉树
寻找中间节点,然后采用递归回复平衡二叉树,创建中间节点的二叉节点,然后该节点的左孩子指向nums(low,mid-1),右孩子指向nums(mid+1,high)。
4. 判断两个string 是否是同构的
两个字符对应位置的字符出现的位置相同
s.find(s[i]) != t.find(t[i]),find返回下标。
5. 比较两个string类型的版本号大小
根据 . 分隔符来计算每一段的大小,然后比较大小,然后循环进行下一位的比较。
6.二分法求中间mid值
int mid = left + (right - left) / 2; // 防止计算时溢出
int mid = (right + left) / 2; // 如果right + left值超过intmax会出现错
7. 两数相乘可能大于intmax
8.二分法在判断大小后:
left = mid +1;
right = mid-1;
否则可能出出现恒left<right。
9. 数组在求二分法时:为防止左边界越界。
int left = 0; int right = nums.size(); //有边界为数组长度,方便在数组是偶数个数时的取值。 int mid = 0; while(left <= right && left < nums.size())
vector<vector<int>>v(m, vector<int>(n));
//升序队列 小顶堆 priority_queue <int,vector<int>,greater<int> > q;
//降序队列 大顶堆 默认大顶堆 priority_queue <int,vector<int>,less<int> >q;
常用的函数:push pop top empty
priority_queue<pair<int, int> > a; // pari型的数据,先比较第一个元素,第一个相等再比较第二个元素。第二个元素时q.top().second; 不是second();
17. queue<int> q
push(elem); //从队尾入对
pop(); //弹出队头元素
back(); //返回最后一个元素
front(); //返回队头元素
A.assign(B.begin(),B.end());
13. 求矩阵对角线是否相同:
matrix[i][j] == matrix[i-1][j-1]
14.归并排序排序链表
ListNode* sortList(ListNode* head) { if (head == nullptr || head->next == nullptr) return head; ListNode* head1 = head; ListNode* head2 = split(head); //寻找链表中间节点 head1 = sortList(head1); head2 = sortList(head2); return merge(head1, head2); //合并两个有序链表 }
15. 整形转string
string str = str + to_string
(left->val);
16.树递归时将需要“累积”的变量通过传引用的方式依次往下传递即可。
比如寻找所有路径,就将path 作为一个变量再递归中调用,将结束的path再放到一个全局变量中,同一个变量再不同的路径下会有不同的值。
17. 树的先序访问:
迭代法:根左右,因为要先访问左节点,考虑栈先进后出,需要先把右节点放进栈中。
对于多叉树的访问:
void preorder(Node* root, vector<int> &res){ if(!root) return ; res.push_back(root->val); //根 for(int i =0;i<root->children.size();i++){ //访问孩子,从左到右 preorder(root->children[i], res); } }
18.判断一个树是否是另外一个棵树的子树,没有很好的办法,只能对主树挨个节点与子树对比。
19. 遍历元素vector和string元素 :
string mostCommonWord(string paragraph, vector<string>& banned) { unordered_set<string> b; for (string bb : banned) { b.insert(bb); }
}
//unordered_set赋值操作: unordered_set<char> s(str.begin(),str.end());
string str = "hello"; string cur; for(char c:str){ cur+=tolower(c); //转为小写 }
20.信号量的使用:
class Foo { protected: sem_t one,two; public: Foo(){ sem_init(&one,0,0); sem_init(&two,0,0); } void first(function<void()> printFirst) { printFirst(); sem_post(&one); } void second(function<void()> printSecond) { sem_wait(&one); printSecond(); sem_post(&two); } void third(function<void()> printThird) { sem_wait(&two); printThird(); } }
21. mutex互斥锁的使用:
交替打印,两个对象可以各自加锁,然后解对方的锁。
class FooBar { private: int n; mutex mtx1,mtx2; public: FooBar(int n) { this->n = n; mtx2.lock(); } void foo(function<void()> printFoo) { for (int i = 0; i < n; i++) { mtx1.lock(); printFoo(); mtx2.unlock(); } } void bar(function<void()> printBar) { for (int i = 0; i < n; i++) { mtx2.lock(); printBar(); mtx1.unlock(); } } };
22. count统计string字符串中字符的数量:
#include <bits/stdc++.h> using namespace std; int main() { string s= "abcdefgaabbccd"; int num =count(s.begin(),s.end(),'a'); //把a改为空格,可以统计字符串中单词的个数 cout<<num<<endl; }
23. vector<int> vec(10);
这是vector初始化,内部每个元素都是0,进行赋值时使用vec[0] = 1; vec[1]=2 进行赋值,如果再直接使用push_back()方式直接往里赛数据,那会出现0000000012的样子。
也就是初始化后只能使用下标进行赋值。直接vector<int> vec;方式初始化,可以不指定下标赋值,内部元素都是空。
24. max_element min
_element求最大值最小值:
int val= *max_element(vec.begin(), vec.end());
25. unordered_set赋值操作:
unordered_set<char> s(str.begin(), str.end());
std::unordered_set<string> words {"one", "two", "three", "four"};
26. sort(vec.begin(), vec.end()) 是从小到大排序的。
27. 坐标两点的距离:切比雪夫距离:简而言之就是左边两点的距离(垂直水平和对角都算距离1),就是两点形成的矩形的最长边。
对于平面上的两个点 x = (x0, y0) 和 y = (x1, y1),设它们横坐标距离之差为 dx = |x0 - x0|,纵坐标距离之差为 dy = |y0 - y1|,对于以下三种情况,我们可以分别计算出从 x 移动到 y 的最少次数: dx < dy:沿对角线移动 dx 次,再竖直移动 dy - dx 次,总计 dx + (dy - dx) = dy 次; dx == dy:沿对角线移动 dx 次; dx > dy:沿对角线移动 dy 次,再水平移动 dx - dy 次,总计 dy + (dx - dy) = dx 次。 可以发现,对于任意一种情况,从 x 移动到 y 的最少次数为 dx 和 dy 中的较大值 max(dx, dy),这也被称作 x 和 y 之间的 切比雪夫距离。 由于题目要求,需要按照数组中出现的顺序来访问这些点。因此我们遍历整个数组,对于数组中的相邻两个点,计算出它们的切比雪夫距离,所有的距离之和即为答案。
28. 有返回值的递归
class Solution { Set<Integer> set = new HashSet<>(); public int numColor(TreeNode root) { if(root == null) return 0; set.add(root.val); numColor(root.left); numColor(root.right);
return set.size(); //只有最外层返回,其他递归调用的返回值没有使用到。 } }
30. string 操作:char *strstr (const char *s1, const char *s2); //在s1中寻找s2,并返回指针
31. 罗马数字转整数,字符排序决定了是累加还是累减。
32. 字符串反转
string s[]="123456"; reverse(s.begin(),s.end());
33.根据数字二进制下 1 的数目排序
自定义cmp类型:
class Solution { public: int get(int x){ int res = 0; while (x) { res += (x % 2); x /= 2; } return res; } vector<int> sortByBits(vector<int>& arr) { vector<int> bit(10001, 0); for (auto x: arr) { bit[x] = get(x); } sort(arr.begin(), arr.end(), [&](int x, int y){ if (bit[x] < bit[y]) { return true; } if (bit[x] > bit[y]) { return false; } return x < y; }); return arr; } };
34.