user-0 提问: C语言题目，要求时间复杂度最高为O（n），球球大佬们了

回复:
user: user-0
content: 引用 2 楼 lin5161678的回复:[quote=引用 1 楼 mymtom 的回复:] 统计黑牛，白牛的数量就可以了呀  #include <assert.h> #include <stdio.h>  int main() {     int i, n;     int c, s[3] = {0};      assert(1 == scanf("%d", &n));      for (i = 0; i < n; i++) {         assert(1 == scanf("%d", &c));         assert(c == 1 || c == 2);         s[c]++;     }      printf("%d\n", (s[1] < s[2]) ? s[1] : s[2]);      return 0; }  这样是不行的 比如  11111222 结果是一次魔法棒都不用挥  应该输出 0 按照你的做法 会输出 3 [/quote] 对，没错，不过我的同学都觉得挺简单的

user: user-1
content: 引用 1 楼 mymtom 的回复:统计黑牛，白牛的数量就可以了呀  #include <assert.h> #include <stdio.h>  int main() {     int i, n;     int c, s[3] = {0};      assert(1 == scanf("%d", &n));      for (i = 0; i < n; i++) {         assert(1 == scanf("%d", &c));         assert(c == 1 || c == 2);         s[c]++;     }      printf("%d\n", (s[1] < s[2]) ? s[1] : s[2]);      return 0; }  这样是不行的 比如  11111222 结果是一次魔法棒都不用挥  应该输出 0 按照你的做法 会输出 3

user: user-2
content: 统计黑牛，白牛的数量就可以了呀  #include <assert.h> #include <stdio.h>  int main() {     int i, n;     int c, s[3] = {0};      assert(1 == scanf("%d", &n));      for (i = 0; i < n; i++) {         assert(1 == scanf("%d", &c));         assert(c == 1 || c == 2);         s[c]++;     }      printf("%d\n", (s[1] < s[2]) ? s[1] : s[2]);      return 0; }

user: user-3
content: 全白的最小的结果就是最后一个，m+n为0， 这个结果就表明了无需再改 全黑的最小的结果就是第一个  第一遍计算的是m数组，第二遍计算的n数组 两个对照做加法，然后找到最小值， 结果就是0

user: user-3
content: 没有漏， 全白和全黑对应的m+n的最小值都是0, m+n的意义就是要改变的数量  全白， 第一遍从前向后累计多少黑：得到的数组 0     0     ......  0 第二遍从后向前累计多少白：得到的数组 n-1 n-2  ......   0 最小的结果就是第一个，m+n为0， 这个结果就表明了无需再改  全黑 第一遍得到数组 0 1  2  3 4 .....n-1 第二遍得到数组 0 0 0 .....         0 m+n最小值依然是0

user: user-4
content: 我觉得上面的答案可能还漏掉一种情况，即全白或者全黑，即题目中 【注意，可以将所有的奶牛都变成白色，或者都变成黑色。】，这种情况是否也该考虑？ 如果是全黑或者全白就是0，否则，还需要从 m+n 和 白妞总数 和 黑妞总数 中取最少，即变成全黑或全白，min(m+n, 白妞总数, 黑妞总数)

user: user-3
content: 非要分出黑妞和白妞 ，还挺能挑的  这个题目是要找到一个点， 此点前面的有n个黑妞，后面有m个白妞，让m+n最小 所以要做多次循环 第一次，从前向后，记录每个位置前面的黑妞数量 第二次，从后向前，记录每个位置后面的白妞数量 第三次，前面两个数组求和，并找到最小值 第四次，这点前面都都是白妞，后面的都是黑妞 搞定，麻烦一点儿， 但是谁让你想找最好的妞呢  虽然是四次循环，它还是O（n）的计算量

user: user-5
content: 引用 4 楼 mymtom 的回复:上面的程序，题意理解错误了！  #include <assert.h> #include <stdio.h> #include <stdlib.h>  #define WHITE   1 #define BLACK   2  int main() {     int i, n;     int *c, *w, *b;     int m, mw, mb;      assert(1 == scanf("%d", &n));      c = malloc(n * sizeof(int));     w = malloc(n * sizeof(int));     b = malloc(n * sizeof(int));     for (i = 0; i < n; i++) {         assert(1 == scanf("%d", &c[i]));         assert(c[i] == WHITE || c[i] == BLACK);     }      /* 统计第i个位置之前的黑色奶牛 */     mb = 0;     for (i = 0; i <= n - 1; i++) {         b[i] = mb;         if (c[i] == BLACK) {             mb++;         }     }      /* 统计第i个位置之后的白色奶牛 */     mw = 0;     for (i = n - 1; i >= 0; i--) {         w[i] = mw;         if (c[i] == WHITE) {             mw++;         }     }      /* 最多需要 n - 1 次? n / 2 就够了吧 */     m = n - 1;     for (i = 0; i <= n - 1; i++) {         if (m > w[i] + b[i]) {             m = w[i] + b[i];         }     }      printf("%d\n", m);     free(c);     free(w);     free(b);      return 0; }    太牛了 就是找到队列中的白牛黑牛分界点，后面如果有白牛就是白牛的挥棒次数，前面有黑牛，就是有黑牛的挥棒次数。 两者之和，就是队伍变成现在样子，求队伍每个位置的最小值。

user: user-2
content: 上面的程序，题意理解错误了！  #include <assert.h> #include <stdio.h> #include <stdlib.h>  #define WHITE   1 #define BLACK   2  int main() {     int i, n;     int *c, *w, *b;     int m, mw, mb;      assert(1 == scanf("%d", &n));      c = malloc(n * sizeof(int));     w = malloc(n * sizeof(int));     b = malloc(n * sizeof(int));     for (i = 0; i < n; i++) {         assert(1 == scanf("%d", &c[i]));         assert(c[i] == WHITE || c[i] == BLACK);     }      /* 统计第i个位置之前的黑色奶牛 */     mb = 0;     for (i = 0; i <= n - 1; i++) {         b[i] = mb;         if (c[i] == BLACK) {             mb++;         }     }      /* 统计第i个位置之后的白色奶牛 */     mw = 0;     for (i = n - 1; i >= 0; i--) {         w[i] = mw;         if (c[i] == WHITE) {             mw++;         }     }      /* 最多需要 n - 1 次? n / 2 就够了吧 */     m = n - 1;     for (i = 0; i <= n - 1; i++) {         if (m > w[i] + b[i]) {             m = w[i] + b[i];         }     }      printf("%d\n", m);     free(c);     free(w);     free(b);      return 0; }