c++后台开发面试常见知识点总结算法手写
Posted wangxf2019
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++后台开发面试常见知识点总结算法手写相关的知识,希望对你有一定的参考价值。
- 链表倒转 leetcode-206
- 连续子数组最大和问题(和最大的连续子序列的和) leetcode-53
- 输出字符串中最长的回文子串长度? leetcode-5
- 一个字符串,求最长无重复子串的长度? leetcode-3
- 最长递增子序列 leetcode-300
- 反转一个字符串。。。。。。(手写代码) leetcode-344
- 数组中存在一个大于n/2次的数,如何以最优方法查找它?LeetCode 169 229
- 一个字符串中{} [ ] ()匹配问题 LeetCode 20
- 一个数组,只有一个数字出现奇数次,其余数字出现偶数次 LeetCode 136
- 给定一个ip地址,编码使得ip和32位整数呈双射关系 LeetCode 93
- 求一个数组逆序对的个数 LeetCode 629
- 1个32位整数,计算二进制格式下有多少个1 LeetCode 191
- 最小生成树与并查集 leetcode684,685, 721
- 比较两二叉树是否相同(手写代码)LeetCode 100
- 手写判断大小端的代码
- 单链表找倒数第n个节点 LeetCode 19
- 把一颗二叉树原地变成一个双向链表? 114
- 判断一个无符号的整数是不是2的n次方? 231
- int atoi(char *str)? 8
- 栈的getmin()操作 O(1) 155
- 用栈实现队列,用队列实现栈?232 225
- 实现strstr函数 28
- 整数a和b,求a的b次方的最后三位数
- 算法题:将字符串转换成人民币大写(半小时后发邮箱)
- 如何删除map中的奇数节点
- 恢复翻转数组
- 二分法
- 排序
- 手写String
- memcpy函数的实现
- strcpy函数的实现
- BST的第K小的节点 230
- 判断链表是否有环,如果有,返回环的入口节点;求环的长度 141
- 求一个数组逆序对的个数 629
- 翻转数组和恢复翻转数组
- 删除单链表中间节点
- 判断两个单链表是否相交
- r行c列的0,1数组,找到最大的全为1的正方形?
- 连续子数组最大和问题(和最大的连续子序列的和)
- excel中,标志列的如AA,AZZ ,BS,求这些列到底是第几列
- 二叉树两个节点的最近公共祖先
- 去掉字符串中的空格字符
- 删除字符串开始和结尾处的空格,并将中间的多个连续的空格合并成一个
- char *s1, const char *s2,删除s1中s2出现过的字符
- 单链表判环
- 判断一个数是不是回文数
- 求一个集合的所有子集,递归实现,非递归实现
- 旋转有序数组的二分查找
- 删除数组中的重复元素
- 实现一个计算器计算简单的表达式字符串
- memcopy和memove
- 微信小程序团队一共有 n 名成员,决定出去秋游,在海边遇到出租摩托艇的杰克马
- 给定一个二叉树,节点值为0-9, LeetCode 129
- 写一个二叉树翻转,然后写个测试
- trcpy安全性,如何实现安全,strnpy,写一下并测试,
- 写sql语句(A表存储有每个电话号码当月通话记录,表B是电话号码集合,求表B每个号码通话次数)
- 如何设计一个好的字符串hash函数
- 两字符串最长公共子串, 最长公共子序列
- 打印二叉树每层最右边的节点 层序遍历 LeetCode 199
- 顺时针回形打印矩阵的元素 LeetCode 54
- 判断在一个矩阵中是否存在一条包含某字符串所有字符的路径 LeetCode 79
- 3sum 数组中三数之和为0的所有三元组 leetcode 15
- 判断一个字符串是不是两个有序的字符串交错组成的。 Leetcode 97
- 编程题:递增数组中找两个数和为某个固定值。设计测试用例 Leetcode 1
- 给你一个数组和数组元素的个数,求平均值。
- 两个非常大的数相加 Leetcode 415
- 手写下单例模式?
- 链表倒转
从尾到头打印链表(使用栈或者使用递归)
链表倒转
typedef struct ListNode
{
int data;
ListNode *next;
};
ListNode* reverseList1(ListNode *head)
{
if (head == NULL)
return head;
ListNode* dummy = new ListNode;
dummy->data = -1;
dummy->next = head;
ListNode *Cur = dummy->next;
ListNode *tmp = Cur->next;
while (tmp != NULL) {
Cur->next = tmp->next;
tmp->next = dummy->next;
dummy->next = tmp;
tmp = Cur->next;
}
Cur->next = NULL;
return dummy->next;
}
- 连续子数组最大和问题(和最大的连续子序列的和)
- 输出字符串中最长的回文子串长度?
https://blog.csdn.net/h_xy_zwb/article/details/64124271
DP:O(n^2)
string longestPalindrome(string s) {
int len=s.size();
vector<vector<int>> flag(len,vector<int>(len,0));
int maxres=0,idx=0;
for(int i=0;i<len;i++){
for(int j=0,k=i;j<len&&k<len;j++,k++){
if(k==j) flag[j][k]=1;
else if(s[k]==s[j]&&j+1==k) flag[j][k]=2;
else if(s[k]==s[j]&&flag[j+1][k-1]>0) flag[j][k]=flag[j+1][k-1]+2;
else flag[j][k]=0;
if(flag[j][k]>maxres){
maxres=flag[j][k];
idx=j;
}
}
}
return s.substr(idx,maxres);
}
一个字符串,求最长无重复子串的长度?
最长递增子序列:
思想:在求以ai为末元素的最长递增子序列时,找到所有序号在L前面且小于ai的元素aj,即j<i且aj<ai。如果这样的元素存在,那么对所有aj,都有一个以aj为末元素的最长递增子序列的长度f(j),把其中最大的f(j)选出来,那么f(i)就等于最大的f(j)加上1,即以ai为末元素的最长递增子序列,等于以使f(j)最大的那个aj为末元素的递增子序列最末再加上ai;如果这样的元素不存在,那么ai自身构成一个长度为1的以ai为末元素的递增子序列。
- 手写下单例模式?
- class singleton{
- protected:
- singleton(){}
- private:
- static singleton* p;
- public:
- static singleton* getInstance();
- }
- singleton* singleton::p = new singleton();
- singleton* singleton::getInstance(){
- return p;
- }
- 写个string类
- 反转一个字符串。。。。。。(手写代码)
剑指58
.对于string类型的:使用algorithm中的reverse函数,reverse(s.begin(),s.end());
对于用char定义的字符串:使用string.h中的strrev函数,char s[]="123456";//不能是string类型;strrev(s);
实现:设置两个指针,一头一尾,往中间移动;
- 数组存中在一个大于n/2次的数,如何以最优方法查找它?
- int MoreThanHalfNum(int *arr, int len)
- 2 {
- 3 int result = arr[0];
- 4 int count = 1;
- 5
- 6 for(int i = 1; i < len; ++i)
- 7 {
- 8 if(arr[i] == result)
- 9 count ++;
- 10 else if(count == 0)
- 11 {
- 12 result = arr[i];
- 13 count = 1;
- 14 }
- 15 else
- 16 count --;
- 17 }
- 18 return result;
- 19 }
一个字符串中{} [ ] ()匹配问题
bool isValid(string s) {
std::stack<char> st;
for(int i = 0; i < s.size(); ++i)
{
char ch = s.at(i);
if(ch == ‘(‘ || ch == ‘[‘ || ch == ‘{‘)
st.push(ch);
else if(st.size() > 0 && ((ch == ‘)‘ && st.top() == ‘(‘) || (ch == ‘]‘ && st.top() == ‘[‘) || (ch == ‘}‘ && st.top() == ‘{‘)))
st.pop();
else
return false;
}
return st.size() == 0;
}
- 一个数组,只有一个数字出现奇数次,其余数字出现偶数次,如何得到这个数字?如果出现奇数次的数字有2个呢?
可以用位运算实现,如果将所有所有数字相异或,则最后的结果肯定是那两个只出现一次的数字异或的结果,所以根据异或的结果1所在的最低位,把数字分成两半,每一半里都还有只出现一次的数据和成对出现的数据
这样继续对每一半相异或则可以分别求出两个只出现一次的数字
- 给定一个ip地址,编码使得ip和32位整数呈双射关系
int IpToInt(string s)
{ int ret=0; int num=0;
for(int i=0;i<s.size();i++)
{
if(s[i]!=‘.‘) {num=num*10+(s[i]-‘0‘);}
else
{
cout<<num<<endl;
ret=ret<<8;
ret+=num;
cout<<ret<<endl;
num=0;
}
}
ret=ret<<8;
ret+=num;
return ret;
}
- 求一个数组逆序对的个数
基于归并排序的思想统计逆序对:先把数组分割成子数组,再子数组合并的过程中统计逆序对的数目。统计逆序对时,先统计子数组内部的逆序对的数目,再统计相邻子数组的逆序对数目。
- 1个32位整数,计算二进制格式下有多少个1,不通过循环怎么做
通过n与n-1相& 清楚n最右边的1;
int BitCount(int n){
int c=0;//计数器
while(n){
n&=(n-1);
++c;
}
return c;
}
- 算法 最小生成树
Prim+ Kruskal算法
https://www.cnblogs.com/GHzz/p/9148279.html
- 比较两二叉树是否相同(手写代码)。现在我才明白,大概是在考我用递归怎么遍历树,我当时写的居然是以按层遍历的方式去遍历树,
递归
手写判断大小端的代码
https://blog.csdn.net/kit_9875507/article/details/44264663
大小端的本质就是不同的存储方式
大端模式:字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
小端模式:字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。
根据这个特性,假设我们初始化了一个int变量i为0x12345678,其地址为0x100,根据定义在小端模式下
0x100一个字节内的值为0x78,类推0x101=>0x56,0x102=>0x34,0x103=0x12,根据这个编程如下
- int checkSystem(void)
- {
- int i = 0x12345678;
- char *c = &i;
- return ((c[0] == 0x78) && (c[1] == 0x56) && (c[2] == 0x34) && (c[3] == 0x12));
- }
int main(void)
{
if(checkSystem())
printf("little endian ");
else
printf("big endian ");
return 0;
}
单链表找倒数第n个节点,说所有你能想到的方法。
方法一:遍历链表,记录链表的长度total,再次遍历链表,第total - N - 1个节点就是查找结果,需要遍历两次链表
方法二:使用两个指针,通过移动指针,遍历一次链表,p指针首先移动n-1步,然后p和q同时移动,直到p.next == null,此时q所指向的节点就是所求
怎么把一颗二叉树原地变成一个双向链表?
转换成有序双向链表:https://www.cnblogs.com/wanglei5205/p/8780086.html
怎么判断一个无符号的整数是不是2的n次方?
思路:一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他所有位都是0。把这个整数与这个整数减去1之后进行与运算,那么这个整数当中唯一的
1会变为0,这个整数也变为0;
- int atoi(char *str)?
- //atoi
- enum ={Invalid = 0, Valid};
- bool errno = Invalid;
- int atoi(const char * str)
- {
- long long num = 0; //point1:可能溢出,所以用long long存
- errno = Invalid;//初始设输入为不合法输入
- if (str!=nullptr && *str != ‘ ‘) //point2://考虑了空串和空指针
- {
- bool minus = false;
- if (*str == ‘+‘)
- {
- ++str;
- }
- else if (*str == ‘-‘)
- {
- ++str;
- minus = true;
- }
- if (*str!=‘ ‘) //只有符号,Invalid
- atoiCore(str, minus, num);
- }
- return (int)num; //已经检查过溢出,保证了num在int范围内
- }
- void atoiCore(const char *str, bool minus, long long &num)
- {
- while (‘ ‘ != *str)
- {
- if (*str >= ‘0‘ && *str <= ‘9‘)
- {
- num = num*10 + (*str - ‘0‘);
- ++str;
- if ((!minus && num > 0x7FFFFFFF)||(minus && (-num) < (signed int)0x80000000))//输入溢出
- {
- errno = Invalid;
- num = 0;
- return;
- }
- }
- else //输入非法字符
- {
- errno = Invalid;
- num = 0;
- return;
- }
- }
- if (minus)
- num = -num;
- errno = Valid; //标志输入合法
- }
- 栈的getmin()操作 O(1)
template <typename T> class NewStack
{
private :
std::stack<T> stack_data;
std::stack<T> stack_support;
public:
NewStack();
~NewStack();
void push( T value)
{
stack_data.push (value);
if (stack_support.size()==0 || stack_support.top()>value)
stack_support.push(value);
else:
stack_support.push (stack_support.top());
}
void pop()
{ if (stack_data.size()>0 && stack_support.size()>0)
{
stack_data.pop;
stack_support.pop;
}
}
T min()
{
if (stack_data.size()>0 && stack_support.size()>0)
{
return stack_support.top();
}
}
- 用栈实现队列,用队列实现栈?
使用队列实现栈:
class MyStack {
public:
MyStack() {
}
void push(int x) {
queue<int> temp; //建立一个辅助队列
while(q.empty() == false){ //将队列q中所有元素存入辅助队列中
temp.push(q.front());
q.pop();
}
q.push(x); //向队列中压入元素,放在队首
while(temp.empty() == false){ //逐个将辅助队列中的元素送回队列q中
q.push(temp.front());
temp.pop();
}
}
int pop() {
int a = q.front(); //将队列首元素返回
q.pop(); //删除队首
return a;
}
int top() {
return q.front(); //返回队首
}
bool empty() {
return q.empty();
}
private:
queue<int> q;
};
用栈实现队列
class MyQueue {
public:
MyQueue() {
}
void push(int x) { //将元素放到栈底
stack<int> temp;
while(s.empty() == false){
temp.push(s.top());
s.pop();
}
s.push(x);
while(temp.empty() == false){
s.push(temp.top());
temp.pop();
}
}
int pop() {
int a = s.top();
s.pop();
return a;
}
int peek() {
return s.top();
}
bool empty() {
return s.empty();
}
private:
stack<int> s, temp;
};
实现strstr函数
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
整数a和b,求a的b次方的最后三位数
.
- 算法题:将字符串转换成人民币大写(半小时后发邮箱)
https://blog.csdn.net/forlove_you/article/details/51248978
- 如何删除map中的奇数节点
遍历删除,考虑迭代器失效问题
- for(ITER iter=mapTest.begin();iter!=mapTest.end();++iter)
{ if(iter指向的元素是奇数)
mapTest.erase(iter);
} //错误,erase会让迭代器会失效!
- for(ITER iter=mapTest.begin();iter!=mapTest.end();)
{ if(iter指向的元素是奇数)
mapTest.erase(iter++);//正确,iter值传递之后,再++;
}
- for(ITER iter=mapTest.begin();iter!=mapTest.end();)
{ if(iter指向的元素是奇数)
iter=mapTest.erase(iter);//
erase() 成员函数返回下一个元素的迭代器
}
翻转数组和恢复翻转数组
找分界点:找分界点可以用一个指针来,遍历找到第一个下降的点,如果没有找到,说明数组已经是排好的。
二分法:
普通
int binary_search(int*arr,int l,int h,int key){
while (l <= h){
int m = l + (h - l) / 2;
if (arr[m] == key)
return m;
else if (arr[m] > key)
h = m - 1;
else l = m + 1;
}
return -1;
}
lower_bound
int binary_search(int*arr, int l, int h, int key){//找到第一个插入的位置
while (l <h){
int m = l + (h - l) / 2;
if (arr[m] >= key)
return h=m;
else l = m + 1;
}
}
排序
插入排序
void insert_sort(int* arr, int l, int h) {
for (int i = l + 1; i <= h; ++i)
for (int j = i; j > 0; --j){
if (arr[j] < arr[j - 1]){
iter_swap(&arr[j], &arr[j-1]);
}
}
}
快速排序
int partition(int* arry, int l, int h){
int pivot = arry[h];
while (true){
while (arry[l] < pivot) ++l;
while (arry[h] > pivot) --h;
if (!(l < h)) return l;
iter_swap(&arry[l], &arry[h]);
++l;
--h;
}
}
void quick_sort(int* arr, int l, int h) {
if (l >= h) return;
int m = partition(arr, l, h);
quick_sort(arr, l, m-1);
quick_sort(arr, m , h);
}
堆排序
void percDown(int* arr, int l, int h, int k) {
int child, tmp;
for (tmp = arr[k]; (k - l) * 2 + l + 1 <= h; k = child) {
child = (k - l) * 2 + l + 1;
if (child + 1 <= h && arr[child] < arr[child + 1]) ++child;
if (arr[child] > tmp) arr[k] = arr[child];
else break;
}
arr[k] = tmp;
}
void heap_sort(int* arr, int l, int h) {
for (int i = l + (h - l) / 2; i >= l; --i) {
percDown(arr, l, h, i);
}
for (int i = h; i >= l; --i) {
int tmp = arr[l];
arr[l] = arr[i];
arr[i] = tmp;
percDown(arr, l, i - 1, l);
}
}
归并排序
void merge_sort(int* arr, int l, int h) {
if (l == h) return;
int m = l + (h - l) / 2;
merge_sort(arr, l, m);
merge_sort(arr, m + 1, h);
int * tmp = new int[h - l + 1];
int i = l, j = m + 1, k = 0;
while (i <= m && j <= h) {
if (arr[i] <= arr[j]) tmp[k++] = arr[i++];
else tmp[k++] = arr[j++];
}
while (i <= m) tmp[k++] = arr[i++];
while (j <= h) tmp[k++] = arr[j++];
for (int i = l; i <= h; ++i) {
arr[i] = tmp[i - l];
}
delete []tmp;
}
冒泡排序
void bubble_sort(int* arr, int l, int h) {
for (int i = l; i <= h; ++i) {
for (int j = l; j <= h - i + l - 1; ++j) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
选择排序
void select_sort(int* arr, int l, int h) {
for (int i = l; i <= h; ++i) {
int id = i;
for (int j = i + 1; j <= h; ++j) {
if (arr[j] < arr[id]) {
id = j;
}
}
int tmp = arr[i];
arr[i] = arr[id];
arr[id] = tmp;
}
}
手写String
class String{
public: String(const char *str = NULL); //普通构造函数
String(const String &other); //拷贝构造函数
String & operator=(String &other) ; //赋值函数
~String(void); //析构函数
private: char* m_str;
};
//普通构造函数
String::String(const char* str){
if(str==NULL) //如果str为NULL,存空字符串{
m_str = new char[1]; //分配一个字节
*m_str = ‘