[7/30] 买香蕉

MIOJ #98 买香蕉 🍌

描述

我是一个爱吃香蕉的强迫症。今天我要去水果店论筐买香蕉。 现在水果店有好多筐香蕉,我的要求是买回来的每一筐里必须有相同数量的香蕉。 为了实现这个目标,你可以每次做两件事情。 1)放弃筐里的一部分香蕉 2)连筐带香蕉放弃一整筐 我想知道我能得到最多多少香蕉。

输入

以空格分割的多个正整数,每个正整数表示一筐香蕉的总香蕉数

输出

最多能得到的香蕉数

输入样例

1 2 3
5 0 29 14

输出样例

4
29

解法

大力出奇迹,暴力解法

这个问题无非是选择哪几筐的问题,先把所有可能的选择枚举出来,然后找到每个选择中最小的那筐,每筐都是这个数量时就是最终获得的香蕉数量,遍历所有所有选择然后找到香蕉数量最大的即可。

第一步:枚举出所有的方案。集合 {1,2,3}枚举出所有的方案有
23 种,除去空集,还有7个。1~7,几个数字换算为二进制分别是,001,010,011,100,101,110,111,每一位的0还是1可以视作是否选择这个元素。依照这个想法,我们可以写出程序枚举出所有的可能方案。

第二步:计算每一种方案对应可获得的香蕉数量,就是每种方案中香蕉数量最小值*筐的数量。

代码如下:


package  com.li2niu.mioj.day7.BuyBananas; 
 import  java.util.Arrays;  import  java.util.Scanner;  /**
 * @author chuanyi@88.com
 * @date 2020/10/29
 * @Description
 */ 
 public  class  Main  {  public  static  void  main(String[] args)  {  Scanner scan =  new  Scanner(System.in);  String line;  while  (scan.hasNextLine())  { line = scan.nextLine().trim();  String[] strings = line.split(" ");  int[] nums =  new  int[strings.length];  for  (int i =  0; i < strings.length; i++)  { nums[i]  =  Integer.parseInt(strings[i]);  }  System.out.println(buyBananas(nums));  }  }  private  static  int  buyBananas(int[] nums)  {  String[] buyMethods =  enumBuyMethod(nums);  int max =  0;  for  (String buyMethod : buyMethods)  {  String[] numbers = buyMethod.split(",");  int min = nums[Integer.parseInt(numbers[0])];  for  (int i =  1; i < numbers.length; i++)  {  int temp = nums[Integer.parseInt(numbers[i])];  if  (temp < min)  { min = temp;  }  }  int count = min * numbers.length;  if  (count > max)  { max = count;  }  }  return max;  }  /**
     * 枚举导致内存超限,只存下标
     * 使用字符串存储每一种方案中的筐的下标
     * @param nums
     * @return
     */  private  static  String[]  enumBuyMethod(int[] nums)  {  int length = nums.length;  int subSetNum =  (int)  Math.pow(2, length);  int temp;  String[] strings =  new  String[subSetNum -  1];  for  (int i =  0; i < subSetNum; i++)  {  if  (i ==  0)  {  continue;  } temp = i;  StringBuilder set =  new  StringBuilder();  for  (int j =  0; j < length; j++)  {  if  ((temp &  1)  ==  1)  { set.append(j);  if  (j < length -  1)  { set.append(",");  }  } temp >>=  1;  }  if  (set.charAt(set.length()  -  1)  ==  ',')  { set.deleteCharAt(set.length()  -  1);  } strings[i -  1]  = set.toString();  }  return strings;  }  }  

时间复杂度为 O(2n+1n) 。枚举的总数为 2n ,每种方案都需要遍历数字的每个二进制位取出对应筐的下标,这个长度是 n ,最后统计每一种方案对应的香蕉数也是相同的复杂度。这样,时间复杂度就是O(2n+1n) 。

空间复杂度 O(2n-1)=O(2n) 。一个用于存储方案的辅助数组。

但是这样的暴力方法会内存超限!!!

排序,找短板

有什么其他的办法吗?

题设说,筐中的香蕉是可以放弃一部分的。 比较容易想到的一点是找到一筐数量比较少最佳的香蕉,然后让其他的筐都减少到相同的数量。因为香蕉只能减少,不能增加,我们应当从数量较少的香蕉筐开始,让其余的可能的香蕉筐放弃一部分以达到相同的数量。

第一步:从小到大排列香蕉筐

第二部:从小到大遍历这些筐,让比当前筐多的香蕉都保持相同的数量,求出可以得到的香蕉总数。找到这些总和的最大值。

代码如下:

package  com.li2niu.mioj.day7.BuyBananas;  import  java.util.Arrays;  import  java.util.Scanner;  /**
 * @author chuanyi@88.com
 * @date 2020/10/29
 * @Description
 */  public  class  Main  {  public  static  void  main(String[] args)  {  Scanner scan =  new  Scanner(System.in);  String line;  while  (scan.hasNextLine())  { line = scan.nextLine().trim();  String[] strings = line.split(" ");  int[] nums =  new  int[strings.length];  for  (int i =  0; i < strings.length; i++)  { nums[i]  =  Integer.parseInt(strings[i]);  }  System.out.println(buyBananas1(nums));  }  }  private  static  int  buyBananas1(int[] nums)  {  Arrays.sort(nums);  int max =  0;  int length = nums.length;  for  (int i =  0; i < length; i++)  {  int count = nums[i]  *  (length - i);  if  (count > max)  { max = count;  }  }  return max;  }  }  

时间复杂度是

O(nlogn+n)=O(nlogn) 。使用的Arrays.sort 时间复杂度是O(nlogn) ,遍历需要O(n) 。

空间复杂度O(1) 。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268