【问题标题】:Turn duplicates into distinct letters in a String [closed]将重复项转换为字符串中的不同字母[关闭]
【发布时间】:2021-10-12 20:28:46
【问题描述】:

我们将得到一个字符串 s。假设例如“creepfe”。我们要做的是删除重复的,而是在该位置添加一个新字母,并且新字母必须是按字母顺序在重复字母旁边可用的不同字母。所以它是这样的:

creepfe 到 crefpfe -- 第一个 e 是不同的,第二个 e 更改为 f,这与此不同。

crefpfe 到 crefpge -- 第二个 f 更改为 g,因为我们之前已经有了 f。

crefpge 到 crefpgf -- 因为 e 已经存在。

现在我们又得到了 f duplicate ,所以把它改成 crefpgg ,这又得到了 g duplicate 所以最后我们到达了 "crefpgh" ,它有所有不同的字母。

最近开始学习java,很欣赏一个工作代码,但是真正需要一个好的算法。

编辑:是的,大写字母也算作重复。而且字符串长度限制在 10-15,所以不用担心用完不同的字母。

【问题讨论】:

  • 大写字母呢?这算作重复吗?
  • 是的,大写字母计入重复!
  • 似乎这是集合的任务。您是否尝试过对字符串中的字符使用 set?
  • 这里是初学者,除了暴力破解之外不知道如何进行(编写一个函数来检查字符串中是否存在一个字母,如果存在则添加下一个字母。然后再重复一次)真的需要一个好主意降低复杂性。
  • ^ 好吧,使用 set 是因为检查之前是否已经看到一个字母( contains() )是一个常数 O(1) 时间复杂度。

标签: java string algorithm data-structures


【解决方案1】:

这里有一个解决方案。如果有重复,我使用递归左移字母。我还回去重新编写了我的代码以包含 MBo 提到的集合。它不是最有效的,但它是您等待更有经验的 SO 成员建议的开始

public class tester {
    public static void main(String[] args){
        //Application.launch(testclass.class, args);
        String str = "creepFeZZ";

        System.out.println(processStr(str));

    }

    public static String processStr(String str){
        StringBuilder sb = new StringBuilder();
        HashSet<String> seen = new HashSet<>();

        insertStr(sb, seen, String.valueOf(str.charAt(0)));

        for (int i=1; i<str.length(); i++){
            char currentchar = str.charAt(i);
            char processedchar = goNext(seen, currentchar);
            insertStr(sb, seen, String.valueOf(processedchar));
        }

        //System.out.println(seen.toString());

        return sb.toString();
    }

    private static void insertStr(StringBuilder sb, HashSet seen, String str){
        seen.add(str.toLowerCase());
        sb.append(str);
    }

    private static char goNext(HashSet seen, char c){
        if (c>= 65 && c<=90){
            //if uppercase letter, check if contains lowercase version
            if (seen.contains(String.valueOf((char)(c+32)))){
                c = goNext(seen, (char)(c+1));
            }
            //any left shifting will overflow back to A
            return (char) ((c -(int) 'A') % 26 +(int) 'A');
        }else{
            //if lowercase letter, just check if contains
            if (seen.contains(String.valueOf((char)(c)))){
                c = goNext(seen, (char)(c+1));
            }
            //any left shifting will overflow back to a
            return (char)((c-(int) 'a') % 26 +(int) 'a');
        }
    }
}

这给出了以下输出: crefpGhZA

【讨论】:

  • 这绝对是一个好的开始。集合似乎是维护可见元素的好主意。我将研究这个想法,因为我不知道更有经验的人是否会回答这个问题,因为它得到了反对票。无论如何谢谢!
【解决方案2】:
  • 查找字符串包含重复项的位置。对此有多种方法。您可以通过 Google 找到适合您方法的最有效的方法。
  • 按字母顺序生成下一个字符。下面的代码展示了如何做到这一点
String value = "C";
int charValue = value.charAt(0);
String next = String.valueOf( (char) (charValue + 1));
System.out.println(next);
  • 重复该过程,直到没有更多重复项(当没有更多重复项时,有一个 while 循环中断)

【讨论】:

  • 问题是如果生成的字符已经存在于字符串中怎么办?就像在步骤 "crefpge to crefpgf -- 因为 e 已经存在。现在我们又得到了 f duplicate ,所以把它改成 crefpgg ,这又得到 g duplicate 所以最后我们到达 "crefpgh" ,它有所有不同的字母 " 。一次又一次地检查重复并一次又一次地更改似乎比我想象的要复杂。本质上,问题是直接生成下一个字母表,而无需检查它是否已经出现在我的视图中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-31
  • 2019-12-01
  • 1970-01-01
  • 2021-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多