编写反向字符串O(N)时间复杂度和O(N)空间复杂度的程序

时间:2016-02-21 21:52:28

标签: java string algorithm reverse swap

我被要求解决低于N ^ 2时间复杂度和O(N)空间复杂度的以下问题:

为以下情况编写程序反向字符串:

输入: - “Hello World” 输出: - “olleH dlroW”

我试图弄清楚它,但无论我尝试什么,我都无法想出一个低于N ^ 2的时间复杂度,我的代码可以在下面看到,你有什么建议我怎么能想出一个线性时间的解决方案?

注意:不允许使用内置方法

 public static String stringReverser(String str) {
        if (str == null || str.isEmpty()) {
            throw new IllegalArgumentException();
        }
        if (str.length() < 2) {
            return str;
        }
        String[] strArr = str.split(" ");
        StringBuffer newHolder = new StringBuffer();
        for (int i = 0; i < strArr.length; i++) {
            int j = 0;
            int len = strArr[i].length();
            char[] newCharStr = strArr[i].toCharArray();
            while (j < len) {
                char temp = newCharStr[j];
                newCharStr[j] = newCharStr[len - 1];
                newCharStr[len - 1] = temp;
                len--;
                j++;
            }
            newHolder.append(String.valueOf(newCharStr));
            if(i != strArr.length-1){
                newHolder.append(" ");
            }
        }

        return newHolder.toString();
    }

4 个答案:

答案 0 :(得分:5)

看起来你想要反转字符串中的单词,而不是整个字符串。你走了:

public static String reverseWords(String str)
{
    char[] chars = str.toCharArray();
    int wstart=0;
    for (int pos=0;;pos++)
    {
        if (pos < chars.length && chars[pos]!=' ')
        {
            continue;
        }
        for (int wend=pos-1; wend>wstart; ++wstart,--wend)
        {
            char t=chars[wstart];
            chars[wstart]=chars[wend];
            chars[wend]=t;
        }
        if (pos>=chars.length)
        {
            break;
        }
        wstart=pos+1;
    }
    return String.valueOf(chars);
}

这是您可以找到的最快,最节省空间的版本。如果这是家庭作业,你的教授会知道你没有写作:)

然而,你在中写的那个满足了要求 - O(N)时间和O(N)空间 - 所以你可能想要转入那个。恭喜!

因为你似乎认为它需要O(N ^ 2)时间,所以这里的时间是如何分解的:

  • str.split:O(输出数组的大小+输出字符串的大小)= O(str.length()),即O(N)
  • 迭代字:O(字数)= O(N)
  • 创建和反转单词字符串:每个O(单词大小),总O(N)
  • newHolder.append:O(创建的字符串的总大小)= O(str.length())= O(N)
  • newHolder.toString():O(输出大小)= O(N)

所以,5 * O(N)= O(N) - 你很高兴。

答案 1 :(得分:2)

以下算法使用O(n)空间,并且将输入字符串重复两次(我相信它满足时间复杂度)。输入字符串的一次迭代是查找空格,另一次迭代是写出反转的字。

算法是这样的:

  • 找到第一个空格(跟踪空间的位置)
  • 以相反的顺序写下第一个单词(跟踪下一个单词的起始位置)
  • 重复直到字符串结尾

    public class ReverseEachWord {
    
    public static void main(String[] args) {
        String input = "Hello World";
        System.out.println(reverseEachWord(input));
    }
    
    public static String reverseEachWord(String input) {
    
        int len = input.length();
    
        char[] out = new char[len]; // O(n) space
        char[] in = input.toCharArray();
    
        int spacePos = 0;
        int activePos = 0;
    
        while (activePos < len) {
            spacePos = activePos+1;
            int spaceFound = -1;
            int offset = 0;
            while (spacePos < len) {
                if (in[spacePos] == ' ') {
                    out[spacePos] = ' ';
                    spaceFound = 0;
                    break;
                }
                spacePos++;
            }
            if (spaceFound < 0) {
                spacePos += spaceFound;
                offset = 1;
            }
    
            for (int i=0; i<(spacePos-activePos+offset); i++) {
                out[spacePos - i -1 - spaceFound] = in[i+activePos];
            }
            activePos = spacePos+1;
    
        }
    
        return Arrays.toString(out);
    }
    

    }

答案 2 :(得分:1)

您正在使用split(),这会为解决方案带来额外的O(N)时间复杂度。此外,你说内置方法不能使用!

这是一个伪代码供您试用。据我所知,它具有O(N)时间复杂度和O(N)空间复杂度。

i = 0, j = 0
for i = 0 to str.length:
    if str[i] == ' ':
        for k=i-1 to j:    // reverse looping
            print str[k]
        j = i + 1
// printing the last word
for k=i to j:
    print(s[k])

这是我对复杂性的直觉。外部循环给出O(N),并且内部循环对于每个单词是一次,因此它再次给出另一个O(N),意味着总复杂度是O(N)。至于空间,如果将字符存储在另一个数组而不是打印中,则需要一个大小为N的数组,其中N是源字符串的大小。因此空间复杂性也是O(N)。

这是伪代码的java实现:

public static String reverseIt(String str) {

    char[] source = str.toCharArray();
    char[] newArray = new char[source.length];

    int i = 0, j = 0, idx = 0;

    for(i = 0; i < source.length; i++) {
        if(source[i] == ' ') {
            for(int k = i-1; k >= j; k--, idx++) {
                newArray[idx] = source[k];
            }
            j = i + 1;
            newArray[idx++] = ' ';
        }
    }
    for(int k = i-1; k >= j; k--, idx++) {
        newArray[idx] = source[k];
    }

    return new String(newArray);
}

答案 3 :(得分:0)

public String reverse(String str)
{
char [] chars= str.toCharArray();
int end=chars.length-1, half_len = (int) Math.ceil(chars.length/2);

for(int i=0;i<half_len;i++)
{
    if(chars[i]==' ')
    {
        continue;
    }
    else
    {
        char t=chars[i];
        chars[i]=chars[end];
        chars[end]=t;
    }
    end--;
}
}

易于理解:)