寻找回文的低效解决方案

时间:2017-02-15 22:55:41

标签: java algorithm

找出由两个n位数字的乘积制成的最大回文并返回mod 1337

从n = 1到n = 8

的输入
public class Solution {
    public int largestPalindrome(int n) {
    int[] arr = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};
    int max_palindrome = 0;
    for(int x = arr[n] - 1; x >= arr[n - 1]; x--){
        for(int y = arr[n] -1; y >= arr[n - 1]; y--){
            int maybe = x*y;
            if(is_Palindrome(maybe)){
                if(maybe > max_palindrome){
                    max_palindrome = maybe;
                }
            }
        }
    }
    return max_palindrome%1337;
    }

    public boolean is_Palindrome(int toCheck){
        char[] charArr = String.valueOf(toCheck).toCharArray();
        for(int i = 0; i < charArr.length; i++){
            if(charArr[i] != charArr[charArr.length - 1 - i]){
                return false;
            }
        }
        return true;
    }
}

由于时间问题,这在n=4失败了。我该怎么办?

2 个答案:

答案 0 :(得分:3)

您可以将内循环从当前外循环值开始减少:

 01234
0*****
1 ****
2  ***
3   **
4    *

这将为您提供所有对。那就是你需要(n *(n + 1))/ 2次而不是n ^ 2.

在你的检查回文功能中,你做了类似的超级工作:

您从右到左检查所有字符是否与对应物相等,但您可以在中间停止。因此,您现在只需要一半的比较操作。

如果可能小于您当前找到的最大回文数,您也可以完全跳过检查数字。目前你首先检查,然后你决定它是否更大。

运行时性能的最终结果是,一旦您到达的产品maybe小于您当前的候选回文,就会停止计算该行。由于您向后计数,此行将丢失:您将无法使用较小的数字来获得更高的产品。

您的代码也存在缺陷。高n值的乘积大于最大整数,并将创建负值。您必须将代码切换为long。

public class Solution {
    public long largestPalindrome(int n) {
        if( n==0 ) return 1;

        int[] arr = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};
        long max_palindrome = 0;
        for (long x = arr[n] - 1; x >= arr[n - 1]; x--) {
            for (long y = x; y >= arr[n - 1]; y--) {
                long maybe = x * y;
                if (maybe <= max_palindrome) {
                    break;
                }

                if (is_Palindrome(maybe)) {
                    max_palindrome = maybe;
                    System.out.printf("Palindrome: %dx: %d, y: %d%n", max_palindrome, x, y);
                }
            }
        }
        return max_palindrome % 1337;
    }

    public boolean is_Palindrome(long toCheck) {
        String cand = String.valueOf(toCheck);
        final int len = cand.length() - 1;
        final int maxIdx = len >> 1;
        for (int i = 0; i <= maxIdx; i++) {
            if (cand.charAt(i) != cand.charAt(len - i))
                return false;
        }
        return true;
    }
}

感谢您提出的问题: - )

答案 1 :(得分:2)

@thst已经指出了一些很好的优化。我已经尝试过他的解决方案了,但是在n = 5时它仍然运行得很慢。

如果分析显示使用字符串很慢(或者您只是不想这样做),则可以修改is_Palindrome()以使用整数运算。我不会显示所有代码,只是大纲和提示:

public JsonResult ReviewedAndApproved(long ParentPositionID, long YearID, long YearCycleID, string UserID)
    {
        string strStat = string.Empty;
        string strError = string.Empty;
        string strProcessStatus = "ProcessStat.Incomplete";
        string strUserID = User.Identity.Name.Split('\\')[1];

        if (strUserID == UserID)
        {
            var positionAssMngr = new PositionAssignmentManager();
            var dtoList = new List<PositionAssignmentDto>();
            string ActionTaken = "Reviewed and Approved";

            dtoList = positionAssMngr.GetTeamStuctureMembers(ParentPositionID, YearID, YearCycleID);

            if (positionAssMngr.ReviewedAndApprove(dtoList, ActionTaken) == true)
            {
                strStat = "Success";
                strProcessStatus = "CompletE";
            }
            else
            {
                strStat = "Failed";
                strError = "Approved and Reviewed process failed!"; 
            }
        }
        else
        {
            strStat = "Failed";
            strError = "User ID not matched with current user!";
        }

        return Json(new { Status = strStat, ErrorMessage = strError, ProcessStatus = strProcessStatus }, JsonRequestBehavior.AllowGet);
    }


    public ActionResult TeamStructureConfirmation(long ParentPositionID)
    {
        var model = new List<PositionAssignmentDto>();
        //var posMngr = new PositionAssignmentManager();

        //if (ProcessStatus == "CompletE")
        //    ViewBag.Validated = true;
        //else
        //    ViewBag.Validated = false;

        //model = posMngr.GetTeamStuctureMembers(ParentPositionID, YearID, YearCycleID);
        return View("Team/ConfirmedTeamStructure", model); 
    }

确定。将一些评论写入答案:

我在C中实现了@ thst的解决方案。对于使用public boolean is_Palindrome(long toCheck) { // TODO // Figure out how many digits toCheck has and the value of the // most significant. e.g. "2345" has a length of 4 and the value // of the most significant is 1000. // You may know these from your array and so can pass them in... while(length > 1) { // In example 2345: left = 2, right = 5. long left = toCheck / msdValue; long right = toCheck % 10; if (left != right) { return false; } // TODO // So they matched eh? You need to remove the digits already checked // from toCheck. Least significant is easy: / 10. // Most significant needs to use the msdValue (and something else) // You stripped out 2 digits, so your length and the size of // the msdValue need to change to reflect that. // length -= 2; msdValue /= 100; } // We've done early return as soon as we found a pair of digits that // didn't match, so if we get here all the digits matched and so we've // got a palindrome. // return true; } 的字符串版本,n = 7的时间约为45秒。当字符串计算被上面的我的实现替换时,时间一直在16秒左右 - 让我们称之为3倍的加速。

然后我用一个执行表查找的函数替换了我的循环。

sprintf

这将时间缩短到7.5秒 - 这比“普通数学”快两倍,比原始字符串实现快6倍。

用原位版本而不是函数调用替换int numDigits(long num, long* msdValue) { if (num >= 1000000000000000) { *msdValue= 1000000000000000; return 16; } // and so on... 会产生一个小但可衡量的差异:始终在5.9秒内运行 - 让它称之为6秒。

请记住:这是在C中,因此结果可能不适用于Java。

总而言之,一个非常方便的提醒是,有多种方法可以做事情,如果经常做的话,小事情就很重要......