【问题标题】:Valid Palindrome, solution too slow for large input sizes有效回文,对于大输入大小的解决方案太慢
【发布时间】:2022-10-01 00:26:34
【问题描述】:

我遇到了一个名为 leetcode 的特定问题有效回文.我的代码适用于除最后一个测试用例 479/480 之外的所有测试用例。

在这个测试用例中,传入了一个长度为 106890 的字符串,但我的代码需要很长时间才能解决它。

我决定尝试采用不同的方法并使用StringBuilder 类来反转字符串,然后简单地使用reversedString.equals(originalString) 来比较它们是否是回文。这种方法解决了问题并通过了所有测试用例

为什么我的两个指针方法不起作用?为什么它在最后一个测试用例上失败了?

这是我的解决方案(两个指针)

class Solution {
    public static boolean isPalindrome(String s) {
        String fixedString = \"\";
        for (char c : s.toCharArray()) {
            if (Character.isDigit(c) || Character.isLetter(c)) {
                fixedString += c;
            }
        }
        fixedString = fixedString.toLowerCase();
        int i = 0;
        int j = fixedString.length() - 1;
        System.out.println(fixedString.toCharArray());
        while (i <= j) {
            if (fixedString.toCharArray()[i] != fixedString.toCharArray()[j]) {
                return false;
            }
            i += 1;
            j -= 1;
        }
        return true;
    }
}

这是我使用StringBuilder 的第二个解决方案。

public class Valid_Palindrome {

    public static void main(String args[]){
        System.out.println(isPalindrome(\"A man, a plan, a canal: Panama\"));
    }

    public static boolean isPalindrome(String s) {
        String fixedString = \"\";
        for(char c : s.toCharArray()){
            if(Character.isDigit(c) || Character.isLetter(c)){
                fixedString += c;
            }
        }
        fixedString = fixedString.toLowerCase();
        StringBuilder sb = new StringBuilder(fixedString);
        sb = sb.reverse();
        System.out.println(sb);
        return sb.toString().equals(fixedString);
    }
}

从技术上讲,由于使用StringBuilder,第二个解决方案不是应该慢得多吗?

如何优化我的第一个解决方案?

这是在我的 leetcode 中传递的输入字符串。

    标签: java string optimization stringbuilder palindrome


    【解决方案1】:

    在循环中执行字符串连接通常很慢。在第一个循环中使用 StringBuilder 来创建过滤后的字符串。

    StringBuilder sb = new StringBuilder(s.length());
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (Character.isLetterOrDigit(c))
            sb.append(Character.toLowerCase(c));
    }
    for (int i = 0, j = sb.length() - 1; i < j; i++, j--)
        if (sb.charAt(i) != sb.charAt(j))
            return false;
    return true;
    

    【讨论】:

    • 在两个指针解决方案上,我用 fixedString.append(c) 替换了我的 fixedString+= c 它仍然超时。
    • @KhandkarIslam 在我的回答中查看我的解决方案。
    • @Unmitigated 一个不错的解决方案,尤其是第二个循环,它只需要循环整个字符串的一半时间。通过更多的努力,您还可以摆脱StringBuilder
    【解决方案2】:

    不要建立或反转或做任何事物与字符串,除了迭代超过一半的字符。

    在伪代码中:

    • 遍历前半部分字符
    • 对于第 i 个字符,将其与第 (length - i - 1) 个字符进行比较
    • 如果不同,返回 false
    • 如果循环结束,返回真

    【讨论】:

      【解决方案3】:

      您的代码中有几个语句可能会减慢它的速度。

      1. fixedString += c;
        这将创建一个新的 StringBuilder 对象。 fixedString 的内容被复制到它。然后附加字符 (c)。然后将StringBuilder 转换为String,并将String 分配给变量fixedString
      2. if (fixedString.toCharArray()[i] != fixedString.toCharArray()[j])
        方法toCharArray 创建一个新的char[] 并将String 的内容复制到它。

        我建议您只创建一次char[] 并使用它。当然,您需要从原始字符串中删除非字母和非数字,并转换为小写。

        这是我对您的 [双指针] 解决方案的重写。
        (请注意,我假设 null 或空字符串不是回文。)

        public static boolean isPalindrome(String s) {
            if (s != null && !s.isEmpty()) {
                char[] chars = s.toCharArray();
                char[] temp = new char[chars.length];
                int count = 0;
                for (char c : chars) {
                    if (Character.isDigit(c) || Character.isLetter(c)) {
                        temp[count++] = Character.toLowerCase(c);
                    }
                }
                char[] letters = new char[count];
                System.arraycopy(temp, 0, letters, 0, count);
                int i = 0;
                int j = count - 1;
                System.out.println(letters);
                while (i <= j) {
                    if (letters[i] != letters[j]) {
                        return false;
                    }
                    i++;
                    j--;
                }
                return true;
            }
            return false;
        }
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-18
        • 2022-12-11
        • 2013-07-30
        • 1970-01-01
        • 2017-07-30
        • 2019-10-19
        • 1970-01-01
        • 2011-05-12
        相关资源
        最近更新 更多