【问题标题】:Write program for Reverse string O(N) time complexity and O(N) space complexity编写反向字符串 O(N) 时间复杂度和 O(N) 空间复杂度的程序
【发布时间】:2016-02-21 21:52:27
【问题描述】:

我被要求解决以下低于 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();
    }

【问题讨论】:

  • return new StringBuilder(str).reverse().toString();
  • 这是一道算法题,不允许使用内置方法

标签: java string algorithm reverse swap


【解决方案1】:

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

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) - 你可以开始了。

【讨论】:

    【解决方案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);
      }
      

      }

    【讨论】:

      【解决方案3】:

      您正在使用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);
      }
      

      【讨论】:

        【解决方案4】:
        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--;
        }
        }
        

        简单易懂:)

        【讨论】:

          猜你喜欢
          • 2015-05-25
          • 1970-01-01
          • 2021-04-14
          • 1970-01-01
          • 2019-12-09
          • 1970-01-01
          • 2011-07-09
          • 2013-10-20
          • 2022-01-20
          相关资源
          最近更新 更多