输入数据包括一个长度为n且只包含G和B的字符串.n不超过50.
输出一个整数,表示最少需要的调整队伍的次数
GGBBG
2
最终目标是将男孩移到最左边,或者将女孩移到最左边。
如果有B个男孩,则移到最左边的index分别为:0,1,2...B-1,所以所有index的和为(B-1)*B/2
一次遍历,计算目前男孩所在的index的和为sumB,则sumB减去上面的和就是所求的结果。
因此只要一次遍历,计算男孩所在的男孩的个数和男孩所在的index的和,求之差就行了。女孩同理。最后求最小值。
#include <string>
#include <iostream>
using namespace std;
int main(){
string S;
cin>>S;
int B=0;
int G=0;
int sumB=0;
int sumG=0;
for(int i=0;i<S.size();i++){
if(S[i]=='G'){
G++;
sumG+=i;
}
else{
B++;
sumB+=i;
}
}
int ret1=sumB-B*(B-1)/2;
int ret2=sumG-G*(G-1)/2;
int ret=ret1<ret2?ret1:ret2;
cout<<ret;
return 0;
}
import java.util.Scanner;
public class shs {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
int b=0;
int g=0;
int bsum = 0;
int gsum = 0;
for(int i=0;i<s.length();i++){
if(s.charAt(i) == 'G'){
gsum+=(i-g);
g++;
}else if(s.charAt(i) == 'B'){
bsum+=(i-b);
b++;
}
}
System.out.println(Math.min(bsum, gsum));
}
}
#include<iostream>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<list>
#include<queue>
#include<algorithm>
using namespace std;
int main()
{
vector<char> line;
int minMoveLeft = 0, leftG = 0;
int minMoveRight = 0, rightG = 0;
int minMove = 0;
char temp = ' ', rightTemp = ' ';
temp = getchar();
while (temp == 'G' || temp == 'B')
{
line.push_back(temp);
temp = getchar();
}
for (size_t i = 0; i < line.size(); i++)
{
temp = line[i];
rightTemp = line[line.size()-1-i];
if (temp == 'G')
leftG++;
else if(temp == 'B')
minMoveLeft += leftG;
if (rightTemp == 'G')
rightG++;
else if (rightTemp == 'B')
minMoveRight += rightG;
}
minMove = min(minMoveLeft, minMoveRight);
cout << minMove << endl;
return 0;
}
O(n)时间复杂度的方法。调整的目标是将所有女孩放到队列前方或者队列后方,男孩和女孩之间只有一处挨着的地方,
男孩和男孩之间,女孩和女孩之间不用排序。思路是计算把女孩都放在队列前部和都放在队列后部分别所需要交换次数
两者的最小值即为所求的答案。
观察一个随机的队列中,考虑把G放在队列前方所需要的移动次数:如BGB当一个G前有一个B,可以把G前面的B移动一次,成GBB。
BGGB需要移动两次,而BBGGB,需要移动4次,虽然不是最优解(G前有两个B,一共有2G),记下这种方法所需要的最少移动次数。
再来考虑把G放在队列后方所需要的移动次数:还是BBGGB,只需要2次移动(G后面有一个B,一共两个G),
记下这种方法所需要的最少移动次数。
将两者的结果取最小值。
package go.jacob.day913; import java.util.ArrayList; import java.util.Scanner; public class Demo2 { public static void main(String[] args) { Scanner sc=new Scanner(System.in); String str=sc.next(); int len=str.length(); ArrayList<Integer> boys=new ArrayList<Integer>(); ArrayList<Integer> girls=new ArrayList<Integer>(); for(int i=0;i<len;i++){ if(str.charAt(i)=='B') boys.add(i); else girls.add(i); } int timeB=0,timeG=0,index=0; for(int i=0;i<boys.size();i++){ timeB+=boys.get(i)-index; index++; } index=0; for(int i=0;i<girls.size();i++){ timeG+=girls.get(i)-index; index++; } System.out.println(Math.min(timeB, timeG)); sc.close(); } }
/*
因为移动B或者移动G都是等价的,所以我们可以只移动B或者G。
若我们移动B的话,从头开始数,如果B的前面有Vk个G,代表我
们要往前移动Vk下B;同理从尾开始数,如果B的后面有Vs个G,
那么我们也要往后移动Vs下B,所以就是用L把每个B前面有几个G
的个数给累加起来,R把每个B后面有几个G的个数累加起来,然后
再比较一下L和R的大小即可。
*/
int fuk(string s) {
int len = s.length(), L = 0, R = 0;
char c = (s[0] == 'G') ? 'B' : 'G';
int l = 1, r = (s[len - 1] == c) ? 0 : 1;
for(int i = 1; i < len; i ++) {
if(s[i] == c) L += l;
else l ++;
}
for(int i = len - 2; i >= 0; i --) {
if(s[i] == c) R += r;
else r ++;
}
return min(L, R);
} //将男生全部移到左边,或者将女生全部移到左边,取两者最小值 import java.util.Scanner; /** * Created by meichen on 17-9-7. */ public class Main { public static void main(String[] args){ Scanner in = new Scanner(System.in); while (in.hasNext()){ String str = in.nextLine(); int gl = 0; int index = 0; for(int i = 0;i < str.length(); i++){ if(str.charAt(i) == 'G'){ gl += i - index; index++; } } index = 0; int bl = 0; for(int i = 0;i < str.length(); i++){ if(str.charAt(i) == 'B'){ bl += i - index; index++; } } System.out.println(gl < bl ? gl : bl); } } }
#include<iostream>
#include<string.h>
using namespace std;
int compare(char a[50],int num)
{
int gleft=0;
for(int i=0;i<num;i++)
{
for(int j=0;j<num-i-1;j++)
{
if(int(a[j])==66)
{
char o;
if(int(a[j+1]==71))
{
o=a[j];
a[j]=a[j+1];
a[j+1]=o;
gleft++;
}
}
}
}
return gleft;
}
int main()
{
int p;
char child[50],childcopy[50];
cin>>child;
p=strlen(child);
for(int i=0;i<p;i++)
childcopy[p-i-1]=child[i];
int x,y;
x=compare(child,p);
y=compare(childcopy,p);
if(x<=y)
cout<<x<<endl;
else
cout<<y<<endl;
}
import java.util.ArrayList;
import java.util.Scanner;
/**
* 调整队形最终的结果为要么男生在左,女生在右,要么反过来
* 只要BBBBGGGGG 或者GGGGGBBBBB即可
* 然而,对于初始状态,比如GGBBG,该如何调整呢?
* 既然最终结果只有两种可能,GGGBB 和BBGGG
* 那么只要比较这两种可能所付出的代价即可,
* 那么这么想,既然GGGBB和BBGGG都有可能,是不是,调整的时候只动
* B或者只动G就行了,因为他们无疑是等价的嘛
*
* 好,那么我们就只移动B,用一个list记录每个B所在的位置,
* 比如GGBBG,list中有个值,2和3,大小为2
*
* 好,那么现在关键的问题,就是如何比较了
* 比如,GGBBG怎么调整,代价最小,最终结果是GGGBB还是BBGGG
*
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.next();
sc.close();
int n = s.length();
if (n <= 0 || n > 50) {
throw new RuntimeException("the length is too long");
}
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < n; i ++) {
if (s.charAt(i) == 'B') {
list.add(i);
}
}
int bSize = list.size();
int indexSum = 0;
for (int val : list) {
indexSum += val;
}
int left = indexSum - bSize * (bSize - 1) / 2;
int right = bSize * (n - 1) - indexSum - bSize * (bSize - 1) / 2;
System.out.println(Math.min(left, right));
}
}
#include <iostream>
#include <cmath>
using namespace std;
int main(){
string s = "";
cin >> s;
int n = s.size();
int boy = 0, sum = 0, girl;
for(int i = 0; i < n; i++){
if(s[i] == 'B'){
boy++;
sum += i;
}
}
girl = n - boy;
cout << min(sum - boy*(boy-1)/2, n*(n-1)/2 - girl*(girl-1)/2 - sum) << endl;
return 0;
}
考虑 男孩+女孩 与女孩+男孩 两种情况即可。最终取最小值。两个for循环基本一致
#include<bits/stdc++.h>
using namespace std;
int main()
{
string str;
cin>>str;
int res;
int cnt1 = 0;
int left = -1;
for(int i =0;i<str.length();i++)//G+B情况
{
if(str[i]=='G')
{
left++;
cnt1 = cnt1 + i-left;
}
}
int cnt2 = 0;
left = -1;
for(int i =0;i<str.length();i++)//B+G情况
{
if(str[i]=='B')
{
left++;
cnt2 = cnt2 + i-left;
}
}
res = min(cnt1,cnt2);
cout<<res<<endl;
}
import java.util.Scanner;
/*
* 此题显然G和B分别站在一起,然后针对两种情况进行讨论:
* 1.左全是G,右全是B;
* 1.左全是B,右全是G;
*
* 然后求解最小值
* */
public class BGPalindrome {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String line = scanner.nextLine();
int min1 = 0;
int min2 = 0;
int index1 = 0;
int index2 = 0;
// 简单的调整位置即可
for (int i = 0; i < line.length(); i++) {
char c = line.charAt(i);
if (c == 'G') {
min1 += i - index1++;
}
if (c == 'B') {
min2 += i - index2++;
}
}
System.out.println(Math.min(min1, min2));
}
}
}
最终结果就是“GGG....GB...BBB"和"BBB....BG...GGGG"两种,如果是第一种的话,只要判定字符串里面是不是包含"BG"这样的字符,如果包含则用"GB”替换第一个“BG”,次数加一,直到字符串中不包含"BG"。如果是第二种的话,只要判定字符串里面是不是包含"GB”这样的字符,如果包含则用"BG"替换第一个“GB",次数加一,直到字符串中不包含"GB"。输出两种情况次数较小者。
import java.util.Scanner; public class 调整队形 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String line = scanner.nextLine(); String temp = line; int timeGb = 0; while (true) { if (temp.contains("BG")) { temp = temp.replaceFirst("BG", "GB"); timeGb++; } else { break ; } } int timeBG = 0; temp = line; while (true) { if (temp.contains("GB")) { temp = temp.replaceFirst("GB", "BG"); timeBG++; } else { break; } } System.out.println(Math.min(timeBG, timeGb)); } }
//抄的高票答案
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
//GGBBG
Scanner scanner = new Scanner(System.in);
String string = scanner.next();
int sumB = 0;
int sumG = 0;
int countB = 0;
int countG = 0;
for(int i = 0;i < string.length();i++){
if(string.charAt(i) == 'B'){
sumB += i;
countB++;
}
else {
sumG += i;
countG++;
}
}
int resultB = 0;
int resultG = 0;
resultB = sumB - (countB * (countB - 1)) / 2;
resultG = sumG - (countG * (countG - 1)) / 2;
if(resultB > resultG){
System.out.println(resultG);
}
else {
System.out.println(resultB);
}
}
}
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
int main(int argc, const char * argv[]) {
string str;
cin>>str;
int gCount = 0, bCount = 0; //判断g多还是b多,目的是减少算法运行时间。
int len = (int)str.size();
for (int i = 0; i < len; i++) {
if (str[i] == 'G') {
gCount++;
} else {
bCount++;
}
}
char lessCh = gCount < bCount ? 'G' : 'B'; //哪个字符少,就移动哪个。本质上没区别,仅仅为了优化算法。
int leftCount = 0, rightCount = 0; //计算哪边的lessCh多。
int mid = len / 2;
for (int i = 0; i < mid; i++) {
if (str[i] == lessCh) {
leftCount++;
}
}
int rightBegin = len % 2 == 0 ? mid : mid + 1;
for (int i = rightBegin; i < len; i++) {
if (str[i] == lessCh) {
rightCount++;
}
}
if (leftCount < rightCount) {
reverse(str.begin(), str.end());
}
int moveCount = 0, didMove = 0;
for (int i = 0; i < len; i++) {
if (str[i] == lessCh) {
moveCount += i - didMove;
didMove++;
}
}
cout<<moveCount;
return 0;
}