算法练习
作者:互联网
0x001
统计一个数值中二进制中1的个数。
def countOnes(x):
count = 0
while x > 0:
count += 1
x &= (x - 1) # x=0b111 x-1=0b110 &= 0b110 1个
# x=0b110 x-1=0b101 &= 0b100 2个
# x=0b100 x-1=0b011 &= 0b000 3个
return count
# 计算其中0的个数
import math
def countZeros(x):
count = 0
while x > 0:
count += 1
x &= (x - 1)
return int(math.log(x) + 1) -count
0x002
在数组中找a,b 使得a+b=c
def binarysearch(L,m): # 折半查找
if len(L) == 0:
return -1
i = int(len(L) / 2)
if a[i] == m:
return i
if a[i] > m:
return binarysearch(L[0:i],m)
if a[i] < m and i+1 < len(L):
return binarysearch(L[i+1:],m)
return -1
L.sort() # 排序
0x003
求两数的公约数。
def gcd(a, b):
if a % b == 0:
return b
d = a % b
return gcd(b, d)
# a b的公约数等于 b d 的公约数
0x004
指定进制的字符和数字转换
def strToInt(str, b): # 字符转数值
val = 0
base = 1
i = len(str) - 1
while i >= 0: # 从最后一位开始
c = str[i]
v = 0
if '0' <= c <= '9': # 判断此位是几
v = ord(c) - ord('0')
if 'A' <= c <= 'E':
v = 10 + ord(c) - ord('A')
if i < len(str) - 1: # 位权最大是 len(str)-1 第一次不执行 base=1
base *= b
val += v * base
i -= 1
return val
def intToStr(v, b): # 数值转字符
s = ''
c = '0'
while v > 0:
d = v % b # 辗转取余
if 0 <= d <= 9:
c = chr(ord('0') + d)
if d >= 10:
c = chr(ord('A') + d - 10)
s = c + s # 倒排
v //= b # 整除
return s
0x005
eliasgamma编码 把一个数转换为二进制 ,并在高位增加长度-1个0
- x=12 0b1100 编码后 0b0001100
def eliaasGammaEncode(n): # 编码
s = intToBinaryString(n) # 数值转二进制字符串
s = addZerosToHead(s) # 在高位补0
return s
def intToBinaryString(n):
s = ''
while n > 0:
if n & 1 == 0: # 每次取最后一位,增加到s里
s = '0' + s
else:
s = '1' + s
n = n >> 1 # 向右移动,以取得每一位数
return s
def addZerosToHead(s):
i = len(s)
while i - 1 > 0: # 增加长度-1个0
s = '0' + s
i -= 1
return s
def eliasGammaDecode(s):
length = getHeadZerosCount(s) # 得到补0的位数
if length <= 0:
raise Exception("Head Zeros error")
s = s[length:] # 取得补0后面的值
binary = s[:length + 1] # 取得这个数
n = binaryStringToInt(binary) # 二进制字符转数值
return n
def getHeadZerosCount(s):
cut = 0
for i in range(len(s)):
if s[i] == '0': # 统计0的个数
cut += 1
else:
break
return cut
def binaryStringToInt(s):
n = 0
for i in range(len(s)):
if s[i] == '1': # 还原这个数
n |= 1
if i < len(s) - 1:
n = n << 1
return n
0x006
位运算实现乘法和加法
def binaryAdd(x, y): # 加法实现
v = 0 # 结果
advance = 0 # 进位标志
r = 0 # 结果中的位置
while x > 0 or y > 0:
i = x & 1 # 取最后一位
j = y & 1
x = x >> 1
y = y >> 1
b = i ^ j # 异或 1^0 0^1 为真
if b == 1:
if advance == 1: # 如果这时有进位 1+0+advace=10 进位标志保持
b = 0 # b = 0
else:
if i & j == 1: # i ,j 都是1
if advance == 1: # advance 为1 i+j+advance = 11 b=1 进位标志保持
b = 1
else: # advance 为0 i+j+advance =10 进位标志置1 b=0
b = 0
advance = 1
else: # i,j都为0
if advance == 1: # i+j+advance=1 b=1 进位标志置0
b = 1 # i+j+advance=0 b=0 进位标志不变
advance = 0
b = b << r
v |= b
r += 1
if advance == 1:
v |= (advance << r)
return v
def binaryMultiply(a, b): # 乘法实现
stack = [] # 利用列表实现栈
s = 0
while b > 0: # a*b 每次把a左移后压栈,直到b为0
if b & 1 == 1: # b为1 就左移后压栈
stack.append(a << s)
else:
stack.append(0) # b为0 不压栈
b = b >> 1 # 右移一位,取下一个1
s += 1 # b向左移动n位
while len(stack) > 1: # 直到最后只有一个元素,就是结果
x = stack.pop()
y = stack.pop()
z = binaryAdd(x, y) # 把x,y求各后再次压栈
stack.append(z)
return stack.pop()
0x007
把一个列表进行划分,分为 小于,等于,大于目标值的列表,原地进行划分
def rearrangeArray(array, i):
if len(array) <= 1:
return array
pivot = array[i]
array = rearrangeByPivot(array, 0, len(array) - 1, pivot, True)
j = 0 # 分成两部分,前边大于piovt 后边的小于pivot
for j in range(len(array)):
if array[j] >= pivot: # 找到第一个大于pivot的值
break
array = rearrangeByPivot(array, j, len(array) - 1, pivot, False)
return array # 对后一部分进行调整
def rearrangeByPivot(array, begin, end, pivot, checkEqual):
if end <= begin:
return
while begin < end:
if (checkEqual is True and array[begin] >= pivot) or (checkEqual is False and array[begin] > pivot):
array[begin], array[end] = array[end], array[begin]
end -= 1 # begin大于pivot 交换 ,end向前 这样换过来的都是大于pivot的
else:
begin += 1 # begin不大于或小于,begin 向后,前边的是小于等于pivot的值
return array
0x008
从列表中找到连续的一组元素的和,取余列表长度等于0
def findModuleSubSet(A):
boxes = [] # 定义一个盒子,用于标志是否出现过这个余数
for i in range(len(A)):
boxes.append(0)
sum = 0
subSet = [] # 存放满足要求的数组下标
for k in range(len(A)):
sum += A[k]
subSet.append(k)
t = sum % len(A)
if t == 0: return subSet # 如果等于0 满足条件,返回下标
if boxes[t] != 0: # 这个盒子有值,说明这个余数出现过
preSum = 0
for i in range(k + 1):
preSum += A[i]
if preSum % len(A) == t: # 若这两个值一样,说明后来的preSum与T之间的数取余
return subSet[i + 1:] # 为0 所以返回i+1 后最后的下标
boxes[t] = 1
return []
标签:advance,return,练习,len,算法,pivot,array,def 来源: https://blog.csdn.net/QTT_Rookie/article/details/115581692