阿里巴巴内推编程测验题目

题目:


思路:

在网上跟大家交流后,才知道自己漏看了题目,后来想了想,现将思路贴出来,供大家交流

目的:最多可以取出多少个能够组成嵌套集

如果存在一个子嵌套集,而新增加的一个二段模式与子嵌套集的某个二段模式冲突(不相互嵌套),它虽然不能加入该嵌套子集,
但是它却可以和该子集中不冲突的其他二段模式组成子集,所以很难处理。因此,从这个角度来思考,太过于复杂。

从上面的思路中我们可以得到一些有用的结论:针对存在的一个子嵌套集,新的二段模式的加入,可以生成新的子嵌套集,也就
是造成分支;进一步我们可以认为,一个二段模式最多可以生成一个分支,而且一个分支主要是因为某个二段模式与其他嵌套集
冲突造成的,也就是一个二段模式可以对应一个嵌套集;N个二段模式最多组成N个独立的嵌套集。


算法流程:
1、初始N个嵌套集,分别包含编号0~N-1二段模式
2、针对某个二段模式,遍历查看是否可以满足加入嵌套集的条件(两两相互嵌套,而且该二段模式之前不存在)
   满足的话,将其加入
3、找出最大的嵌套集

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <deque>
#include <cassert>
#include <map>
#include <algorithm>

using namespace std;

class Interval
{
public:
	explicit Interval(size_t left, size_t right)
		: mLeft(left),
		mRight(right)
	{
		assert(left <= right);
	}

	size_t left() const
	{
		return mLeft;
	}

	size_t right() const
	{
		return mRight;
	}
	/添加
	Interval(){};
	Interval(const Interval &a);
	Interval &operator = (const Interval &a);
	
private:
	size_t mLeft;
	size_t mRight;
};

//
Interval::Interval(const Interval &a)
{
	this->mLeft = a.mLeft;
	this->mRight = a.mRight;
}
Interval &Interval::operator =(const Interval &a)
{
	this->mLeft = a.mLeft;
	this->mRight = a.mRight;
	return *this;
}
/

inline bool operator<(const Interval& a, const Interval& b)
{
	return a.right() < b.left();
}

class TwoInterval
{
public:
	explicit TwoInterval(const Interval& left, const Interval& right)
		: mLeft(left),
		mRight(right)
	{
		assert(left < right);
	}

	const Interval& left() const
	{
		return mLeft;
	}

	const Interval& right() const
	{
		return mRight;
	}
	/添加
	TwoInterval(){};
	TwoInterval(const TwoInterval &a);
	TwoInterval &operator = (const TwoInterval &a);
	

private:
	Interval mLeft;
	Interval mRight;
};
//
TwoInterval::TwoInterval(const TwoInterval &a)
{
	this->mLeft = a.mLeft;
	this->mRight = a.mRight;
}
TwoInterval &TwoInterval::operator=(const TwoInterval &a)
{
	this->mLeft = a.mLeft;
	this->mRight = a.mRight;
	return *this;
}
/


inline bool within(const TwoInterval& a, const TwoInterval& b)
{
	return b.left() < a.left() && a.right() < b.right();
}

void input(vector<TwoInterval>& twos)
{
	int m = 0;
	{
		string s;
		getline(cin, s);
		istringstream is(s);
		is >> m;
	}
	for (int i = 0; i < m; ++i) {
		string s;
		getline(cin, s);
		istringstream is(s);
		size_t a, b, c, d;
		is >> a >> b >> c >> d;
		Interval left(a, b);
		Interval right(c, d);
		twos.emplace_back(left, right);
	}
}

// ====== 填入你自己的逻辑 ========

/********************************/
/*
目的:最多可以取出多少个能够组成嵌套集

思路:

如果存在一个子嵌套集,而新增加的一个二段模式与子嵌套集的某个二段模式冲突(不相互嵌套),它虽然不能加入该嵌套子集,
但是它却可以和该子集中不冲突的其他二段模式组成子集,所以很难处理。因此,从这个角度来思考,太过于复杂。

从上面的思路中我们可以得到一些有用的结论:针对存在的一个子嵌套集,新的二段模式的加入,可以生成新的子嵌套集,也就
是造成分支;进一步我们可以认为,一个二段模式最多可以生成一个分支,而且一个分支主要是因为某个二段模式与其他嵌套集
冲突造成的,也就是一个二段模式可以对应一个嵌套集;N个二段模式最多组成N个独立的嵌套集。

算法流程:
1、初始N个嵌套集,分别包含编号0~N-1二段模式
2、针对某个二段模式,遍历查看是否可以满足加入嵌套集的条件(两两相互嵌套,而且该二段模式之前不存在)
   满足的话,将其加入
3、找出最大的嵌套集

*/
/********************************/

inline bool operator==(const Interval& a, const Interval& b)
{
	return (a.right() == b.right()) && (a.left() == b.left());
}


inline bool operator==(const TwoInterval& a, const TwoInterval& b)
{
	return (a.right() == b.right()) && (a.left() == b.left());
}

bool confl(const TwoInterval& a, const TwoInterval& b)
{
	if (!(within(a, b) || within(b, a))) return true;
	if (a == b) return true;
	return false;
}


bool add(vector<TwoInterval> &a, TwoInterval b)
{
	for (TwoInterval ti : a)
	{
		if (confl(ti,b))
		{
			
			return false;
		}
	}
	a.push_back(b);
	return true;
}


int intussusception(vector<TwoInterval>& two2)
{
	int len = two2.size();
	if (len < 2) return len;
	int max = 0;
	vector<vector<TwoInterval> > res(len);
	for (int i = 0; i < len; i++)
	{
		res[i].push_back(two2[i]);
	}
	for (int i = 0; i < len; i++)
	{
		for (int j = 0; j < len; j++)
		{
			add(res[j], two2[i]);
		}
	}
	for (int i = 0; i < len; i++)
	{
		if (res[i].size()>max)
		{
			max = res[i].size();
		}
	}
	return max;
}

// ====== 结束 ========

int main() {
	vector<TwoInterval> twos;
	input(twos);

	cout << intussusception(twos) << endl;

	return 0;
}


  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值