- Identify the ordered answer range or sorted search domain.
- Write a predicate whose truth changes only once.
- Move the appropriate boundary after each midpoint check and return the final feasible position.
Code notes
- 74 lines of Python from the credited upstream file next-special-palindrome-number.py.
- The implementation visibly relies on sequence storage.
- No explicit loop blocks detected.
Complexity
Multiply the logarithmic number of midpoint checks by the cost of one predicate evaluation.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1234 5import bisect6 7 89def next_permutation(nums, begin, end):10 def reverse(nums, begin, end):11 left, right = begin, end-112 while left < right:13 nums[left], nums[right] = nums[right], nums[left]14 left += 115 right -= 116 17 k, l = begin-1, begin18 for i in reversed(xrange(begin, end-1)):19 if nums[i] < nums[i+1]:20 k = i21 break22 else:23 reverse(nums, begin, end)24 return False25 for i in reversed(xrange(k+1, end)):26 if nums[i] > nums[k]:27 l = i28 break29 nums[k], nums[l] = nums[l], nums[k]30 reverse(nums, k+1, end)31 return True32 33 34def precompute():35 def f(mask):36 result = []37 mid = ""38 for i in xrange(9):39 if mask&(1<<i) == 0:40 continue41 if (i+1)%2:42 if mid:43 return result, mid, False44 mid = str(i+1)45 result.extend([str(i+1)]*((i+1)2))46 return result, mid, True47 48 result = []49 for mask in xrange(1, 1<<9):50 left, mid, ok = f(mask)51 if not ok:52 continue53 while True:54 s = "".join(left)55 p = s+mid+s[::-1]56 if len(p) > MAX_LEN:57 break58 result.append(int(p))59 if not next_permutation(left, 0, len(left)):60 break61 result.sort()62 return result63 64 65MAX_LEN = 1666PALINDROMES = precompute()67class Solution(object):68 def specialPalindrome(self, n):69 """70 :type n: int71 :rtype: int72 """73 return PALINDROMES[bisect.bisect_right(PALINDROMES, n)]74