实际算法问题

1. 实现二叉树的层序遍历并输出

void layerTrace(BTreeNode *T){
if(T== nullptr)
	return;
BTreeNode *p=T;
queue<BTreeNode*>q;
q.push(p);
while(!q.empty()){
	p=q.front();
	q.pop();
	cout<<<<p->data;
	if(p->left!= nullptr)	q.push(p->left);
	if(p->right!= nullptr)	q.push(p->right);
}
}

2. 怎么判断一个数是二的倍数

取余

3. 怎么求一个数中有几个1

逐位除十取余、位的与1做异或运算

4. 如果在只修改一个字符的前提下,使代码输出20个hello?

5. n个整数的无序数组,找到每个元素后面比它大的第一个数,要求时间复杂度为O(N)

组合使用:vector、stack

if(s.empty()||num[s.top()]>=num[i]) 
{	
	s.push(i++);
}
else
{ 
	res[s.top()]=num[i]; s.pop(); 
}

6. Top(K)问题。求前K大的数

  • 直接全部排序(只适用于内存够的情况)
  • 快速排序的变形 (只使用于内存够的情况)这种方法类似于快速排序,首先选择一个划分元,将比这个划分元大的元素放到它的前面,比划分元小的元素放到它的后面,此时完成了一趟排序。如果此时这个划分元的序号index刚好等于K,那么这个划分元以及它左边的数,刚好就是前K个最大的元素;如果index > K,那么前K大的数据在index的左边,那么就继续递归的从index-1个数中进行一趟排序;如果index < K,那么再从划分元的右边继续进行排序,直到找到序号index刚好等于K为止。再将前K个数进行排序后,返回Top K个元素。这种方法就避免了对除了Top K个元素以外的数据进行排序所带来的不必要的开销。
  • 最小堆法:先读取前K个数,建立一个最小堆。然后将剩余的所有数字依次与最小堆的堆顶进行比较,如果小于或等于堆顶数据,则继续比较下一个;否则,删除堆顶元素,并将新数据插入堆中,重新调整最小堆。当遍历完全部数据后,最小堆中的数据即为最大的K个数。
  • 分治法:将全部数据分成N份,前提是每份的数据都可以读到内存中进行处理,找到每份数据中最大的K个数。此时剩下NK个数据,如果内存不能容纳NK个数据,则再继续分治处理,分成M份,找出每份数据中最大的K个数,如果M*K个数仍然不能读到内存中,则继续分治处理。直到剩余的数可以读入内存中,那么可以对这些数使用快速排序的变形或者归并排序进行处理。
  • Hash法:如果这些数据中有很多重复的数据,可以先通过hash法,把重复的数去掉。这样如果重复率很高的话,会减少很大的内存用量,从而缩小运算空间。处理后的数据如果能够读入内存,则可以直接排序;否则可以使用分治法或者最小堆法来处理数据。

7. 求第k大的数的方法

  • 1.快速排序,时间复杂度最快为O(nlogn)
  • 2.堆排序,建立最大堆,然后调整堆,直到获得第k个元素,其时间复杂度为O(n+klogn)
  • 3.利用哈希表统计数组中各元素出现的次数,然后利用计数排序的思想,线性从大到小扫描过程中,前面有k-1个数则为第k大的数
  • 4.利用快排思想,从数组中随机选择一个数i,然后将数组分成两部分Dl,Dr,Dl的元素都小于i,Dr的元素都大于i。然后统计Dr元素个数,如果Dr元素个数等于k-1,那么第k大的数即为k,如果Dr元素个数小于k,那么继续求Dl中第k-Dr大的元素;如果Dr元素个数大于k,那么继续求Dr中第k大的元素。

当有相同元素的时候——利用哈希表统计数组中个元素出现的次数,然后利用计数排序的思想,线性从大到小扫描过程中,前面有k-1个数则为第k大的数,平均情况下时间复杂度为O(n)

8. 二叉树序列化反序列化

序列化:必须保存一个中序遍历结果,然后外加一个前序或者后序遍历结果
反序列化:根据两次遍历生成的结果恢复二叉树,代码如下(前序和中序)

TreeNode* helper(vector<int>pre,int startPre,int endPre,vector<int>in,int startIn,int endIn){
	if(startPre>endPre||startIn>endIn)
		return nullptr;
	TreeNode * root=new TreeNode(pre[startPre]);
	for(int i=startIn;i<=endIn;++i){
		if(in[i]==pre[startPre]){
			root->left=helper(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
			root->right=helper(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
			break;
		}
	}
	return root;
}

TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin){
	TreeNode *root=helper(pre,0,pre.size()-1,vin,0,vin.size()-1);
	return root;
}

9. 两个栈实现一个队列

class Solution{
public:
	void push(int node) {
		stack1.push(node);
	}
	int pop() {
		if(stack2.size()!=0){
			int tmp = stack2.top();
			stack2.pop();
			return tmp;
		}
		else{
			while(stack1.size()!=0){
				int tmp = stack1.top();
				stack1.pop();
				stack2.push(tmp);
		}
		return pop();
	}
}

private:
	stack<int> stack1;
	stack<int> stack2;
};

10. 一个长度为N的整形数组,数组中每个元素的取值范围是[0,n-1],判断该数组否有重复的数。

把每个数放到自己对应序号的位置上,如果其他位置上有和自己对应序号相同的数,那么即为有重复的数值。时间复杂度为O(N),同时为了节省空间复杂度,可以在原数组上进行操作,空间复杂度为O(1)

11. 快速排序

划分函数:
int partition(vector<int> &data, int left, int right){
	int pivot=a[left]; 
	while(left<right&&pivot<=a[right]) right--;
	if(left<right) a[left++]=a[right];
	while(left<right&&pivot>a[left]) left++;
	if(left<right) a[right--]=a[left];
	a[left]=pivot;
	return left;
}

12. 用两个栈实现一个队列、用两个队列实现一个栈

栈:括号匹配;用于计算后缀表达式,等数据结构中
队列:应用于类似现实生活中一些排队问题,例如Linux中我们学习进程间通信的时候,有一种通信方式就是“消息队列”等。

用两个栈实现队列——定义两个栈为“stack1”和“stack2”,栈1只用来插入数据,栈2用来删除数据。当且仅当栈stack2为空时,才插入stack1中的元素。

用两个队列实现一个栈——定义两个队列q1和q2,插入(若两个队列为空,插入q1;若其中一个队列不为空,插入到该队列末尾)删除(将非空的那个队列除了队列尾元素之外的所有元素按顺序插入到另一个队列,然后删除队列尾元素,使得队列为空)

13. 实现LRU(最少最近使用算法)

方法:双向链表、hashmap

双向链表读取、插入的时间复杂度都是O(n), 但是如果知道插入位置,则可以实现O(1)实现。hash存key对应的数据在双向链表中的位置,就可以完成该功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值