【问题标题】:Need help understanding an algorithm that employs Arrays.sort()需要帮助理解使用 Arrays.sort() 的算法
【发布时间】:2020-01-20 23:03:50
【问题描述】:

问题

给定一个非负整数列表,将它们排列成最大的数。

例如输入:[3,30,34,5,9] 输出:“9534330”

解决方案

public class Solution {
    // DO NOT MODIFY THE LIST
    public String largestNumber(final List<Integer> a) {

    String[] arr = new String[a.size()];
    for (int i = 0; i < a.size(); i++) {
        arr[i] = String.valueOf(a.get(i));
    }


    Arrays.sort(arr, new Comparator<String>(){
        public int compare(String a, String b){
            return (b+a).compareTo(a+b);
        }
    });


    StringBuilder sb = new StringBuilder();
    for(String s: arr){
        sb.append(s);
    }

    if(sb.charAt(0) == '0'){     //check if all zeroes are there
        return String.valueOf(0);
    }

    return sb.toString();   
    }
}

这行得通,但我不知道 - 我不明白 Comparator 做了什么,但我知道通过在代码中交换 (b+a) 和 (a+b) 我们将得到一个升序结果 - 但我是无法理解这是如何在内部工作的。

【问题讨论】:

  • “它们组成最大的数”是什么意思?
  • 使用数组的元素我们必须创建尽可能多的数字...所以必须牢记字典顺序输入:[3,30,34,5,9] 输出:“9534330 "
  • FWIW,你可以只使用 Arrays.sort(arr, (a,b) -&gt; (b+a).compareTo(a+b) ); 而不是你的所有 Arrays.sort(...) 以提高可读性 - Comparator 自 Java 8 起就是 @FunctionalInterface。

标签: java string comparator compareto


【解决方案1】:

你可以在b+a 之前写a+b。但是,您必须将参数切换到 compare 方法,然后是 b,然后是 a。但这就是所有这一切的原因。

首先,您需要假设 strings 可以像 ints 一样使用 进行比较。

在 sort 方法的某处,您有一个比较两个值 r 和 s 的构造。

当你对它们进行排序时,你有一个类似的语句

    if (r < s) {
       swap them
    }

按一个方向对它们进行排序(可能是升序)。

如果你这样做了

    if (s < r) {
      swap them 
    }

将它们按另一个方向排序。

当您颠倒r 和s 的顺序时,这就是您正在做的事情。改变排序的方向。

当您将它们连接在一起时,您会形成两个不同的字符串a+b 和b+a。但是这个过程仍然是一样的,你在一个方向上比较它们,然后在另一个方向上比较它们。所以本质上是,

    r = a+b
    s = b+a

然后你像上面一样比较r和s以获得连接字符串的升序或降序。

这里有一个简单的排序方法和两个Comparators 对integers 进行排序,这样你就可以看到它们是如何工作的。唯一的区别是哪个比较返回 -1 和 1。

      int[] v = { 10, 8, 2, 3, 4, 1, 7, 5, 6, 9
      };

      sort(v, new Comparator<Integer>() {
         public int compare(Integer r, Integer s) {
            if (r < s) {
               return -1;
            }
            if (r > s) {
               return 1;
            }
            return 0;
         }
      });

      System.out.println(Arrays.toString(v));

      v = new int[] { 10, 8, 2, 3, 4, 1, 7, 5, 6, 9
      };

      sort(v, new Comparator<Integer>() {
         public int compare(Integer r, Integer s) {
            if (s < r) {
               return -1;
            }
            if (s > r) {
               return 1;
            }
            return 0;
         }
      });

      System.out.println(Arrays.toString(v));
   }

   public static void sort(int[] v, Comparator<Integer> comp) {
      for (int i = 0; i < v.length - 1; i++) {
         for (int k = i + 1; k < v.length; k++) {
            if (comp.compare(v[k], v[i]) < 0) {
               int t = v[i];
               v[i] = v[k];
               v[k] = t;
            }
         }
      }
   }
}

【讨论】:

    【解决方案2】:

    A 和 B 在比较时是字符串,因此它们不是数字相加,而是使用字符串连接组合。 CompareTo 然后查看字符串中的字符并进行比较。

    即如果 a = 1 和 b = 2,它实际上是 a ="1" 和 b="2" 所以 a+b="1"+"2" = "12"

    【讨论】:

    • 我们在这里处理的是 9 和 90 ,如果我们正常比较它,90 会比 9 更早,我们会有 909 作为答案...但是 990 更大。 ..这就是为什么要完成连接.....但是我的问题是比较的,这就是为什么我不能在 b+a 之前写 a+b
    • CompareTo 在后台评估字符串中的字符。这包括查看字符串的长度。它根据它们的 unicode 值比较两个字符串。更多信息:javatpoint.com/java-string-compareto
    猜你喜欢
    • 2019-05-01
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    相关资源
    最近更新 更多