题目:

在幼儿园有n个小朋友排列为一个队伍,从左到右一个挨着一个编号为(0~n-1)。其中有一些是男生,有一些是女生,男生用’B’表示,女生用’G’表示。小朋友们都很顽皮,当一个男生挨着的是女生的时候就会发生矛盾。作为幼儿园的老师,你需要让男生挨着女生或者女生挨着男生的情况最少。你只能在原队形上进行调整,每次调整只能让相邻的两个小朋友交换位置,现在需要尽快完成队伍调整,你需要计算出最少需要调整多少次可以让上述情况最少。例如:
GGBBG -> GGBGB -> GGGBB
这样就使之前的两处男女相邻变为一处相邻,需要调整队形2次
输入描述:

输入数据包括一个长度为n且只包含G和B的字符串.n不超过50.

输出描述:

输出一个整数,表示最少需要的调整队伍的次数

输入例子:

GGBBG

输出例子:

2

分析:

解:最后矛盾最少的状态只可能是男生和女生分别在两边,最多只有中间一个男生挨着女生,所以总共有两种方式:男生全部在座女生全部在右;女生全部在坐男生全部在右。

算法:所以分两种情况:把男生全部移到左边;把女生全部移到左边。再从两个数中求一个最小值即可。在移动的时候可以用一个游标记录一次需要移动的位置次数,这样会简化移动过程,不需要每次只能移动一步。

算法代码:

int adjustFormation(const char * formation, int size)
{
    bool * formBoyMove = new bool[size];
    bool * formGirlMove = new bool[size];
    
    for (int i = 0; i < size; ++i) {
        if ('B' == formation[i]) {
            formBoyMove[i] = formGirlMove[i] = true;
        } else {
            formBoyMove[i] = formGirlMove[i] = false;
        }
    }
    
    int minChangeTimes, boyMove, girlMove;
    boyMove = girlMove = 0;
    
    int tempChangingTimes = 1;
    
    //move boy
    for (int i = 0; i < size; ++i) {
        if (true == formBoyMove[i]) {
            continue;
        } else {
            //find the closest boy
            while (true != formBoyMove[i+tempChangingTimes] && (tempChangingTimes + i) < size) {
                ++tempChangingTimes;
            }

            //no boys behind
            if (tempChangingTimes + i >= size) {
                //move end
                break;
            }
            
            //change formation for tempChangingTimes
            formBoyMove[i] = true;
            formBoyMove[i+tempChangingTimes] = false;
            boyMove += tempChangingTimes;
            
            //reset tempChangingTimes
            tempChangingTimes = 1;
        }
    }
    
    //reset tempChangingTimes
    tempChangingTimes = 1;
    
    //move girl
    for (int i = 0; i < size; ++i) {
        if (false == formGirlMove[i]) {
            continue;
        } else {
            //find the closest girl
            while (false != formGirlMove[i+tempChangingTimes] && (tempChangingTimes + i) < size) {
                ++tempChangingTimes;
            }
            
            //no girls behind
            if (tempChangingTimes + i >= size) {
                //move end
                break;
            }
            
            //change formation for tempChangingTimes
            formGirlMove[i] = false;
            formGirlMove[i+tempChangingTimes] = true;
            girlMove += tempChangingTimes;
            
            //reset tempChangingTimes
            tempChangingTimes = 1;
        }
    }
    
    minChangeTimes = min(boyMove, girlMove);
    
    return minChangeTimes;
}

测试代码:

//
//  main.cpp
//  adjustFormation
//
//  Created by Jiajie Zhuo on 2017/4/7.
//  Copyright © 2017年 Jiajie Zhuo. All rights reserved.
//

#include <iostream>

#define MAXNUMBER 50

using namespace std;

int adjustFormation(const char * formation, int size);

int main(int argc, const char * argv[]) {
    cout << "Please enter the formation of students: ";
    char * formation = new char[MAXNUMBER];
    cin >> formation;
    
    int size = (int)strlen(formation);
    
    int minChangeTimes = adjustFormation(formation, size);
    cout << "The minimum times of changing is " << minChangeTimes << endl;
    
    delete [] formation;
    
    return 0;
}

总结:

简化问题的关键点即是用一个游标记录下一个男生(女生)的的位置,这样可以一次移动多步。