基础题:
判断链表是否带环?
思路:
代码实现:
bool HaveLoop(ListNode* l)
{
if(l == NULL)
return false;
ListNode* fast = l;
ListNode* slow = l;
while(fast && fast->_next)
{
fast = (fast->_next)->_next;
slow = slow->_next ;
if(fast == slow)
return true;
}
return false;
}
若带环求环的长度?
思路:
代码:
ListNode* MeetNode(ListNode* l) //相遇结点
{
if(l == NULL)
return NULL;
ListNode* fast = l;
ListNode* slow = l;
while(fast && fast->_next)
{
fast = (fast->_next)->_next;
slow = slow->_next ;
if(fast == slow)
return slow;
}
return NULL;
}
size_t LoopLength(ListNode* l) //求环的长度
{
ListNode* meet = MeetNode(l);
ListNode* cur = meet->_next ;
size_t length = 1;
while(cur != meet)
{
cur = cur->_next ;
++length;
}
return length;
}
若带环求环的入口点?并计算以上每个问题的时间复杂度?
思路:
代码实现:
ListNode* Entrance(ListNode* l) //入口点
{
size_t length = LoopLength(l);
ListNode* fast = l;
ListNode* slow = l;
while(fast && length)
{
fast = fast->_next;
--length;
}
while(fast)
{
fast = fast->_next;
slow = slow->_next;
if(fast == slow)
return fast;
}
return NULL;
}
附加题:
1、设计一个不能被继承的类
思路 :根据继承的性质可知,子类对象的构造函数是合成的,即由父类的构造函数合成的;因此将一个类的构造函数定义成私有时,这个类将不能继承;
2、只能在堆上生成对象:将析构函数设置为私有。
原因:C++是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象。
原因:C++是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象。
#include<iostream>
using namespace std;
class A
{
public:
A(int a)
:_a(a)
{
}
private:
~A()
{
cout<<" "<<endl;
}
private:
int _a;
};
int main()
{
//A a(1);
A* p = new A(1);
}
执行A a(1)的结果图:(在栈上创建对象时)
思路:一个类在实例化出一个对象时,会调用该类的构造函数,只能在堆上创建,那这个对象一定是通过new出来的;
方法:将该类的构造函数定义成私有或者保护,然后在该类中定义一个静态的成员函数用于new一个对象,在实例化对象时调用该静态函数(注意:new出来的对象一定要delete,防止内存泄漏,在析构函数中delete);
3、只能在栈上生成对象:方法:将operator new函数和operator delete函数定义成私有;
原因:在堆上生成对象,使用new关键词操作,其过程分为两阶段:第一阶段,使用new在堆上寻找可用内存,分配给对象;第二阶段,调用构造函数生成对象。
将new操作设置为私有,那么第一阶段就无法完成,就不能够再堆上生成对象。