We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2698. Find the Punishment Number of an Integer 预处理 + 回溯(Python/Java/C++/Go)
这周周赛第三题。这道题一看就知道直接暴力回溯。我还加了缓存memo,表示一个整数能对应的子串之和的集合。
class Solution { Map<Integer, Set<Integer>> memo = new HashMap<>(); public int punishmentNumber(int n) { int ans = 0; for (int i = 1; i <= n; i++) { int square = i * i; String squareStr = String.valueOf(square); if (isPunishNum(squareStr, i)) { ans += (i * i); } } return ans; } private boolean isPunishNum(String str, int val) { if (val < 0) { return false; } int all = Integer.parseInt(str); if (all == val) { return true; } if (memo.containsKey(all) && memo.get(all).contains(val)) { return true; } if (all < val) { return false; } boolean ans = false; for (int i = 1; i < str.length(); i++) { ans |= isPunishNum(str.substring(i), val - Integer.parseInt(str.substring(0, i))); } if (ans) { if (!memo.containsKey(all)) { memo.put(all, new HashSet<>()); } memo.get(all).add(val); } return ans; } }
分析下上面解法的时间复杂度,循环外层n,内层对于数字i,其长度是m=1+2log10(i),所以回溯时间是m * (2^m),最大也就是6 * (2^6),大概100层级,所以整个循环的时间复杂度是接近100n。
可以发现,去掉memo缓存后程序运行时间没什么变化,所以这层缓存没什么用。
第二种做法是预处理。既然数组最大长度只有1000,可以预先算好所有n的答案。这样循环外层固定为1000。其次经过上面的回溯时间复杂度分析,可以不需要memo缓存。
class Solution { int[] preSum = new int[1001]; public int punishmentNumber(int n) { for (int i = 1; i <= 1000; i++) { int square = i * i; preSum[i] = preSum[i - 1]; String squareStr = String.valueOf(square); char[] squareChar = squareStr.toCharArray(); if (isPunishNum(squareChar, i, 0, 0)) { preSum[i] += i * i; } } return preSum[n]; } private boolean isPunishNum(final char[] chars, final int sum, int p, int val) { if (p >= chars.length) { return val == sum; } int x = 0; for (int i = p; i < chars.length; i++) { x = x * 10 + (chars[i] - '0'); if (isPunishNum(chars, sum, i + 1, val + x)) { return true; } } return false; } }
以上是改进后的做法,优势在于:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
2698. Find the Punishment Number of an Integer
2698. Find the Punishment Number of an Integer
预处理 + 回溯(Python/Java/C++/Go)
这周周赛第三题。这道题一看就知道直接暴力回溯。我还加了缓存memo,表示一个整数能对应的子串之和的集合。
分析下上面解法的时间复杂度,循环外层n,内层对于数字i,其长度是m=1+2log10(i),所以回溯时间是m * (2^m),最大也就是6 * (2^6),大概100层级,所以整个循环的时间复杂度是接近100n。
可以发现,去掉memo缓存后程序运行时间没什么变化,所以这层缓存没什么用。
第二种做法是预处理。既然数组最大长度只有1000,可以预先算好所有n的答案。这样循环外层固定为1000。其次经过上面的回溯时间复杂度分析,可以不需要memo缓存。
以上是改进后的做法,优势在于:
The text was updated successfully, but these errors were encountered: