我被要求解决低于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();
}
答案 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)时间,所以这里的时间是如何分解的:
所以,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--;
}
}
易于理解:)