带有重复字母及其字母顺序的键

时间:2017-09-22 19:28:31

标签: java arrays

我有一个字符串,这是我的密钥,我有一种方法可以为该密钥中的每个字母分配一个代表字母顺序的数字。例如,如果我的密钥是“安全”一词,则输出为4, 1, 0, 6, 3, 2, 5, 7,我的代码如下:

String key = "Security".toLowerCase();
String alphabet = Arrays.stream(key.split("")).sorted().collect(Collectors.joining());
int[] order = new int[key.length()];
for (int i = 0; i < key.length(); i++) {
    order[i] = alphabet.indexOf(key.charAt(i));
}

我省略了在这里打印数组...

如果密钥不包含任何重复的字母,则此代码可以正常工作。但是,如果密钥变为“aardvark”,则输出变为0, 0, 5, 3, 7, 0, 5, 4,这是有问题的。我不知道如何解决这个问题。所需的输出应为0, 1, 5, 3, 7, 2, 6, 4

有什么建议吗?我是Java编程的新手,所以可能无法理解非常复杂的解决方案。

3 个答案:

答案 0 :(得分:1)

你可以通过一招来实现这个目标。你必须做一个多重排序。要在Java中实现此目的,请将两个数组的每个条目保存在地图的一个条目中。现在,您可以按键对此地图进行排序,并且还会对值进行排序。这就是诀窍。

String key = "Security".toLowerCase();
ArrayList<Integer> order = new ArrayList<>();
String[] alphabet = key.split(""));
SortedMap<String,Integer> map = new TreeMap<>();
for (int i = 0; i < key.length(); i++) {
    map.put(alphabet[i], i);
}
SortedMap<Integer, Integer> map2 = new TreeMap<>();
int i = 0;
for (Entry<Integer, Integer> entry : map.entrySet()) {
    map2.put(entry.getValue(), i++);
}
for (Entry<Integer, Integer> entry : map2.entrySet()) {
    order.add(entry.getValue());
}

这样的事情应该未经测试

地图填充了键中的每个字符,值是原始键字符串中的位置。因为它是一个有序的地图,所以地图按键排序。所以是由ord-no提升。来自角色。这些职位也在同一时刻排序。现在创建第二个地图,并在此刻填充分类位置和此位置的索引。因为它是一个有序的地图(再次),所以这些位置是有序的,而索引(地图条目的值)是字母表中的键。这个位置可以通过循环读出并保存在订单数组中。

答案 1 :(得分:1)

一种方法是做零&#34;零&#34;在使用它们时输出字母:

String key = "aardvark".toLowerCase();
String alphabet = Arrays.stream(key.split("")).sorted().collect(Collectors.joining());
System.out.println("alphabet: " + alphabet);
int[] order = new int[key.length()];
for (int i = 0; i < key.length(); i++) {
  order[i] = alphabet.indexOf(key.charAt(i));
  alphabet = alphabet.replaceFirst( ""+key.charAt(i), "0" ); //Zero out chars as they are used
  System.out.println(order[i]);
}

答案 2 :(得分:0)

这是一个面向对象的解决方案:

模拟&#34;字母表&#34;在它自己的类中,它主要与它所代表的字符的字母数字值相当,其次是它在&#34;键&#34;中的位置。串。字母表的标识(在equals()中实现)由其在&#34;键&#34;中的位置决定。字符串。

public class Alphabet implements Comparable<Alphabet> {

    private final char character;
    private final int position;       

    public Alphabet(char character, int position) {
        this.character = character;
        this.position = position;
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Alphabet) {
            return other != null && position == ((Alphabet) other).position;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(position);
    }

    @Override
    public int compareTo(Alphabet other) {

        int comparison = Character.compare(character, other.character);

        if (comparison != 0) {
            return comparison;
        } else {
           return Integer.compare(position, other.position);
        }
    }
}

现在,转换算法变得简单易用:

  1. 从输入/键字符串
  2. 创建List<Alphabet>
  3. 创建列表的副本,并根据Alphabet
  4. 中指定的顺序对其进行排序
  5. 创建&#34;排序数组&#34;通过迭代原始字母表列表和每个元素,查找字母表在排序列表中的索引
  6. 如下:

    public static int[] ordering(String input) {
    
        List<Alphabet> alphabet = new ArrayList<>();
    
        for (int i = 0; i < input.length(); i++) {
            alphabet.add(new Alphabet(input.charAt(i), i));
        }
    
        List<Alphabet> sorted = new ArrayList<>(alphabet);
        Collections.sort(sorted);
        int[] ordering = new int[input.length()];
    
        for (int i = 0; i < input.length(); i++) {
            ordering[i] = sorted.indexOf(alphabet.get(i));
        }
        return ordering;
    }
    

    使用

    进行测试
    String input1 = "security", input2 = "aardvark";
    
    System.out.println(input1 + ": " + Arrays.toString(ordering(input1)));
    System.out.println(input2 + ": " + Arrays.toString(ordering(input2)));
    

    产生

    security: [4, 1, 0, 6, 3, 2, 5, 7]
    aardvark: [0, 1, 5, 3, 7, 2, 6, 4]