查找花费时间到字符串S2

时间:2019-04-13 04:41:06

标签: java algorithm data-structures

想象一下,您有一个特殊的键盘,其中所有键都位于一行中。键盘上字符的布局由长度为26的字符串S1表示。S1的索引从0到25。最初的索引为0。要键入字符,我们需要移动所需字符的索引。将索引从i移到j所需的时间是| j-i |。其中||是绝对值。

给出字符串s1和s2,描述键入字符串s2所花费的时间。

给出两个字符串S1和S2,其中S1 = abcdeghijklmnopqrstuvwxyz

s2 = cba

并从索引0('A')开始,找到键入cba所需的时间。

index of c = 2
count = 2 - 0
count = 2 + 1 (c to b )
count = 2 + 1(c to b) + 1 (b to a)
count returned should be 4.

我确信通过运行两个循环可以很容易地二次实现这一点,但这不是一个有效的解决方案。有什么想法可以改善这个问题吗?

4 个答案:

答案 0 :(得分:2)

大编辑

实际上,根据定义,S1是固定长度并且不依赖于输入S2的事实意味着@Amiy的答案是正确的。由于indexOf仅在S1上运行,因此最多需要恒定的26个步骤。 O(26n) = O(n)。我的答案只是一个较低的常数,具体取决于变数,范围从1n2n


另一个编辑

对于一般情况,S1也是变量输入,我们不能做任何假设,请参阅O(nlogm)中@ user000001的哈希解决方案。


原始答案

如果您依靠对S1进行排序并且每个字符与其相邻字符的值相差1的事实,则可以只计算S2中字符之间的差并将其求和< / p>

例如:
S2 = cba

a插入S2以获取初始值:
S2 = acba

对于c1中的每个字符c2及其右邻S2
distance += |c1 - c2|


如果您不依赖于S1已排序的事实(可能正是您要找的东西),则可以将S1的值索引到数组中并应用与上述类似的算法:

例如:

S1 = "qwertyuiopasdfghjklzxcvbnm"
arr = array of size 26
let i = 0
for each character c in S1:
    arr[c - 'a'] = i++

然后,修改算法:

S2 = "cba"
let distance = 0
for each character c1 and its right-neighbour c2 in S2:
    distance += |arr[c1 - 'a'] - arr[c2 - 'a']|


两种算法都可以解决O(n)中的问题,而第一种使用O(1)空间,第二种使用O(n)空间。

答案 1 :(得分:1)

一种将复杂度从O(N ^ 2)降低到O(Nlog(N)的方法,是从字符串中创建HashMap。

类似这样的东西:

String s1 = "abcdeghijklmnopqrstuvwxyz";
String s2 = "cba";

Map<Byte, Integer> map = new HashMap<>();

int i = 0;
for (Byte b: s1.getBytes()) {
    map.put(b, i++);
}

int result = 0;
int previndex = 0;
for (Byte b: s2.getBytes()) {
    int currentindex = map.get(b);
    result += (int) Math.abs(currentindex - previndex);
    previndex = currentindex;
}

System.out.println("resutlt= " + result);

答案 2 :(得分:1)

这是Java中的算法:

String s1 = "abcdefghijklmnopqrstuvwxyz";
String s2 = "cba";

int pos = 0;
int time = 0;

for (int ind = 0;ind < s2.length(); ind++) {
    char cur_char = s2.charAt(ind);
    index = s1.indexOf(cur_char);
    time += Math.abs(index - pos);
    pos = index;
}

System.out.println("Time taken: " + time);

对于上述值,输出为:Time taken: 4

修改:
该算法的时间复杂度为O(n)
由于s1的长度是常数,因此设k。
并将字符串s2的长度ia变量设为n。
时间复杂度:O(nk)= O(n)[由于k为常数]

答案 3 :(得分:1)

这个更容易理解:

String s1 = "abcdefghijklmnopqrstuvwxyz";
String s2 = "cba";
int jumps = 0;

for(int i=0; i<s2.length();i++){

        if(i==0){
            jumps += s1.indexOf(s2.charAt(i));
        }else{
            jumps += Math.abs(s1.indexOf(s2.charAt(i)) - s1.indexOf(s2.charAt(i-1)));
        }
}
System.out.println("Total Jumps: "+jumps);

在这里,它使用循环查找s2s1的每个字符。第一次运行if块,然后运行else其余字符。对于s2中的每个字符,它将继续将跳跃/跳跃/花费的时间加到总数中,并在循环完成后返回您。

此外,它通过从我们所在位置的字符位置减去我们所在位置的字符位置来计算跳跃。简而言之,由于它从位置0开始,因此您可以这样计算:[(C-0)+(B-C)+(B-A)]