算法练习

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 []
上一篇:guava之新集合


下一篇:VAIO、东芝、富士通将在PC业务方面达成联合协议