首先申明,我没有去阿里巴巴面试这个题目的,我是看到坛子里有人贴出问题的。我想如果是我去面试,我该怎么解决,如何去分析这个问题,这个问题背后隐藏的是什么哪类问题,花了一个晚上终于把它给弄出来了,不足之处大家给意见。
题目是这样的: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 &¤tMember.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
http://fruitking.iteye.com/blog/505037