打印范围为 1 到 n 内具有交替模式位的数字
交替位模式意味着在数字中交替位置放置 0 和 1,即没有两个 0 或 1 放在一起。例如,10 的二进制表示形式为 (1010)2,它具有交替位模式,因为 0 和 1 相互隔开。
问题陈述
给定一个整数 N。找到 1 到 N 范围内所有位模式交替的整数。
示例 1
Input: 10
Output: 1, 2, 5, 10
解释
$\mathrm{(1)_{10} = (1)_2, (2)_{10} = (10)_2, (5)_{10} = (101)_2, (10)_{10} = (1010)_2}$
示例 2
Input: 31
Output: 1, 2, 5, 10, 21
解释
$\mathrm{(1)_{10} = (1)_2, (2)_{10} = (10)_2, (5)_{10} = (101)_2, (10)_{10} = (1010)_2, (21)_{10} = (10101)_2}$
方法 1:检查交替模式
解决此问题的朴素方法是检查 1 到 n 范围内的每个数字,查看其位模式是否交替。
这可以通过以下方式完成:
为了检查一个数字是否具有交替位模式,我们可以使用 AND 操作的真值表来检查连续位是否不同。
伪代码 -
procedure checkAltPattern (num) temp = num count = 0 while (temp) count = count +1 num = num >> 1 end while for i = 0 to count - 2 iTh = num >> i i2Th = num >> (i + 2) if ((iTh & 1) != (i2Th & 1)) ans = FALSE end if end for ans = TRUE end procedure procedure numbers (num) ans [] for i = 1 to num if checkAltPattern = TRUE ans.add(i) end if end for end procedure
示例
在以下程序中,我们检查 1 到 N 范围内的每个数字,查看它们是否具有交替位模式,方法是检查在每个交替位置是否存在相同的位。
#include <bits/stdc++.h> using namespace std; // Function to check if the number has alternate pattern bool checkAltPattern(int num){ int temp = num, count = 0; // Counting total bits of the number by using the right shift operator while (temp) { count++; // Right shift of a number shift all the bits one position right temp >>= 1; } // For every alternate position checking if bits are same for (int i = 0; i < (count - 1); i++) { int iTh = num >> i, i2Th = num >> (i + 2); // iTh & 1 gives the bit at ith position // i2Th &N1 gives the bit at (i+2)th position // If both bits are not same then bits pattern is not alternate if ((iTh & 1) != (i2Th & 1)) { return false; } } return true; } vector<int> numbers(int num){ // Initializing an array to add numbers with alternate bit pattern vector<int> ans; for (int i = 1; i <= num; i++){ if (checkAltPattern(i)){ ans.push_back(i); } } return ans; } int main(){ int N = 50; cout << "Numbers in range 1 to " << N << " having alternate bit pattern : "; vector<int> res = numbers(N); for (int i = 0; i < res.size(); i++){ cout << res[i] << " "; } return 0; }
输出
Numbers in range 1 to 50 having alternate bit pattern : 1 2 5 10 21 42
时间复杂度 - O(nlogn),因为对于每个数字,我们都会检查交替模式,这需要 O(logn) 时间,因为 logn 是表示该数字的位数。因此,总时间为 O(logn + logn + … n 次) = O(nlogn)
空间复杂度 - O(1),因为没有使用额外的空间。
方法 2:从 1 生成数字
解决此问题的优化且更好的方法是从第一个具有交替模式的数字开始,然后连续交替地添加 0 和 1。
要向右侧添加 0,请使用左移运算符。
要向右侧添加 1,请先进行左移,然后使用 XOR 运算符添加 1。
伪代码 -
procedure addZero (pass) pass = pass << 1 ans = pass end procedure procedure addOne (pass) pass = pass << 1 pass = pass ^ 1 ans = pass end procedure procedure numbers (N) ans [] int num = 1 ans.add (num) while (1) num = addZero (num) if (num > N) break else ans.add (num) end if num = addOne (num) if (num > N) break else ans.add (num) end if end while end procedure
示例
在以下程序中,addZero() 函数在 LSB 位置添加 0,addOne() 函数在 LSB 位置添加 1。
#include <bits/stdc++.h> using namespace std; int addZero(int pass){ // Left shift puts 0 at LSB position pass = pass << 1; return pass; } int addOne(int pass){ // Left shift puts 0 at LSB position pass = pass << 1; // XOR with 1 sets the LSB position pass = pass ^ 1; return pass; } vector<int> numbers(int N){ // Initializing an array to add numbers with alternate bit pattern vector<int> ans; // First number with alternate bit pattern is 1 int num = 1; ans.push_back(num); while (1) { num = addZero(num); // If on adding 0, num is greater than N then leave loop if (num > N) { break; } else{ ans.push_back(num); } num = addOne(num); // If on adding 1, num is greater than N then leave loop if (num > N){ break; } else{ ans.push_back(num); } } return ans; } int main(){ int N = 50; cout << "Numbers in range 1 to " << N << " having alternate bit pattern : "; vector<int> res = numbers(N); for (int i = 0; i < res.size(); i++){ cout << res[i] << " "; } return 0; }
输出
Numbers in range 1 to 50 having alternate bit pattern : 1 2 5 10 21 42
时间复杂度 - O(logn)
空间复杂度 - O(1)
结论
总之,为了找到具有交替位模式的数字,优化的方案是从 1 开始生成数字本身,通过左移然后设置和取消设置 LSB 位置。这种方法是最优化和最优的。