Topcoder_157

来源:互联网 发布:微软的云计算系统 编辑:程序博客网 时间:2024/06/16 16:07
【问题描述】
    有n张卡片,每张卡片有一些整数值,并且在这些卡片上也标注了一些字母。同时,在你面前有一排n个插槽,每个插槽上标注了数字。
    现在你需要做的是将此n张卡片放入这n个插槽(每个插槽1张),并且要达到卡片上的数值不小于插槽上标注的数字。最终的结果就是你要给出从左到右排列的字母(代表卡片),并且在满足前面条件的基础上,结果的字母排列尽量按照字母顺序。
    题目中给定一个int数组和一个字符串,字符串的第i个元素和int数组的第i个元素就是第i张卡片上的标识。同时另外给定的一个int数组就是n个插槽的标注值。插槽的顺序是从左向右。返回的字符串就是卡片的排列顺序,如果不存在解,那么返回一个空字符串。
 定义:
    类  CardsAndSlots
    方法  public String firstValid(int[] values, String letters, int[] required)
 约束:
    1、卡片数量在1至50之间(包括)
    2、每个卡片的值和插槽的值在1至1000之间(包括)
    3、给定的字符串letters的长度、values数组的长度、required数组的长度相同
    4、给定的字符串letters仅包含大写英文字母('A'-'Z')
 例子:
    1、values {1, 2, 3};letters "ABC";required {2, 2, 1}
         Returns: "BCA"
    2、values {1, 2, 3, 4, 5};letters "BBBAA";required {1, 1, 1, 1, 5}
         Returns: "ABBBA"
    3、values {1, 1};letters "AA";required {2, 2}
         Returns: ""

【我的解答】
  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.List;
  4. public class CardsAndSlots {
  5.     private boolean check(int[] values, int[] required, boolean[] used) {
  6.         List<Integer> val = new ArrayList<Integer>();
  7.         List<Integer> req = new ArrayList<Integer>();
  8.         int count = 0;
  9.         for (int i = 0; i < values.length; i++) {
  10.             if (!used[i]) {
  11.                 val.add(values[i]);
  12.             } else {
  13.                 count++;
  14.             }
  15.         }
  16.         for (int i = count; i < values.length; i++) {
  17.             req.add(required[i]);
  18.         }
  19.         Collections.sort(val);
  20.         Collections.sort(req);
  21.         for (int i = 0; i < val.size(); i++) {
  22.             if (val.get(i) < req.get(i))
  23.                 return false;
  24.         }
  25.         return true;
  26.     }
  27.     private int findMin(String letters, boolean[] used, boolean[] choose) {
  28.         int index = -1;
  29.         char c = 'Z' + 1;
  30.         for (int i = 0; i < letters.length(); i++) {
  31.             if (!used[i] && !choose[i] && letters.charAt(i) < c) {
  32.                 index = i;
  33.                 c = letters.charAt(i);
  34.             }
  35.         }
  36.         return index;
  37.     }
  38.     public String firstValid(int[] values, String letters, int[] required) {
  39.         boolean[] used = new boolean[letters.length()];
  40.         boolean[] choose;
  41.         StringBuilder sb = new StringBuilder();
  42.         char c;
  43.         int index,count=0;
  44.         while (count++ < letters.length()) {
  45.             choose = new boolean[letters.length()];
  46.             for (int i = 0; i < letters.length(); i++) {
  47.                 index = findMin(letters, used, choose);
  48.                 if (index > -1) {
  49.                     choose[index] = true;
  50.                     if (values[index] >= required[sb.toString().length()]) {
  51.                         c = letters.charAt(index);
  52.                         used[index] = true;
  53.                         if (check(values, required, used))
  54.                             sb.append(c);
  55.                         else
  56.                             used[index] = false;
  57.                     }
  58.                 }
  59.             }
  60.         }
  61.         return sb.toString();
  62.     }
  63. }
【思想】
    使用循环检测的方法,即每次选择最小的字母然后检测在这个位置使用这个字母,是否会得到解,如果可以得到解就记录。
    此处用到了以下事实,将values和required数组中现在可用的值(未被使用)排序,如果存在某一位置上的values的值小于required的值,那么无论怎么调整至少存在一个位置values的值将小于required的值。
原创粉丝点击