【CODE】面试基础代码

单例模式

#include<iostream>
#include<atomic>
#include<mutex>
using namespace std;
/*一个类只有一个实例,提供这个实例的全局访问点,
应用程序的日志应用,一般对都是单例模式实现,只能有一个实例去操作文件*/
/*线程不安全版本*/
class Singleton {
public:
	static Singleton* getinstance() {
		if (m_instance == NULL) {
			m_instance = new Singleton();
		}
		return m_instance;
	}
private:
	Singleton();//私有构造函数,不允许使用者自己生成对象
	Singleton(const Singleton& other);
	static Singleton* m_instance;//静态成员变量
};
Singleton* Singleton::m_instance = NULL;//静态成员初始化
/*上述,将构造函数和拷贝构造函数都设为私有,而且采用了延迟初始化的方式,
在第一调用getinstance后才会生成对象,会产生两个对象。*/

/*线程安全,锁的代价高*/
Singleton* Singleton::getinstance(){
	Lock lock;//伪代码,加锁
	if (m_instance == NULL) {
		m_instance = new Singleton();
	}
	return m_instance;
}
/*上述,性能不高,因为每次调用getinstance都会加锁,而这个步骤只有在第一次new对象时才需要*/

/*双检查锁,由于内存读写失序,会导致不安全*/
//双检查锁,但由于内存读写reorder不安全
Singleton* Singleton::getinstance() {
	//先判断是不是初始化了,如果初始化过,就再也不会使用锁了
	if (m_instance == nullptr) {
		Lock lock; //伪代码
		if (m_instance == nullptr) {
			m_instance = new Singleton();
		}
	}
	return m_instance;
}
/*上述,m_instance = new Singleton();有三步:(1)分配一个Singleton类型的对象需要的缓存
(2)在分配的内存处构造Singleton类型的对象(3)把分配的内存地址赋值给指针m_instance
但是后两步的执行不一定是按照顺序的。*/

/*c++11引入了原子操作atomic,表示不能失序*/

/*c++11最新:*/
class Singleton {
public:
	// 注意返回的是引用。
	static Singleton& getInstance() {
		static Singleton m_instance;  //局部静态变量
		return m_instance;
	}
private:
	Singleton(); //私有构造函数,不允许使用者自己生成对象
	Singleton(const Singleton& other);
};

/*饿汉模式:在单例类定义的时候就进行实例化,
由于要线程同步,所以在访问量较大时,或者可能访问的线程较多时,采用饿汉实现*/
class Singleton {
public:
	static Singleton * getinstance();
private:
	Singleton(const Singleton&) {};
	Singleton & operator=(const Singleton&) {};
	Singleton() {};
	static Singleton* instance;
};
Singleton* Singleton::instance = new Singleton();
Singleton* Singleton::getinstance() {
	return instance;
}

实现strcpy、strlen

#include"pch.h"
#include<iostream>
#include<vector>
using namespace std;
char * strcpy0(char *dst, const char * src) {
	if (dst == NULL || src == NULL) return NULL;
	char *res = dst;//保存原始dst的地址
	while ((*dst++ = *src++) != '\0');
	return res;
}
int getstrlen(const char * src) {
	int len = 0;
	if (src == NULL) return 0;
	while ((*src++) != '\0') len++;
	return len;
}
int main() {
	char src[] = "hello world";
	char dst[20] = { 0 };
	char* res = strcpy0(dst, src);
	cout << res << endl;
	cout << getstrlen(res) << endl;
	return 0;
}

单链表反转(递归与非递归) 

#include"pch.h"
#include<iostream>
#include<vector>
using namespace std;
typedef struct Node {
	int value;
	Node *next;
	Node(int x) :value(x), next(NULL) {}
}Node;
Node *reverse(Node *head) {
	Node *tmp = head, *res = head;
	head = head->next; tmp->next = NULL;
	while (head->next) {
		Node *tmpp = head->next;
		head->next = tmp;
		tmp = head;
		head = tmpp;
	}
	head->next = tmp;
	return head;
}
Node *reverse0(Node *head) {
	if (head == NULL || head->next == NULL) return head;
	Node *newhead = reverse0(head->next);
	head->next->next = head;
	head->next = NULL;
	return newhead;
}
int main() {
	vector<int> nums = { 1,2,3,4,5 };
	Node *node1 = new Node(nums[0]);
	Node *node2 = new Node(nums[1]);
	Node *node3 = new Node(nums[2]);
	Node *node4 = new Node(nums[3]);
	Node *node5 = new Node(nums[4]);
	node1->next = node2; node2->next = node3;
	node3->next = node4; node4->next = node5;
	node5->next = NULL;
	node1 = reverse0(node1);
	while (node1) {
		cout << node1->value << " ";
		node1 = node1->next;
	}
	return 0;
}

