繁体   English   中英

字符串中的最后一个重复字符

[英]Last repeating character in a string

我正在寻找一种解决方案,以找到字符串中最后一个重复的字符,该字符串显示“您今天好吗”,应该以y作为答案。 我尝试使用链接哈希映射来获取有序的插入,但是我将d作为最后重复的插入。

String testString  =  "how are you doing today";

    char[] testStringArray = testString.toCharArray();
    Map<Character,Integer> map = new LinkedHashMap<>();

    for( char i : testStringArray) {
     if (!(i==' ')) {
    if(map.containsKey(i) ) {
        map.put(i, map.get(i)+1);
    } else {
        map.put(i, 1);
    }
     }
    }

    System.out.println(map);

    List<Entry<Character, Integer>> list = new ArrayList<>(map.entrySet());
    ListIterator<Entry<Character, Integer>> it = list.listIterator(list.size());    

    while(it.hasPrevious()) {
        if(it.previous().getValue() > 1)
            System.out.println(it.previous().getKey());


    }
}

感谢帮助。

此代码从最后一个字符开始扫描,并检查它是否存在于第一个字符之前的其余子字符串中:

String str = "how are you doing today";
int len = str.length();
int i = len - 1;
for (; i >= 1; i--) {
    if (str.substring(0, i).contains(str.charAt(i) + "")) {
        break;
    }
}
if (i == 0) {
    System.out.println("no repeating character");
} else
    System.out.println(str.charAt(i));

您可以使用使用Set的简单方法。 从String的char数组中读取元素后,请继续将其添加到Set (使用toCharArray() ),如果add()操作的返回值为false,则意味着该元素已被添加。 保留一个包含“最新的最后一个元素”的char变量。 只需在循环结束时打印即可。

一个简单的解决方案是向后遍历字符,并使用lastIndexOf查找该字符的先前位置:

for (int i = testString.length() - 1; i > 0; --i) {
  char ch = testString.charAt(i);
  if (testString.lastIndexOf(ch, i - 1) != -1) {
    return ch;
  }
}
// Handle no repeating character found.

发生这种情况是因为LinkedHashMap保持加法顺序,并且y在给定字符串的d之前插入,并且当您从最后一次进行迭代时,它首先读取d

为了实现你想要的,我建议

  1. 从末尾读取您的字符串,然后将count插入LinkedHashMap中
  2. 从开始迭代LinkedHashMap以获得所需的输出。

希望这可以帮助。

您可以使用ArrayList或Set代替LinkedHashMap来使用此代码,没有必要。 这是我的代码:

public static Character getLastRepeatingCharacter(String src) {
    Character defaultChar = null;
    char[] srcCharArr = src.toCharArray();
    List<Character> list = new ArrayList<Character>();
    final int length = srcCharArr.length;
    for(int idx = 0; idx < length; idx++) {
        if (srcCharArr[idx] == ' ') {
            continue;
        }
        if (list.contains(srcCharArr[idx])) {
            defaultChar = srcCharArr[idx];
        }else {
            list.add(srcCharArr[idx]);
        }
    }
    if (list.size() == length) {
        defaultChar = srcCharArr[length-1];
    }
    return defaultChar;
}

您发布的代码中有两个错误:1)在LinkedHashMap排序,以及2)在迭代器循环中两次调用previous()

要从LinkedHashMap获得所需的顺序,您需要插入顺序。 但是更新映射中已经存在的值不会更改插入顺序。 规格

请注意,如果将密钥重新插入到映射中,则插入顺序不会受到影响。 (如果在调用之前m.containsKey(k)将立即返回true时调用了m.put(k,v),则将密钥k重新插入到映射m中。)

要解决此问题,您必须删除条目并再次插入。 代替:

    map.put(i, map.get(i) + 1);

你必须做:

    int old = map.get(i);
    map.remove(i);
    map.put(i, old + 1);

第二个问题是,您在向后迭代的迭代器循环中调用了previous()两次。 找到所需条目后,这会产生副作用,即再次推进迭代器。 您需要缓存previous()的结果并使用两次。 因此,代替:

    while (it.hasPrevious()) {
        if (it.previous().getValue() > 1)
            System.out.println(it.previous().getKey());
    }

您需要执行以下操作:

    while (it.hasPrevious()) {
        Entry<Character, Integer> prev = it.previous();
        if (prev.getValue() > 1)
            System.out.println(prev.getKey());
    }

(我怀疑您可能已经找到并修复了此问题,因为有了此修复程序,但没有LinkedHashMap修复程序,结果是d与您所看到的匹配。)

从根本上讲,我认为您采用的是正确的方法。 本质上是这样的:

  1. 生成字符串中字符出现频率的直方图; 接着
  2. 向后迭代以找到频率大于1的最后一个字符,这意味着它是重复的。

一种简化的变体是迭代从字符串中向后获取字符,然后在映射中查找以找到频率大于1的第一个字符字符串保持顺序,因此映射不必如此。 因此,您可以避免使用LinkedHashMap和维护其插入顺序所需的额外工作。 您将执行以下操作:

    for (int i = testString.length() - 1; i >= 0; i--) {
        char ch = testString.charAt(i);
        if (map.containsKey(ch) && map.get(ch) > 1) {
            System.out.println(ch);
        }
    }

事实证明,使用Java 8 lambda和流可以使用更简单的方法来完成这两种操作。 首先,在给定字符串input的情况下,生成字符出现的直方图(频率图),请执行以下操作:

    Map<Character, Long> hist =
        input.chars()
             .mapToObj(ch -> (char)ch)
             .filter(ch -> ch != ' ')
             .collect(groupingBy(ch -> ch, counting()));

这里的皱纹是, chars()方法返回一个IntStream与每个char包含在值int 因此,必须将其转换为mapToObj()中的char才能将其转换为Stream<Character> 请注意,我依赖于java.util.stream.Collectors.*静态导入来获取简洁的分组/计数收集器。

获得直方图后,就可以再次串流字符,并使用reduce()技巧获取最后一个元素:

           input.chars()
                .mapToObj(ch -> (char)ch)
                .filter(ch -> ch != ' ')
                .filter(ch -> hist.get(ch) > 1L)
                .reduce((a, b) -> b);

放在一起,您将拥有:

Optional<Character> lastRepeat(String input) {
    Map<Character, Long> hist =
        input.chars()
             .mapToObj(ch -> (char)ch)
             .filter(ch -> ch != ' ')
             .collect(groupingBy(ch -> ch, counting()));
    return input.chars()
                .mapToObj(ch -> (char)ch)
                .filter(ch -> ch != ' ')
                .filter(ch -> hist.get(ch) > 1L)
                .reduce((a, b) -> b);
}

这将返回一个Optional其中包含字符串中的最后一个重复的字符;如果没有重复的字符,则返回一个空的Optional

    String str="how are you doing today";


    char charArr[]=str.toCharArray();

    HashMap<Character,Integer> hMap=new HashMap();


    for(int i=0;i<charArr.length;i++)
    {
        if(hMap.containsKey(charArr[i]))
        {
            int count=hMap.get(charArr[i]);
            hMap.put(charArr[i],count+1);
        }else
        {
            hMap.put(charArr[i], 1);
        }
    }
    System.out.println(hMap);
    for(int i=charArr.length-1;i>=0;i--)
    {
        if(hMap.get(charArr[i])>1)
        {
            System.out.println("The Last Repeated Character is :"+charArr[i]);
            break;
        }
    }

输出:

    { =4, a=2, d=2, e=1, g=1, h=1, i=1, n=1, o=4, r=1, t=1, u=1, w=1, y=2}

    The Last Repeated Character is : y

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM