Binary Operations
&, bitwise AND, x & y, : Returns 1 if both the bits are 1 else 0
a = 10 = 1010 (Binary) b = 4 = 0100 (Binary a & b 1010 & 0100 =0000 =0 (Decimal) Helpful when doing bit addition and you need to know the carry value, x & b << 1 is the carry value
|, bitwise OR, x | y, Bitwise or operator: Returns 1 if either of the bit is 1 else 0.
Example:
a = 10 = 1010 (Binary) b = 4 = 0100 (Binary a | b 1010 | 0100 =1110 =14 (Decimal)
~, bitwise NOT, ~x, Returns one’s compliement of the number
a = 10 = 1010 (Binary)
~a = ~1010
= -(1010 + 1)
= -(1011)
= -11 (Decimal)
https://www.tutorialspoint.com/two-s-complement
^, bitwise XOR, x^y, Returns 1 if one of the bit is 1 and other is 0 else returns false
a = 10 = 1010 (Binary)
b = 4 = 0100 (Binary
https://stackoverflow.com/questions/6398427/what-does-bitwise-xor-exclusive-or-mean
XOR is self-inverting, identity element, and associative
a^(a^b) = b, where b would be f(f(b)) = b
b^a = a^b
XOR’s identity element is 0, X ^ 0 = X for all of X
a & b =
1010
^
0100
= 1110
= 14 (Decimal)
USE CASE: set the last bit of a num to 0, x &= x - 1 : 111 & 110 = 110 = 7, which sets the right most bit to 0
ANOTHER ONE: x % 2 is the same as x & 1. 10 & 01 is 0, even. 11 & 01 is 1, which means odd> > , bitwise right shift, x»y, shifts the bits “away” from the number, dividing it by 2, or multiplying it by (1/2)^y, floor division too, no floats in binary!
This makes sense bc we shift the binary values 1 to the left or right, that takes away or adds a binary value, which will effectively DOUBLE or HALF the amount of values we can have, therefore doubling or halfing the the value
a=12=1100 a>>1 = 110, = 6 a>>2 = 11, =3 a>>3=1, =1 a>>4=0=0
list strategies for binary
kth grammar (can not be binary)
We build a table of n rows (1-indexed). We start by writing 0 in the 1st row. Now in every subsequent row, we look at the previous row and replace each occurrence of 0 with 01, and each occurrence of 1 with 10.
For example, for n = 3, the 1st row is 0, the 2nd row is 01, and the 3rd row is 0110.
Given two integer n and k, return the kth (1-indexed) symbol in the nth row of a table of n rows.
Example 1:
Input: n = 1, k = 1
Output: 0
Explanation: row 1: 0
Example 2:
Input: n = 2, k = 1 Output: 0 Explanation: row 1: 0 row 2: 01 Example 3:
Input: n = 2, k = 2 Output: 1 Explanation: row 1: 0 row 2: 01
brute is quadratic time and 2^n space, double for loop and the space is squared after each row
time: O(n log(n)) because we do this n times and the modulus operator is logN time
space: recursive stack space is linear with N
class Solution:
add binary
Given two binary strings a and b, return their sum as a binary string.
Example 1:
Input: a = “11”, b = “1”
Output: “100”
Example 2:
Input: a = “1010”, b = “1011”
Output: “10101”
brute is to convert the strings to ints using int(x, 2) to represent a base 2 system, then add them, format back to binary. Time/space is O(n+m) bc we need to operate both inputs and hold both in space
def brute(self, a, b): ----return bin((int(a, 2) + int(b, 2)))[2:]
time: O(n+m) bc we have to convert them to ints, the XOR part is O(32) bc we are using 32 bit ints
space: O(max(n,m)) bc we need to store the answer
time: O (max(n, m) bc we only operate based on the largest input
space: O(A + B + answer) since we store A, B, and the answer in memory
from collections import deque
class Solution:
----def addBinary1(self, a: str, b: str) -> str:
--------n = max(len(a), len(b))
--------a, b = a.zfill(n), b.zfill(n)
--------out = deque()
--------carry = 0
--------for i in range(n - 1, -1, -1):
------------x = int(a[i])
------------y = int(b[i])
------------current = x + y + carry
------------
------------if current % 2 == 1:
----------------out.appendleft("1")
------------else:
----------------out.appendleft("0")
------------carry = current // 2
--------if carry == 1:
------------out.appendleft("1")
--------return "".join(out)single number
Given a non-empty array of integers nums, every element appears twice except for one. Find that single one.
You must implement a solution with a linear runtime complexity and use only constant extra space.
Example 1:
Input: nums = [2,2,1]
Output: 1
Example 2:
Input: nums = [4,1,2,1,2]
Output: 4
brute force would be the math, since each value is is there twice except our answer, take the set, multiply by 2, and subtract from the sum of original set you get the single number
time: linear
space: constant
class Solution:
Sum of two integers
Given two integers a and b, return the sum of the two integers without using the operators + and -.
Example 1:
Input: a = 1, b = 2
Output: 3
Example 2:
Input: a = 2, b = 3
Output: 5
time: O(32), constant since there are only 32 bits
space: O(32), constant since there are only 32 bits and we dont make any new data structures
class SumOfTwoBinary(object):
divide 2 integers
Given two integers dividend and divisor, divide two integers without using multiplication, division, and mod operator.
Return the quotient after dividing dividend by divisor.
The integer division should truncate toward zero, which means losing its fractional part. For example, truncate(8.345) = 8 and truncate(-2.7335) = -2.
Note: Assume we are dealing with an environment that could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For this problem, assume that your function returns 231 − 1 when the division result overflows.
brute force is to add the divisor until you cant anymore, then get the answer. That is linear but is also really bad incase of large dividends
time: O(log(n)), exponential search is logN time
space: logN if you have the memos, constant if you do not
class Solution:
time: log(n)
space: constant
class Solution:
missing element
Given an array nums containing n distinct numbers in the range [0, n], return the only number in the range that is missing from the array.
Example 1:
Input: nums = [3,0,1]
Output: 2
Explanation: n = 3 since there are 3 numbers, so all numbers are in the range [0,3]. 2 is the missing number in the range since it does not appear in nums.
len(nums) = 3
range: 0 1 2
values: 3 0 1
time: O(n)
space: constant
class Solution:
happy number
Write an algorithm to determine if a number n is happy.
A happy number is a number defined by the following process:
Starting with any positive integer, replace the number by the sum of the squares of its digits.
Repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1.
Those numbers for which this process ends in 1 are happy.
Return true if n is a happy number, and false if not.
Input: n = 19 Output: true Explanation: 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1 Example 2:
Input: n = 2
Output: false
time: O(log(n)), this is tricky, it requires us to know that we cycle around 243, and it takes log(n) time to perform the happy calculation because it is based on the digits in the number, which is on a base-10 system so log(n). For numbers larger thatn 243, it will take log(log(log(n))) time, which basically means log(n)
space: O(1) or O(243) if we do an optimized hashmap
class Solution:
Solution2
Write a function that takes an unsigned integer and returns the number of ‘1’ bits it has (also known as the Hamming weight).
Note:
Note that in some languages, such as Java, there is no unsigned integer type. In this case, the input will be given as a signed integer type. It should not affect your implementation, as the integer’s internal binary representation is the same, whether it is signed or unsigned.
In Java, the compiler represents the signed integers using 2’s complement notation. Therefore, in Example 3, the input represents the signed integer. -3.
Example 1:
Input: n = 00000000000000000000000000001011
Output: 3
Explanation: The input binary string 00000000000000000000000000001011 has a total of three ‘1’ bits.
time: O(32), space is O(1). On LC it says that the time is O(1), but then it references that the worst case is 32 1’s. Make sure to clarify this worst-case scenario and just say it is constant in an interview
class Solution:
time: O(32) space/time, since the string could take up 32 bits
- —def pythonic(self, n):
- ——-return bin(n).count(“1”)
time/space: O(32) / O(1)
—-def bit_manipulation2(self, n):
——–bits = 0
——–’’’
110011 &= 110010 = 110010 add 1
110010 &= 110001 = 110000 adds 1
110000 &= 101111 = 100000 adds 1
100000 &= 011111 = 000000 adds 1, result is 4, crazy this works
‘’’
——–while n > 0:
————bits += 1
————n &= (n -1)
——–return bits
Given an integer n, return an array ans of length n + 1 such that for each i (0 <= i <= n), ans[i] is the number of 1’s in the binary representation of i.
Example 1:
Input: n = 2 Output: [0,1,1] Explanation: 0 --> 0 1 --> 1 2 --> 10
time: O(n * 32), worst case for each N is 32 bc of how many bits are in a 32 int
space: O(1), not including answer
class Solution:
time: O(n), we loop through n once
space: O(1), not including answer
time: O(n), we loop through n once
space: O(1), not including answer
Given an integer n, return the number of prime numbers that are strictly less than n.
Example 1:
Input: n = 10
Output: 4
Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7.
time: O(squareroot(n) * log(log(n)) ): logN because we go from base*base, n, base, then log(log(n)) bc we keep increaseing the base value over each iteration. there is a proof somewhere, square root N * log n is probably correct too space O(N): we can store n values in the hashmap
time:
class Solution:
—-def countPrimes(self, n: int) -> int:
——–if n <= 2:
————return 0
——–
——–composite_nums = {}
——–square_root = int(n ** 0.5)
——–for base in range(2, square_root + 1):
————if base not in composite_nums:
—————-for multiple in range(base*base, n, base):
——————–composite_nums[multiple] = 1
——–
——–return n - 2 - len(composite_nums)