找出由两个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
失败了。我该怎么办?
答案 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)
如果分析显示使用字符串很慢(或者您只是不想这样做),则可以修改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。
总而言之,一个非常方便的提醒是,有多种方法可以做事情,如果经常做的话,小事情就很重要......