n!后面0的个数

#include"pch.h"
#include<iostream>
#include<vector>
using namespace std;
/*n!后面0的个数
找规律的数学问题,两个大数字相乘,可以拆分成多个质数相乘,
质数相乘结尾是0的,只有2*5,
所以两个数相乘,尾数0的个数其实就是依赖于2和5因子的个数,
因为每两个连续的数字就有一个2,所以只需要关心5因子的个数。
如何计算一个n!中5的个数?
把5的倍数都挑出来: 令n! = (5*K) * (5*(K-1)) * (5*(K-2)) * ... * 5 * A,
其中A就是不含5因子的数相乘结果,n = 5*K + r(0<= r <= 4)。
假设f(n!)是计算阶乘n!尾数0的个数,而g(n!)是计算n!中5因子的个数,
那么就会有如下公式:
f(n!) = g(n!) = g(5^K * K! * A) = K + g(K!) = K + f(K!),其中K=n / 5(取整数)。
很显然,当0 <= n <= 4时,f(n!)=0。*/
int getN_1(int n) {
	if (n < 5) return 0;
	return (n / 5) + getN_1(n / 5);
}
int main() {
	cout << getN_1(1000) << endl;
	return 0;
}

判断平衡二叉树

#include<iostream>
using namespace std;
//判断平衡二叉树
typedef struct TreeNode{
    int value;
    TreeNode *left,*right;
    TreeNode(int x):value(x),left(NULL),right(NULL){}
}
int height(TreeNode *root,bool &res){
    if(root==NULL) return 0;
    int left=height(root->left,res)+1;
    int right=height(root->right,res)+1;
    if(left-right>=2 || right-left>=2) res=0;
    return max(left,right);//这棵树的高度,左节点、右节点的更高的
}
bool isBalance(TreeNode *root){
    bool res=1;
    height(root,res);
    return res;
}
int main(){
    ...
}

最近公共祖先节点

#include<iostream>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
//最近公共祖先节点
typedef struct TreeNode{
    int value;
    TreeNode *left,*right;
    TreeNode(int x):value(x),left(NULL),right(NULL){}
};
//如果是二叉搜索树
TreeNode* LCA1(TreeNode *root,TreeNode *a,TreeNode *b){
    if(root==NULL||a==NULL||b==NULL) return NULL;
    if(a->value==root->value || b->value==root->value) return root;
    //上条语句,相当于说a是b的祖先,或者b是a的祖先
    TreeNode *l=LCA1(root->left,a,b);//到左子树中找
    TreeNode *r=LCA1(root->right,a,b);//到右子树中找
    if(l&&r) return root;//如果左子树有其中一个节点,右子树有另一个节点,root就是所求
    return l==NULL?r:l;//如果返回的左子树为空,那么LCA在右子树上
}//a和b分别是两个需要查找的树节点,
//后序遍历非递归方法找LCA,后序遍历非递归,栈中元素就是从根到达该节点的路径
TreeNode *LCA2(TreeNode *root, TreeNode *a, TreeNode *b) {
	if (root == NULL) return root;
	stack<TreeNode*> st;
	vector<TreeNode *> vec1, vec2;
	bool tag1 = false;
	bool tag2 = false;
	TreeNode *pre = NULL;
	while (root || !st.empty()) {
		if (tag1 && tag2) break;
		while (root) {
			if (tag1 && tag2) break;
			if (root == a) {
				tag1 = true;
				stack<TreeNode*> tmp = st;
				vec1.push_back(root);
				while (!tmp.empty()) {
					vec1.push_back(tmp.top());
					tmp.pop();
				}
				
			}
			if (root == b) {
				tag2 = true;
				stack<TreeNode*> tmp = st;
				vec2.push_back(root);
				while (!tmp.empty()) {
					vec2.push_back(tmp.top());
					tmp.pop();
				}
			}
			st.push(root);
			root = root->left;
		}
		root = st.top();
		if (root->right == NULL || root->right == pre) {
			st.pop();
			pre = root;
			root = NULL;
		}
		else {
			root = root->right;
		}
	}
	reverse(vec1.begin(), vec1.end());
	reverse(vec2.begin(), vec2.end());
	TreeNode *res = NULL;
	for (int i = 0, j = 0; i < vec1.size() && j < vec2.size();i++,j++) {
		if (vec1[i]->value == vec2[i]->value) {
			res = vec1[i];
			continue;
		}
		else if (vec1[i]->value != vec2[i]->value) {
			return vec1[i - 1];
		}
	}
	return res;
}
//后序遍历非递归:
void BacOrder(TreeNode* root){
    stack<TreeNode*> st;
    TreeNode *pre=NULL;
    while(root|| !st.empty()){
        while(root){
            st.push(root);
            root=root->left;
        }
        root=st.top();
        if(root->right==NULL || root->right==pre){
            st.pop();
            cout<<root->value<<endl;
            pre=root;
            root=NULL;
        }else{
            root=root->right;
        }
    }
    return ;
}
int main(){
    TreeNode *root=new TreeNode (10);
    TreeNode *node1=new TreeNode (1);
    TreeNode *node2=new TreeNode (2);
    TreeNode *node3=new TreeNode (3);
    TreeNode *node4=new TreeNode (4);
    TreeNode *node5=new TreeNode (5);
    root->left=node1;root->right=node2;
    node1->left=node3;node2->left=node4;node2->right=node5;
    //BacOrder(root);
    TreeNode *res=LCA2(root,node2,node5);
    cout<<res->value<<endl;
    return 0;
    
}

