题目描述
请编写一个程序,按升序对栈进行排序(即最大元素位于栈顶),要求最多只能使用一个额外的栈存放临时数据,但不得将元素复制到别的数据结构中。
给定一个int[] numbers(C++中为vector<int>),其中第一个元素为栈顶,请返回排序后的栈。请注意这是一个栈,意味着排序过程中你只能访问到第一个元素。
测试样例:
[1,2,3,4,5]
返回:[5,4,3,2,1]
思路:迫于题目要求,只能使用两个栈,可以想到一个栈存放有序数列,另一个栈buffer存放无序的其它数列,,可以另外定义一个整形变量tmp,用排序时的数据交换,
排序:
》》1 ,从buffer中取出(pop)一个元素,放到tmp,和有序栈栈顶的元素比较(每次只能访问栈的栈顶元素);若小于栈顶元素,则有序栈栈顶元素出栈 到 buffer,同时记下出栈元素个数,依次继续比较,直到小于不成立,
》》2,根据出栈元素个数,将buffer中元素 返回到有序栈,一次循环结束
Java
import java.util.*;
public class TwoStacks {
public ArrayList<Integer> twoStacksSort(int[] numbers) {
// write code here
if(numbers == null && numbers.length==0)return null;
ArrayList<Integer> arrlist=new ArrayList<Integer>(numbers.length);
Stack<Integer> sta = new Stack<Integer>();
Stack<Integer> buffer = new Stack<Integer>();
int i=0,tmp=0;
while( i < numbers.length )
{
buffer.push(numbers[i]);
i++;
}
while(buffer.isEmpty()!=true){
tmp = buffer.pop();//一定要pop 不能peek()
int count=0;
//while(tmp < sta.peek()&&sta.isEmpty()!=true)//这样会出异常,一定要判断在前,比较在后
while(sta.isEmpty() != true && tmp < sta.peek())
{
buffer.push(sta.peek());
sta.pop();
count++;//出栈元素数 统计,,然后依此数逐个返回原栈
}
sta.push(tmp);
for(i = 0;i < count;i++) {
sta.push(buffer.pop());
}
}
for( i = 0;i < numbers.length;i++){
arrlist.add(sta.pop());
// sta.pop();
}
return arrlist;
}
}
C/C++
思路一样,,只是采取了vector 容器的方式,vector顺序容器的基本操作,访问、添加、删除等。push_back(t) ,push_front(t) , back(),pop_back(),,等
说明
vector是一种动态数组,是基本数组的类模板。其内部定义了很多基本操作。
#include 注意:头文件没有“.h”
构造:
这个构造函数还有一个可选的参数,这是一个类型为T的实例,描述了各个向量种各成员的初始值;
如:vectorv2(init_size,0); 如果预先定义了:intinit_size;他的成员值都被初始化为0;
· 复制构造函数,构造一个新的向量,作为已存在的向量的完全复制;
如:vectorv3(v2);
· 带两个常量参数的构造函数,产生初始值为一个区间的向量。区间由一个半开区间first,last来指定。
如:vectorv4(first,last) vector v1;
vectorv2(init_size,0);
vectorv3(v2);
方法:
c.assign(beg,end)c.assign(n,elem) 将(beg; end)区间中的数据赋值给c。将n个elem的拷贝赋值给c。
c. at(idx) 传回索引idx所指的数据,如果idx越界,抛出out_of_range。
c.back() 传回最后一个数据,不检查这个数据是否存在。
c.begin() 传回迭代器中的第一个数据地址。
c.capacity() 返回容器中数据个数。
c.clear() 移除容器中所有数据。
c.empty() 判断容器是否为空。
c.end() // 指向迭代器中末端元素的下一个,指向一个不存在元素。
c.erase(pos)// 删除pos位置的数据,传回下一个数据的位置。
c.erase(beg,end) 删除[beg,end)区间的数据,传回下一个数据的位置。
c.front() 传回第一个数据。
get_allocator 使用构造函数返回一个拷贝。
c.insert(pos,elem)// 在pos位置插入一个elem拷贝,传回新数据位置
c.insert(pos,n,elem)// 在pos位置插入n个elem数据,无返回值
c.insert(pos,beg,end)// 在pos位置插入在[beg,end)区间的数据。无返回值
c.max_size() 返回容器中最大数据的数量。
c.pop_back() 删除最后一个数据。
c.push_back(elem) 在尾部加入一个数据。
c.rbegin() 传回一个逆向队列的第一个数据。
c.rend() 传回一个逆向队列的最后一个数据的下一个位置。
c.resize(num) 重新指定队列的长度。
c.reserve() 保留适当的容量。
c.size() 返回容器中实际数据的个数。
c1.swap(c2)// 将c1和c2元素互换
参考链接
class TwoStacks {
public:
vector<int> twoStacksSort(vector<int> numbers) {
// write code here
vector<int> forSort;
if(numbers.size() <= 1) return numbers;
forSort.push_back(numbers.back());
numbers.pop_back();
while(numbers.size() > 0)
{
int temp = numbers.back();
numbers.pop_back();
int count = 0; // 出栈元素的数量
while(!forSort.empty() && temp < forSort.back()){
numbers.push_back(forSort.back());
forSort.pop_back();
count++;
}
forSort.push_back(temp);
for(int i = 0 ; i < count ;i ++ ){
forSort.push_back(numbers.back());//不可以直接pop_back(),,类似于C里面的pop()
numbers.pop_back();
}
}
reverse(forSort.begin(),forSort.end());
return forSort;
}
};
这个是网上的另外一种解法,,可以减少循环次数,,
public ArrayList<Integer> twoStacksSort(int[] numbers) {
/*
* 思路:
* 只用两个栈排序,一个是有序的asc,另一个是无序的buffer就可以实现对一个栈的排序。如何有序,当原始栈只有一个时就有序了
* numbers中第一个为栈顶
* 主要是解决buffer栈顶元素放在asc的位置
* 1. buffer栈顶大于等于asc栈顶或asc空
* 直接放
* 2. buffer栈顶小于asc栈顶
* buffer栈顶值出栈,临时变量存放buffer栈顶值
* 循环从asc中拿出值放到buffer直至asc空或满足1条件
*/
if(numbers == null || numbers.length == 0){
return null;
}
int length = numbers.length;
ArrayList<Integer> res = new ArrayList<Integer>(length);
Stack<Integer> buffer = new Stack<Integer>();
Stack<Integer> ascStack = new Stack<Integer>();
//初始状态,buffer中放了length-1个与numbers逆序的数串,asc只剩栈底元素
for(int i = 0; i < length-1; i++){
buffer.push(numbers[i]);
}
ascStack.push(numbers[length-1]);
//排序
int bufTop = 0;
while(buffer.size() > 0){
if(ascStack.isEmpty() || buffer.peek() >= ascStack.peek()){
ascStack.push(buffer.pop());
}
else{//这里一定要加else ,
bufTop = buffer.pop();
int count_curBuffer = buffer.size();
while(!ascStack.isEmpty() && bufTop < ascStack.peek()){
buffer.push(ascStack.pop());
}
ascStack.push(bufTop);
int count_numsFromAsc = buffer.size()-count_curBuffer;
for(int i = 0; i < count_numsFromAsc; i++){
ascStack.push(buffer.pop());
}
}
}
for(int i = 0; i < length; i++){
res.add(ascStack.pop());
}
return res;
}