`

也谈阿里巴巴面试题_身高排队问题

阅读更多
    首先申明,我没有去阿里巴巴面试这个题目的,我是看到坛子里有人贴出问题的。我想如果是我去面试,我该怎么解决,如何去分析这个问题,这个问题背后隐藏的是什么哪类问题,花了一个晚上终于把它给弄出来了,不足之处大家给意见。

    题目是这样的:12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?

    初看这个问题,如果是应试,还真有点摸不着头脑,但是静心想想,还是有规律的,一般面试题目都是一些经典的算法问题,只是常常将问题以某种看似日常化,生活的题目来叙述罢了。

    首先把问题抽象,题目变成:给定一组整数(当然可以是整数,浮点数等,这里姑且当成整数处理,道理是一样的),这组整数中每个数值大小不一样,把这组整数分成两组,每组按照从小到大排列,要求一组每个成员数值比对应位置上的另外一组的成员数值小。

    再进一步分解抽象:就是给定一组整数,从这整数中找X个整数出来,使得这X个数之和不大于给定整数数组之和的一半,如果这个一半的情况找到了,另外一半基本确定,因此,现在题目转化成从给定数组中找一个X个数,使得X个数之和小于给定数组之和的一半。

    既然问题抽象了,那么现在来设计算法,一个最简单的算法就是穷举,人脑简直是太有限了,让计算机穷举去贝,这里采用遍历整个数组,即确定一个首元素后采用栈来确定这个栈里面的元素是否符合上文中X个数的情况,如果符合就记录下来,如果不符合就进入下一步选择。具体算法是:
    (1)先对给定数组Q排序,按照从小到大的顺序排列。
    (2)然后循环这个数组(其时排序后循环一半就可以了,理由是找小的一半数组H,最小的元素肯定小于1/2长度的那个元素),把这个循环中的整数A1加入一个栈S,然后从给定数组Q中找比栈顶元素次大的一个元素最为下一个栈顶元素入栈,循环入栈操作。
    (3)符合情况的记录:如果这个栈S的元素长度达到给定数组Q元素长度的一半时,就要判断这个栈S元素之和是否小于Q数组之和的一半,如果符合就记录这个栈S的所有元素,并弹出栈顶元素Top,从Q数组中找下一个入栈元素,条件时这个入栈元素要比这个出栈元素Top大
    (4)不符合半组H的情况:当栈S元素长度等于Q数组长度一半时,并且此时出栈元素是最后一个了(排序后最大的元素),那么就要出栈两个元素;当栈S元素长度等于Q数组长度一半时,并且此时栈S元素之和已大于给定数组Q之和的一半了,也要出栈两个元素;
    (5)退出循环情况:当栈S只有小于等于一个元素了,且下一个元素为空,那么退出当前循环;当栈S小于等于两个元素长度,且下一个元素为数组Q最后一个元素时,那么退出当前循环;当栈S大于两个元素长度,且下一个元素为数组Q最后一个元素时,那么要出栈两个元素。
本人采用java语言实现了这个算法过程,可以任意定义数组大小,最后打印出来这个排列组合,具体程序如下:
package com.fruitking.test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

/**
 * 给定一个整数列表(每个数大小都不一样),分成两队,
 * 每对按照高矮排列,且左边一对比右边一对对应位置上的值要小
 * @author XuGuo
 * @since 2009-10-27
 */
public class HalfOfQueue {
	
	private List<Integer> queueList;//存储整个编队的人的身高数据列表
	private Stack<Integer> halfStack = new Stack<Integer>();//遍历时候临时使用的栈
	private List<List<Integer>> halfResultList = new ArrayList<List<Integer>>();//用于临时存储半个队列
	private List<List<Pair>> resultList = new ArrayList<List<Pair>>();//用于存储结果排序好的符合要求的队列
	private int sum = 0;//整个编队的总大小
	private Integer lastMember;//排序后最大的元素
	
	public HalfOfQueue(List<Integer> queueList){
		this.queueList = this.sortQueueList(queueList);
		this.sumOfQueueList();
		if(queueList!=null&&queueList.size()>=2){
			this.lastMember = queueList.get(queueList.size()-1);
		}
	}
	
	/**
	 * 打印总过有多少组合,并且组合是哪些
	 */
	public List<List<Pair>> getResultPairList(){
		return this.resultList;
	}
	
	/**
	 * 查找和结果整理
	 */
	public void run(){
		this.halfQueue();
		this.handlePairQueue();
	}
	
	/**
	 * 匹配成对
	 */
	private void handlePairQueue(){
		if(halfResultList!=null&&!halfResultList.isEmpty()){
			for(int i=0;i<halfResultList.size();i++){
				List<Integer> tempOneList = halfResultList.get(i);
				List<Integer> tempOtherList = new ArrayList<Integer>();
				int queueSize = this.queueList.size();
				if(tempOneList!=null&&!tempOneList.isEmpty()){
					Integer tempMember = null;
					for(int k=0;k<queueSize;k++){
						tempMember = queueList.get(k);
						if(!tempOneList.contains(tempMember)){
							tempOtherList.add(tempMember);
						}
					}
					tempOtherList = this.sortQueueList(tempOtherList);
				}
				List<Pair> pairList = new ArrayList<Pair>();
				for(int k=0;k<tempOneList.size();k++){
					Pair pair = new Pair(tempOneList.get(k),tempOtherList.get(k));
					if(pair.isCorrectPair()){
						pairList.add(pair);
					}
				}
				if(pairList.size()==this.queueList.size()/2){
					this.resultList.add(pairList);
				}
			}
		}
	}
	
	/**
	 * 半块队列的穷举
	 */
	private void halfQueue(){
		for(int i=0;i<queueList.size()/2;i++){
			if(queueList.size()<2){
				return;
			}
			halfStack.clear();
			halfStack.push(queueList.get(i));
			Integer inNextMember = halfStack.peek();
			Integer topStackMember = null;
			while(true){
				if(halfStack.size()<(queueList.size()/2)){
					inNextMember = getNextMember(inNextMember);
					if(inNextMember!=null){
						halfStack.push(inNextMember);
					}else{
						if(halfStack.size()<=1){
							break;//退出条件
						}else{
							halfStack.pop();//退出最后一个元素
							inNextMember = halfStack.pop();//退出到数第二个元素
							continue;
						}
					}
					if(halfStack.size()==(queueList.size()/2)){
						if(this.isHalfOfSumQueueList()){
							List<Integer> tempList = new ArrayList<Integer>();
							tempList.addAll(halfStack);
							halfResultList.add(tempList);
							topStackMember = halfStack.pop();//当栈满时退出最后一个栈元素
							if(topStackMember.intValue()==this.lastMember.intValue()){
								//最后一个元素了
								inNextMember = halfStack.pop();//当栈差一个元素满时退出最后一个元素
							}
						}else{
							halfStack.pop();//退出最后一个元素(这个元素的加入已经满足此栈所有元素不符合业务逻辑的情况了)
							inNextMember = halfStack.pop();//退出到数第二个元素(即使后面还有元素已经不满足业务逻辑了)
						}
					}else if(inNextMember.intValue()==this.lastMember.intValue()){
						if(halfStack.size()<=2){//第一个元素和最后一个元素了也就要退出
							break;//退出条件
						}else{
							halfStack.pop();//退出最后一个元素(这个元素一定是编队中最大的元素)
							inNextMember = halfStack.pop();//退出到数第二个元素
						}
					}
				}
			}
		}
	}
	
	/**
	 * 是否是编队值的一半的最大值
	 * @return
	 */
	private boolean isHalfOfSumQueueList(){
		int sumOfHalf = 0;
		if(halfStack!=null&&!halfStack.isEmpty()){
			Iterator<Integer> halfStackIt = halfStack.iterator();
			while(halfStackIt.hasNext()){
				sumOfHalf = sumOfHalf + halfStackIt.next().intValue();
			}
			if(sumOfHalf<=(this.sum/2-queueList.size()/4)){
				return true;
			}
		}
		return false;
	}
	
	
	
	/**
	 * 获得比当前元素大的元素,已经对成员列表排序了
	 * 如果当前为空就返回最小的那个元素,如果当前元素最大,就返回最大的那个元素
	 * @return
	 */
	private Integer getNextMember(Integer currentMember){
		Integer nextMember = null;
		if(queueList!=null&&!queueList.isEmpty()){
			if(currentMember!=null&&currentMember.intValue()==this.lastMember.intValue()){
				return null;
			}
			Iterator<Integer> memberIt = queueList.iterator();
			while(memberIt.hasNext()){
				nextMember = memberIt.next();
				if(currentMember!=null){
					if(nextMember.intValue()>currentMember.intValue()){
						break;
					}
				}else{
					break;
				}
			}
		}
		return nextMember;
	}
	
	/**
	 * 求队列和
	 */
	private void sumOfQueueList(){
		if(queueList!=null&&!queueList.isEmpty()){
			for(int k=0;k<queueList.size();k++){
				sum = sum + queueList.get(k).intValue();
			}
		}
	}
	
	/**
	 * 对编队按照从小到大排序
	 * @param queueList
	 * @return
	 */
	private List<Integer> sortQueueList(List<Integer> srcQueueList){
		List<Integer> destQueueList = new ArrayList<Integer>();
		if(srcQueueList!=null&&!srcQueueList.isEmpty()){
			List<Integer> tempList = new ArrayList<Integer>();
			tempList.addAll(srcQueueList);
			Iterator<Integer> outIt = tempList.iterator();
			while(outIt.hasNext()){
				Integer nextMember = null;
				Integer tempMember = null;
				Iterator<Integer> inIt = tempList.iterator();
				while(inIt.hasNext()){
					tempMember = inIt.next();
					if(nextMember==null){
						nextMember = tempMember;
					}
					if(nextMember.intValue()>tempMember.intValue()){
						nextMember = tempMember;
					}
				}
				if(nextMember!=null){
					destQueueList.add(nextMember);
					tempList.remove(nextMember);
					outIt = tempList.iterator();
				}
			}
		}
		return destQueueList;
	}
}

package com.fruitking.test;

/**
 * 数据封装而已,不想用太多的数组这样的单个东西
 * @author XuGuo
 * @since 2009-10-27
 */
public class Pair {
	
	private Integer left;
	private Integer right;
	
	public Pair(Integer left,Integer right){
		this.left = left;
		this.right = right;
	}
	
	/**
	 * 判断这对是否是正确的组合(即左边这个元素是否小于右边这个元素)
	 * @return
	 */
	public boolean isCorrectPair(){
		if(left!=null&&right!=null&&left.intValue()<right.intValue()){
			return true;
		}else{
			return false;
		}
	}

	public int getLeft() {
		return left;
	}

	public void setLeft(int left) {
		this.left = left;
	}

	public int getRight() {
		return right;
	}

	public void setRight(int right) {
		this.right = right;
	}
}

package com.fruitking.test;

import java.util.ArrayList;
import java.util.List;

/**
 * @author XuGuo
 * @since 2009-10-27
 */
public class Test10 {

	/**
	 * 12个高矮不同的人,排成两排,每排必须是从矮到高排列,
	 * 而且第二排比对应的第一排的人高,问排列方式有多少种? 
	 */
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<Integer>();
		list.add(new Integer(2));list.add(new Integer(4));
		list.add(new Integer(1));list.add(new Integer(3));
		list.add(new Integer(5));list.add(new Integer(6));
		list.add(new Integer(7));list.add(new Integer(8));
		list.add(new Integer(9));list.add(new Integer(11));
		list.add(new Integer(10));list.add(new Integer(12));
		HalfOfQueue test1 = new HalfOfQueue(list);
		test1.run();
		List<List<Pair>> resultList = test1.getResultPairList();
		/**
		 * 打印总过有多少组合,并且组合是哪些
		 */
		System.out.println();
		System.out.println("---总共有"+resultList.size()+"个组合---");
		for(int i=0;i<resultList.size();i++){
			List<Pair> tempList = resultList.get(i);
			if(tempList!=null&&!tempList.isEmpty()){
				System.out.println("--------------------");
				for(int k=0;k<tempList.size();k++){
					System.out.print(tempList.get(k).getLeft()+" ");
				}
				System.out.println();
				for(int k=0;k<tempList.size();k++){
					System.out.print(tempList.get(k).getRight()+" ");
				}
				System.out.println();
			}
		}
	}
}

运行结果:


---总共有132个组合---
--------------------
1 2 3 4 5 6
7 8 9 10 11 12
--------------------
1 2 3 4 5 7
6 8 9 10 11 12
--------------------
1 2 3 4 5 8
6 7 9 10 11 12
--------------------
1 2 3 4 5 9
6 7 8 10 11 12
--------------------
1 2 3 4 5 10
6 7 8 9 11 12
--------------------
1 2 3 4 5 11
6 7 8 9 10 12
--------------------
1 2 3 4 6 7
5 8 9 10 11 12
--------------------
1 2 3 4 6 8
5 7 9 10 11 12
--------------------
1 2 3 4 6 9
5 7 8 10 11 12
--------------------
1 2 3 4 6 10
5 7 8 9 11 12
--------------------
1 2 3 4 6 11
5 7 8 9 10 12
--------------------
1 2 3 4 7 8
5 6 9 10 11 12
--------------------
1 2 3 4 7 9
5 6 8 10 11 12
--------------------
1 2 3 4 7 10
5 6 8 9 11 12
--------------------
1 2 3 4 7 11
5 6 8 9 10 12
--------------------
1 2 3 4 8 9
5 6 7 10 11 12
--------------------
1 2 3 4 8 10
5 6 7 9 11 12
--------------------
1 2 3 4 8 11
5 6 7 9 10 12
--------------------
1 2 3 4 9 10
5 6 7 8 11 12
--------------------
1 2 3 4 9 11
5 6 7 8 10 12
--------------------
1 2 3 5 6 7
4 8 9 10 11 12
--------------------
1 2 3 5 6 8
4 7 9 10 11 12
--------------------
1 2 3 5 6 9
4 7 8 10 11 12
--------------------
1 2 3 5 6 10
4 7 8 9 11 12
--------------------
1 2 3 5 6 11
4 7 8 9 10 12
--------------------
1 2 3 5 7 8
4 6 9 10 11 12
--------------------
1 2 3 5 7 9
4 6 8 10 11 12
--------------------
1 2 3 5 7 10
4 6 8 9 11 12
--------------------
1 2 3 5 7 11
4 6 8 9 10 12
--------------------
1 2 3 5 8 9
4 6 7 10 11 12
--------------------
1 2 3 5 8 10
4 6 7 9 11 12
--------------------
1 2 3 5 8 11
4 6 7 9 10 12
--------------------
1 2 3 5 9 10
4 6 7 8 11 12
--------------------
1 2 3 5 9 11
4 6 7 8 10 12
--------------------
1 2 3 6 7 8
4 5 9 10 11 12
--------------------
1 2 3 6 7 9
4 5 8 10 11 12
--------------------
1 2 3 6 7 10
4 5 8 9 11 12
--------------------
1 2 3 6 7 11
4 5 8 9 10 12
--------------------
1 2 3 6 8 9
4 5 7 10 11 12
--------------------
1 2 3 6 8 10
4 5 7 9 11 12
--------------------
1 2 3 6 8 11
4 5 7 9 10 12
--------------------
1 2 3 6 9 10
4 5 7 8 11 12
--------------------
1 2 3 6 9 11
4 5 7 8 10 12
--------------------
1 2 3 7 8 9
4 5 6 10 11 12
--------------------
1 2 3 7 8 10
4 5 6 9 11 12
--------------------
1 2 3 7 8 11
4 5 6 9 10 12
--------------------
1 2 3 7 9 10
4 5 6 8 11 12
--------------------
1 2 3 7 9 11
4 5 6 8 10 12
--------------------
1 2 4 5 6 7
3 8 9 10 11 12
--------------------
1 2 4 5 6 8
3 7 9 10 11 12
--------------------
1 2 4 5 6 9
3 7 8 10 11 12
--------------------
1 2 4 5 6 10
3 7 8 9 11 12
--------------------
1 2 4 5 6 11
3 7 8 9 10 12
--------------------
1 2 4 5 7 8
3 6 9 10 11 12
--------------------
1 2 4 5 7 9
3 6 8 10 11 12
--------------------
1 2 4 5 7 10
3 6 8 9 11 12
--------------------
1 2 4 5 7 11
3 6 8 9 10 12
--------------------
1 2 4 5 8 9
3 6 7 10 11 12
--------------------
1 2 4 5 8 10
3 6 7 9 11 12
--------------------
1 2 4 5 8 11
3 6 7 9 10 12
--------------------
1 2 4 5 9 10
3 6 7 8 11 12
--------------------
1 2 4 5 9 11
3 6 7 8 10 12
--------------------
1 2 4 6 7 8
3 5 9 10 11 12
--------------------
1 2 4 6 7 9
3 5 8 10 11 12
--------------------
1 2 4 6 7 10
3 5 8 9 11 12
--------------------
1 2 4 6 7 11
3 5 8 9 10 12
--------------------
1 2 4 6 8 9
3 5 7 10 11 12
--------------------
1 2 4 6 8 10
3 5 7 9 11 12
--------------------
1 2 4 6 8 11
3 5 7 9 10 12
--------------------
1 2 4 6 9 10
3 5 7 8 11 12
--------------------
1 2 4 6 9 11
3 5 7 8 10 12
--------------------
1 2 4 7 8 9
3 5 6 10 11 12
--------------------
1 2 4 7 8 10
3 5 6 9 11 12
--------------------
1 2 4 7 8 11
3 5 6 9 10 12
--------------------
1 2 4 7 9 10
3 5 6 8 11 12
--------------------
1 2 4 7 9 11
3 5 6 8 10 12
--------------------
1 2 5 6 7 8
3 4 9 10 11 12
--------------------
1 2 5 6 7 9
3 4 8 10 11 12
--------------------
1 2 5 6 7 10
3 4 8 9 11 12
--------------------
1 2 5 6 7 11
3 4 8 9 10 12
--------------------
1 2 5 6 8 9
3 4 7 10 11 12
--------------------
1 2 5 6 8 10
3 4 7 9 11 12
--------------------
1 2 5 6 8 11
3 4 7 9 10 12
--------------------
1 2 5 6 9 10
3 4 7 8 11 12
--------------------
1 2 5 6 9 11
3 4 7 8 10 12
--------------------
1 2 5 7 8 9
3 4 6 10 11 12
--------------------
1 2 5 7 8 10
3 4 6 9 11 12
--------------------
1 2 5 7 8 11
3 4 6 9 10 12
--------------------
1 2 5 7 9 10
3 4 6 8 11 12
--------------------
1 2 5 7 9 11
3 4 6 8 10 12
--------------------
1 3 4 5 6 7
2 8 9 10 11 12
--------------------
1 3 4 5 6 8
2 7 9 10 11 12
--------------------
1 3 4 5 6 9
2 7 8 10 11 12
--------------------
1 3 4 5 6 10
2 7 8 9 11 12
--------------------
1 3 4 5 6 11
2 7 8 9 10 12
--------------------
1 3 4 5 7 8
2 6 9 10 11 12
--------------------
1 3 4 5 7 9
2 6 8 10 11 12
--------------------
1 3 4 5 7 10
2 6 8 9 11 12
--------------------
1 3 4 5 7 11
2 6 8 9 10 12
--------------------
1 3 4 5 8 9
2 6 7 10 11 12
--------------------
1 3 4 5 8 10
2 6 7 9 11 12
--------------------
1 3 4 5 8 11
2 6 7 9 10 12
--------------------
1 3 4 5 9 10
2 6 7 8 11 12
--------------------
1 3 4 5 9 11
2 6 7 8 10 12
--------------------
1 3 4 6 7 8
2 5 9 10 11 12
--------------------
1 3 4 6 7 9
2 5 8 10 11 12
--------------------
1 3 4 6 7 10
2 5 8 9 11 12
--------------------
1 3 4 6 7 11
2 5 8 9 10 12
--------------------
1 3 4 6 8 9
2 5 7 10 11 12
--------------------
1 3 4 6 8 10
2 5 7 9 11 12
--------------------
1 3 4 6 8 11
2 5 7 9 10 12
--------------------
1 3 4 6 9 10
2 5 7 8 11 12
--------------------
1 3 4 6 9 11
2 5 7 8 10 12
--------------------
1 3 4 7 8 9
2 5 6 10 11 12
--------------------
1 3 4 7 8 10
2 5 6 9 11 12
--------------------
1 3 4 7 8 11
2 5 6 9 10 12
--------------------
1 3 4 7 9 10
2 5 6 8 11 12
--------------------
1 3 4 7 9 11
2 5 6 8 10 12
--------------------
1 3 5 6 7 8
2 4 9 10 11 12
--------------------
1 3 5 6 7 9
2 4 8 10 11 12
--------------------
1 3 5 6 7 10
2 4 8 9 11 12
--------------------
1 3 5 6 7 11
2 4 8 9 10 12
--------------------
1 3 5 6 8 9
2 4 7 10 11 12
--------------------
1 3 5 6 8 10
2 4 7 9 11 12
--------------------
1 3 5 6 8 11
2 4 7 9 10 12
--------------------
1 3 5 6 9 10
2 4 7 8 11 12
--------------------
1 3 5 6 9 11
2 4 7 8 10 12
--------------------
1 3 5 7 8 9
2 4 6 10 11 12
--------------------
1 3 5 7 8 10
2 4 6 9 11 12
--------------------
1 3 5 7 8 11
2 4 6 9 10 12
--------------------
1 3 5 7 9 10
2 4 6 8 11 12
--------------------
1 3 5 7 9 11
2 4 6 8 10 12
分享到:
评论
3 楼 zrs217 2012-03-06  
很犀利,学习一下
2 楼 BenArfa 2009-11-03  
(12,6)/7 = ((12*11*10*9*8*7)/(6*5*4*3*2*1))/7 = 132
^_^
1 楼 fruitking 2009-10-28  
后来修正过一次
栈操作退出条件的bug修正
这次终于完整了,谢谢大家的支持

相关推荐

Global site tag (gtag.js) - Google Analytics