多线程

三个线程A、B、C,循环输出ABCABC。。。。。。

#include"pch.h"
#include<iostream>
#include<stack>
#include<vector>
#include<mutex>
#include<thread>
using namespace std;
//三个线程A、B、C,循环输出ABCABC。。。。。。
int main() {
	mutex mtex;
	int cnt = 0;
	auto work = [&](char ch, int num) {
		while (num--) {
			while (ch != cnt + 'A') this_thread::yield();
            //this_thread::yield();可以将本线程时间片放弃,允许其他线程运行
			unique_lock<mutex> lk(mtex);
			cout << ch;
			cnt = (cnt + 1) % 3;
			lk.unlock();
		}
	};//lambda,[&]表示引用的外部变量可以被改变
	thread t1(work, 'A', 10);
	thread t2(work, 'B', 10);
	work('C', 10);
	t1.join();
	t2.join();
	return 0;
}

输入一个正数n,输出所有和为n连续正数序列。

#include "pch.h"
#include <iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
/*题目:
输入一个正数n,输出所有和为n连续正数序列。
例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6和7-8。
解决:
结果一定是2个相连的数、3个相连的数、4个、5个等等。
那么可以把这个数n除以i(i为2,3,4...代表相连的数的个数),
得到的这些相邻的数的大概平均值,如当 n = 15、i = 2 时,n / i = 7,
这代表如果有两个相邻的数的和是15,那么它们的大概平均值是7;
i = 3 时,n / i = 5,代表三个连续的数的大概平均值是5,那么这三个数是4,5,6。
大概平均值是因为整数除引起的。
所以可以由相连数的个数得到这些数的大概平均值,从而可以得到这么多个相连的数,
判断它们的和是否满足,不满足再看下一个相邻数的个数,直到相连数的第一个到了1。

或者使用公式:
Suppose n = i+(i+1)+...+(j-1)+j, then n = (i+j)(j-i+1)/2 = (j*j-i*i+i+j)/2 
=> j^2+j+(i-i^2-2n) = 0 => j = (sqrt(1-4(i-i^2-2n))-1)/2 
=> j = (sqrt(4i^2+8n-4i+1)-1)/2.
*/
int main() {
	int n;
	cin >> n;
	vector<vector<int> > res;
	for (int i = 2;i<=sqrt(2*n); i++) {
		int tmp = n / i;
		if (i % 2 == 0) {
			int sum = (tmp * 2 + 1)*(i / 2);
			if (sum != n) continue;
		}
		else {
			int sum = 2 * tmp*(i / 2) + tmp;
			if (sum != n) continue;
		}
		vector<int> ans;
		int sum = 0;
		for (int j = tmp - (i - 1) / 2;; j++) {
			sum += j;
			ans.push_back(j);
			if (sum == n) {
				res.push_back(ans);
				break;
			}
			else if (sum > n) break;
		}
	}
	for (int i = 0; i < res.size(); i++) {
		for (int j = 0; j < res[i].size(); j++) cout << res[i][j] << " ";
		cout << endl;
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值