Welcome to Subscribe On Youtube
3766. Minimum Operations to Make Binary Palindrome
Description
You are given an integer array nums.
For each element nums[i], you may perform the following operations any number of times (including zero):
- Increase
nums[i]by 1, or - Decrease
nums[i]by 1.
A number is called a binary palindrome if its binary representation without leading zeros reads the same forward and backward.
Your task is to return an integer array ans, where ans[i] represents the minimum number of operations required to convert nums[i] into a binary palindrome.
Example 1:
Input: nums = [1,2,4]
Output: [0,1,1]
Explanation:
One optimal set of operations:
nums[i] |
Binary(nums[i]) |
Nearest Palindrome |
Binary (Palindrome) |
Operations Required | ans[i] |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 1 | Already palindrome | 0 |
| 2 | 10 | 3 | 11 | Increase by 1 | 1 |
| 4 | 100 | 3 | 11 | Decrease by 1 | 1 |
Thus, ans = [0, 1, 1].
Example 2:
Input: nums = [6,7,12]
Output: [1,0,3]
Explanation:
One optimal set of operations:
nums[i] |
Binary(nums[i]) |
Nearest Palindrome |
Binary (Palindrome) |
Operations Required | ans[i] |
|---|---|---|---|---|---|
| 6 | 110 | 5 | 101 | Decrease by 1 | 1 |
| 7 | 111 | 7 | 111 | Already palindrome | 0 |
| 12 | 1100 | 15 | 1111 | Increase by 3 | 3 |
Thus, ans = [1, 0, 3].
Constraints:
1 <= nums.length <= 50001 <= nums[i] <= 5000
Solutions
Solution 1: Preprocessing + Binary Search
We observe that the range of numbers given in the problem is only $[1, 5000]$. Therefore, we directly preprocess all binary palindromic numbers in the range $[0, 2^{14})$ and store them in an array, denoted as $\textit{p}$.
Next, for each number $x$, we use binary search to find the first palindromic number greater than or equal to $x$ in the array $\textit{p}$, denoted as $\textit{p}[i]$, as well as the first palindromic number less than $x$, denoted as $\textit{p}[i - 1]$. Then, we calculate the number of operations required to convert $x$ to these two palindromic numbers and take the minimum value as the answer.
The time complexity is $O(n \times \log M)$, and the space complexity is $O(M)$. Where $n$ is the length of the array $\textit{nums}$, and $M$ is the number of preprocessed binary palindromic numbers.
-
class Solution { private static final List<Integer> p = new ArrayList<>(); static { int N = 1 << 14; for (int i = 0; i < N; i++) { String s = Integer.toBinaryString(i); String rs = new StringBuilder(s).reverse().toString(); if (s.equals(rs)) { p.add(i); } } } public int[] minOperations(int[] nums) { int n = nums.length; int[] ans = new int[n]; Arrays.fill(ans, Integer.MAX_VALUE); for (int k = 0; k < n; ++k) { int x = nums[k]; int i = binarySearch(p, x); if (i < p.size()) { ans[k] = Math.min(ans[k], p.get(i) - x); } if (i >= 1) { ans[k] = Math.min(ans[k], x - p.get(i - 1)); } } return ans; } private int binarySearch(List<Integer> p, int x) { int l = 0, r = p.size(); while (l < r) { int mid = (l + r) >>> 1; if (p.get(mid) >= x) { r = mid; } else { l = mid + 1; } } return l; } } -
vector<int> p; auto init = [] { int N = 1 << 14; for (int i = 0; i < N; ++i) { string s = bitset<14>(i).to_string(); s = s.substr(s.find_first_not_of('0') == string::npos ? 13 : s.find_first_not_of('0')); string rs = s; reverse(rs.begin(), rs.end()); if (s == rs) { p.push_back(i); } } return 0; }(); class Solution { public: vector<int> minOperations(vector<int>& nums) { int n = nums.size(); vector<int> ans(n, INT_MAX); for (int k = 0; k < n; ++k) { int x = nums[k]; int i = lower_bound(p.begin(), p.end(), x) - p.begin(); if (i < (int) p.size()) { ans[k] = min(ans[k], p[i] - x); } if (i >= 1) { ans[k] = min(ans[k], x - p[i - 1]); } } return ans; } }; -
p = [] for i in range(1 << 14): s = bin(i)[2:] if s == s[::-1]: p.append(i) class Solution: def minOperations(self, nums: List[int]) -> List[int]: ans = [] for x in nums: i = bisect_left(p, x) times = inf if i < len(p): times = min(times, p[i] - x) if i >= 1: times = min(times, x - p[i - 1]) ans.append(times) return ans -
var p []int func init() { N := 1 << 14 for i := 0; i < N; i++ { s := strconv.FormatInt(int64(i), 2) if isPalindrome(s) { p = append(p, i) } } } func isPalindrome(s string) bool { runes := []rune(s) for i := 0; i < len(runes)/2; i++ { if runes[i] != runes[len(runes)-1-i] { return false } } return true } func minOperations(nums []int) []int { ans := make([]int, len(nums)) for k, x := range nums { i := sort.SearchInts(p, x) t := math.MaxInt32 if i < len(p) { t = p[i] - x } if i >= 1 { t = min(t, x-p[i-1]) } ans[k] = t } return ans } -
const p: number[] = (() => { const res: number[] = []; const N = 1 << 14; for (let i = 0; i < N; i++) { const s = i.toString(2); if (s === s.split('').reverse().join('')) { res.push(i); } } return res; })(); function minOperations(nums: number[]): number[] { const ans: number[] = Array(nums.length).fill(Number.MAX_SAFE_INTEGER); for (let k = 0; k < nums.length; k++) { const x = nums[k]; const i = _.sortedIndex(p, x); if (i < p.length) { ans[k] = p[i] - x; } if (i >= 1) { ans[k] = Math.min(ans[k], x - p[i - 1]); } } return ans; }