There are some definite symbols that indicate fixed numbers. Note how we translate number 4 in Roman. $IV$ means 5-1, while if $VI$ it is 5+1.
Problem reduces to just traversing the symbol and adding and subtracting according the priority.
class Solution {
public:
map<char,int> mp;
void init() {
// Can't be initialised in global scope.
mp['I'] = 1 ;
mp['V'] = 5 ;
mp['X'] = 10 ;
mp['L'] = 50 ;
mp['C'] = 100 ;
mp['D'] = 500 ;
mp['M'] = 1000 ;
}
int romanToInt(string s) {
init(); // C++ requires a type specifier for all declaration.
int n = s.size();
int res = 0;
for (int i = 0; i < n-1; i++) {
// Get the corresponding value of symbol.
if(mp[s[i]] >= mp[s[i+1]])
res += mp[s[i]];
else
res -= mp[s[i]];
}
res += mp[s[n-1]];
return res;
}
};
Convert other way now :)
Note : Take a look at the upper bound given in description (4k).
class symbolMap {
public:
symbolMap() {
m.resize(1001);
m[1] = "I";
m[4] = "IV";
m[5] = "V";
m[9] = "IX";
m[10] = "X";
m[40] = "XL";
m[50] = "L";
m[90] = "XC";
m[100] = "C";
m[400] = "CD";
m[500] = "D";
m[900] = "CM";
m[1000] = "M";
}
string getSymbol (int val) {
return m[val];
}
vector<int> getAllValues() {
return {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
}
private:
vector<string> m;
};
class Solution {
public:
string intToRoman(int num) {
symbolMap sm;
vector<int> vals = sm.getAllValues();
string res = "";
// Divide in decreasing order
int m = vals.size();
for(int i = m-1; i >= 0; i--) {
int q = num/vals[i];
while(q--) {
res += sm.getSymbol(vals[i]);
}
num = num%vals[i];
}
return res;
}
};
Practice : AND, OR , XOR operations.
AD HOC : Next Permutation of a sorted sequence.
Bitwise operator :
binary operator AND &
, OR |
, XOR ^
unary operator left shift <<
, right shift >>
Note : $a \oplus a =0$ and $a\oplus 0 = a$ .
so if there is any number which doesn’t repeat twice will be left after doing cumulative xor on entire array.
int singleNumber(vector<int>& nums) {
int res = nums[0];
int n = nums.size();
for(int i = 1; i < n; i++)
res ^= nums[i];
return res;
}
Similar to maintaining a prefix array sum.
Typically Brute force will be O(nq) : ~ $10^8$ easy TLE
but with precomputation O(1) , and reasonable because only involves lookup queries.
vector<int> xorQueries(vector<int>& arr, vector<vector<int>>& queries) {
int n = arr.size();
vector<int> pre(n+1,0);
int run = 0;
for(int i = 0; i < n; i++)
run ^= arr[i];
pre[i+1] ^= run;
int m = queries.size();
vector<int> ans(m);
for(int i = 0; i < m; i++)
ans[i] = pre[queries[i][1]+1] ^ pre[queries[i][0]];
return ans;
}
Number of Steps to Reduce a Number in Binary Representation to One
Notes
Simulation is not preferred for solution. Operate on the boolean representation.
Remove all zeroes until u see a one ( from right to left ~ removing even) as we see 1 we keep inverting until we see new 0 (adding 1).
Keep doing this. Again we have pruned above simulation but original problem is counting simulation not simulate.
Note : each zero from rightmost costs 1 operation, first immediate 1 costs 2 operation, all subsequent 1 will cost 1. Now next set of zeroes costs 2.
Now we abstracted simulation to counting problem.
stop when number becomes 1.
int numSteps(string s) {
int n = s.size(), i;
bool one_seen = false;
int first_one_idx = -1;
int res = 0;
for(i = n-1; i >=0; i--) {
// if not seen a one
if(!one_seen) {
if(s[i] =='0')
res++;
else {
res+=2;
one_seen = true;
first_one_idx = i;
}
}
else {
if(s[i] == '1')
res++;
else
res+=2;
}
}
return first_one_idx == 0 ? res-2:res;
}
T = (S & 1<<j)
S|=(1<<j)
S &= ~(1<<j)
S^= (1<<j)
T=(S & (-S))
S=(1<<n)-1
Additional functions
The g++ compiler provides the following functions for counting bits:
__builtin_clz(x)
: # zeros at the beginning (count leading zeros)__builtin_ctz(x)
: # zeros at the end (count trailing zeros)__builtin_popcount(x)
: # ones in a number.__builtin_parity(x)
: # the parity (even/odd) of the number of ones.Minimum flips to make a OR b Equal to c
a OR b = c
Here are there are 2 cases for each bit
a_ bit | b_ bit == c_bit : Don’t do anything when OR of ith bit is same
OR is different so we check c_bit
c_bit = 1 we ADD 1
c_bit = 0 then we see the table
c_bit | a_bit | b_bit | cost |
---|---|---|---|
0 | 0 | 1 | 1 |
0 | 1 | 0 | 1 |
0 | 1 | 1 | 2 |
1 | 0 | 0 | 1 |
Simply a_bit & b_bit == 1(this is wrong, remember what ai & bi is :) cost : 2 else cost 1.
int minFlips(int a, int b, int c) {
// Iterate bit by bit
int i, ai, bi, ci;
int res = 0;
for(i = 0; i < 32; i++) {
ai = (1<<i)&a;
bi = (1<<i)&b;
ci = (1<<i)&c;
if((ai | bi) == ci)
continue;
if((ai & bi) > 0) // hmm :)
res += 2;
else
res++;
}
return res;
}
Represent the numbers in their bit representation
Number of 1s in the ith bit. so 1 bit will be of form 3k and its 3k + 1 (number than appears once)
Count divisible by 3 $c_i$ = 0, otherwise $c_i$ = 1
this way we can generate $c_i$ using the division on every ith bit :)
Bitwise trick :) set the ith bit.
int singleNumber(vector<int>& nums) {
int c = 0, i, j, count, ci;
// fix a position
for(i = 0; i < 32; i++) {
// get count of 1s in this position
count = 0;
for(j = 0; j < nums.size(); j++){
// Test whether ith bit of nums[j] is set
// increment count accordingly.
count+= nums[j]&(1<<i) ? 1 : 0;
}
ci = count%3;
if(ci)
c = c | (1<<i);
}
return c;
}
Note : interesting write up link
Note :
lets say b, f are the unique numbers
b ^ f = a ^ a ^ b ^ c ^ ….
b and f are different numbers.
Can we distinguish b and f on the basis of first different bit from the right. If we find such position we can separate and get that position
How will you use this information. ( i.e. i represents first different bit)
b and f will be in different group that their ith bit will differ. say : b belongs to a group where ith bit is 0. then we can do xor the number where ith bit is zero we definitely say that the one of the number in group=0 will be b.
Similarly we have same group-1 where ith bit is set 1.
vector<int> singleNumber(vector<int>& nums) {
long long run = 0;
for(int j = 0; j < nums.size(); j++)
run ^= nums[j];
// run = b ^ f
long long mask = (run) & (~(run-1)); // first differnt bit or first set bit in xor of b and f
// Group-0/1 processing
long long xorg1 = 0, xorg2 = 0;
for(int i = 0; i < nums.size(); i++) {
if((nums[i]&mask) == 0)
xorg1 ^= nums[i];
else
xorg2 ^= nums[i];
}
return {(int)xorg1, (int)xorg2};
}