有道毒鸡汤:My motto is:Contented with little,yet wishing for more.我的座右铭是:为一点点感到满足,但希望获得更多。
国庆开始看的《剑指offer》,还有最后几题
========================================================================================
约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1。
因为是一个圈,而且要从其中删除数据,所以首先想到的是用循环链表来解决,因为最近在学校C++,就直接用模板库里的双向链表了。
int LastRemaining_Solution1(unsigned int n, unsigned int m)
{
if(n < 1 || m < 1)
return -1;
unsigned int i = 0;
list<int> numbers;
for(i = 0; i < n; ++ i)
numbers.push_back(i);
list<int>::iterator current = numbers.begin();
while(numbers.size() > 1)
{
for(int i = 1; i < m; ++ i)
{
current ++;
if(current == numbers.end())
current = numbers.begin();
}
list<int>::iterator next = ++ current;
if(next == numbers.end())
next = numbers.begin();
-- current;
numbers.erase(current);
current = next;
}
return *(current);
}
因为对C++不熟悉,看这代码时,我产生了疑问,下面为什么要这样了
if(current == numbers.end())
current = numbers.begin();
if(next == numbers.end())
next = numbers.begin();
找了找才发现begin指向的是链表的第一个元素,但是end并不是指向链表的最后一个元素,而是最后一个元素之后,所以才有上面的代码,这样才能构成一个循环链表,下面是list个成员函数的作用,一起学习学习吧(关于约瑟夫问题,剑指offer里面还提出了一种更有效率的方法,感兴趣的可以去找找看,里面涉及找被删除数字的规律,解释比较麻烦)
Lists将元素按顺序储存在链表中. 与 向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢.
STL中 end()指向的总是无效值,取值都用迭代器,用法跟指针差不多。
assign() 给list赋值
back() 返回最后一个元素
begin() 返回指向第一个元素的迭代器
clear() 删除所有元素
empty() 如果list是空的则返回true
end() 返回末尾的迭代器 (返回指向链表最后一个元素之后的迭代器。)
erase() 删除一个元素
front() 返回第一个元素
get_allocator() 返回list的配置器
insert() 插入一个元素到list中
max_size() 返回list能容纳的最大元素数量
merge() 合并两个list
pop_back() 删除最后一个元素
pop_front() 删除第一个元素
push_back() 在list的末尾添加一个元素
push_front() 在list的头部添加一个元素
rbegin() 返回指向第一个元素的逆向迭代器
remove() 从list删除元素
remove_if() 按指定条件删除元素
rend() 指向list末尾的逆向迭代器
resize() 改变list的大小
reverse() 把list的元素倒转
size() 返回list中的元素个数
sort() 给list排序
splice() 合并两个list
swap() 交换两个list
unique() 删除list中重复的元素