剑指offer部分题目(一)

# fibonacci
def fib(n):
    a, b = 0, 1
    print(1)
    for i in range(n - 1):
        a, b = b, b + a
        print(b)  # 打印第5个数


# 跳台阶
def jump_recur(n):
    if n == 1 or n == 0:
        return 1
    return jump_recur(n - 1) + jump_recur(n - 2)


def jump_dp(n):  # 动态规划思想: 1到2 1中跳法,2到3 是一种跳法
    if n == 1:
        return 1
    if n == 2:
        return 2
    a, b, c = 1, 2, 0
    while n > 2:
        c = a + b
        a, b = b, c
        n -= 1
    return c


# 二进制中1的个数
'''输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。'''
'''负数的补码:正数二进制取反,首位+1 。默认八位数'''


def num_1(num):
    if num == 0:
        return 0
    if num > 0:
        binary = str(bin(num)[2:])
        a = binary.count('0')
        b = (8 - len(binary))
        return a + b
    if num < 0:
        binary = str(bin(num)[3:])
        a = binary.count('0')
        b = (8 - len(binary))
        return a + b + 1


# 调整数组中奇偶数位置,奇前偶后
def adjust(lst):
    while True:
        flag = 0
        for i in range(len(lst)):
            if i > 0:
                a, b = lst[i], lst[i - 1]
                if a % 2 != 0 and b % 2 == 0:  # 如果是奇数且前面是偶数
                    lst[i], lst[i - 1] = b, a
                    flag += 1
        if flag == 0:
            break
    return lst


# 输入链表,输出倒数第K个节点: 压栈再弹出就行了

class Node:
    def __init__(self, val):
        self.val = val
        self.next = None


class Llst:
    def __init__(self):
        self.head = None
        self.end = None

    def append(self, val):
        if not self.head:
            self.head = self.end = Node(val)
        else:
            self.end.next = Node(val)
            self.end = self.end.next


def prt_one(s, n, lst):
    for i in range(s, n + 1):
        print(lst[s][i])
    for i in range(s + 1, n + 1):
        print(lst[i][n])
    for i in range(n - 1, s - 1, -1):
        print(lst[n][i])
    for i in range(n - 1, s, -1):
        print(lst[i][s])


# 顺时针打印矩阵
def rect(array):
    l = len(array) // 2
    l2 = []
    for i in range(l):
        if i == len(array) - i:
            break
        l2.append((i, len(array) - 1 - i))
    for i in l2:
        prt_one(i[0], i[1], array)
    if len(array) % 2 != 0:  # 长度为奇数补打最中间那个数
        print(array[len(array) // 2 + 1])
    # l = [[x for x in range(i, i + 4)] for i in range(1, 17, 4)]  # 生成4*4矩阵
    # rect(l) 执行


# 全排列使用的函数
def ins(tar, t):
    tar = list(tar)  # a,b,c,d
    l = []
    for i in range(len(tar)):
        tar.insert(i, t)
        s = ''.join(tar)
        l.append(s)
        tar.remove(t)
        if i == len(tar) - 1:
            tar.append(t)
            l.append(''.join(tar))
    return l


# 字符串全排列问题:1、递归实现 2、 回溯法排列树思想解决3、动态规划实现
def perm_dp(alpha):  # 动态规划实现
    l = []  # 上一个list
    new_l = []  # 新list
    for i in alpha:  # 有几个字母运行几次
        tar = i  # 分别用 a,b,c,d进行排列
        if not l:
            l.append(tar)
        else:
            for j in l:
                new_l += ins(j, tar)
            l = new_l[:]
            new_l = []
    print(l)


perm_dp('abc')


def perm(l):
    if (len(l) <= 1):
        return [l]
    r = []
    for i in range(len(l)):
        s = l[:i] + l[i + 1:]
        p = perm(s)
        for x in p:
            r.append(l[i:i + 1] + x)
    return r



# 找出出现次数超过一半的数字
def find_num(array):
    d = {}
    num = len(array)
    for i in array:
        d[i] = d.get(i, 0) + 1
        if d[i] >= len(array) / 2:
            print('the num is {}'.format(i))
            return i
    print('no such number')


# 返回最大连续子序列的和,包含负数
def ret_maxsum(array):
    sum = 0
    l = []
    for i in range(len(array)):
        sum += array[i]
        if sum > 0:
            l.append(sum)
        else:
            sum = 0
    return max(l)


# 1 到 n 中 ,1 出现的次数:1、穷举(可进一步优化) 2、分类讨论
def find_1(n):
    num_1 = 0
    for i in range(1, n + 1):
        num_1 += str(i).count('1')
    print('time 1 appears {}'.format(num_1))
    return num_1


# 输入正整数数组,拼成一个最小的数字:1、由于位数不变,首数字最小的依次排前即可
def make_min(array):
    l2 = sorted(array, key=lambda x: int(str(x)[0]))
    return int(''.join(l2))


# 丑数, 只包含2,3,5质因子的数称为丑数,从小到大输出第N个丑数:依次循环÷2,3,5假如最终能等于1则
def find_ugly(n):
    lst = [1, 2, 3, 5]  # initial list
    if n > 6:  # 从6开始
        for i in range(6, n + 1):
            a = i
            for j in [2, 3, 5]:  # 判断丑数部分
                while True:
                    if a == 1 and j == 5:
                        lst.append(i)
                        break
                    if a == 1:
                        break
                    if a % j == 0:
                        a = a // j
                    else:
                        break
    return lst


# 第一个只出现一次的字符,字符长度1w以内
def find_one(string):
    d = {}
    for i in range(len(string)):
        tar = string[i]
        if not d.get(tar, False):  # 如果不在字典里就添加
            d[tar] = i + 1  # 用来记录位置
        else:  # 已存在 就把值标记成True,
            d[tar] = True
    lst = list(d.items())
    lst = sorted(lst, key=lambda x: x[1] if x[1] != True else 10001)
    print(lst)
    return lst[0][1] - 1 if lst[0][1] != True else -1


# 统计一个数字在排序数组中出现的次数:先二分查找找到这个数,然后whileTrue遍历 前后元素,直到不同
def func():
    # 不难就先不写了
    # 注意元素正好在首尾要做条件判断,规避索引越界
    pass

# 整形数组除了两个数字外,别的都出现偶数次,找出这两个只出现一次的数字
def solu():
    # 第一种方法:快排排序,for循环遍历找到只出现一次的
    # 第二种,用异或性质:偶数个相同的数进行异或,结果是0,奇数个数异或结果是自身
    # 不会写,日后再说
    pass

# 输出所有和为S 的连续正整数序列,比如1819202122  加起来是100
def out_S(n):
    # 根据等差数列中值性质来做,不难,耗时,先放着
    pass

# 和为S的两个数字 : 输入递增排序的数组[1,2,4,5,7,8]和一个数字S,在数组中查找两个数使得和正好等于S,多对则输出乘机最小的
def sum_s(array, S):
    # 类似二分思想,先找最中间两个数,和大就 往下遍历 ,和小就往上遍历
    mid = (len(array)-1)//2
    s,b = mid ,mid+1
    l = []
    while True:
        if sum([array[s],array[b]]) > S:
            s-=1
            if s<0:
                print('small {}={}'.format(s,b))
                return l
            else:
                continue
        if sum([array[s],array[b]]) < S:
            b +=1
            if b>= len(array):
                print('beyong {}={}'.format(s,b))
                return l
            else:
                continue
        if sum([array[s],array[b]]) == S:
            l.append((array[s],array[b]))
            s-=1;b+=1
            if s<0 or b>=len(array):
                print('结束{}={}'.format(s,b))
                return l
            else:
                continue

# 循环左移k位,比如abcde 变成 cdeab
def cyc_left_move(string, k):
    k = k % len(string)  # 先处理k 比string长度大的情况  比如abcd 左移9次相当于左移1次
    return ''.join([string[k:], string[:k]])


# 翻转单词顺序: student a am I
def rever(string):
    return ' '.join(reversed(string.split(' ')))


# 一个数组里有未知的重复数字,找出第一个重复的数字,数组长度为n ,里面数字范围0 到 n-1
def findfirst(array):
    d = {}
    for i in array:
        if not d.get(i, 0):
            d[i] = d.get(i, 0) + 1
        else:
            return i


'''给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。
例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,
他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个:
 {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1},
  {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。'''


def max_window(array, size):  # 假设size不超过
    lst = []
    for i in range(len(array) - size + 1):
        win = array[i:i + size]
        lst.append(max(win))
    return lst


# 给定一个字母矩阵,查找是否有一条路径 满足一个单词
# 比如[[a,b,c,e],[s,f,c,s],[a,d,e,e]]  包含bcced 这个单词,走过的路劲不能重复
a = [['a', 'b', 'c', 'e'], ['s', 'f', 'c', 's'], ['a', 'd', 'e', 'e']]


def str_path(array, word):#可以用回溯法,也可以所有路径都存储下来一个个判断
    l = []  # 用于存放所有可行路径
    X = len(array) - 1
    Y = len(array[0]) - 1
    for i in range(X):  # 找到所有首字母的位置
        for j in range(Y):
            if array[i][j] == word[0]:
                l.append([(i, j)])
    for alp in range(1, len(word)):  # 遍历路径字母
        alpha = word[alp]
        new_path = []
        for loca in l:  # 对于每条路径的尾部 loca = [(x,y),(x2,y2)]
            print('============================')
            x, y = loca[-1][0], loca[-1][1]  # 尾部位置
            up, down, left, right = (x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)  # 下一位置
            for i in (up, down, left, right):  # 对于每个合法位置都新建一条路径
                if 0 <= i[0] <= X and 0 <= i[1] <= Y:  # 检验合法的位置
                    print(i)
                    if array[i[0]][i[1]] == alpha and (i not in loca):  # 如果位置合法且为目标字母则加入路径,走过的路径不加入
                        new_path.append(loca + [i])
        l = new_path[:]  # 更新路径
    print(l)
    return l


猜你喜欢

转载自blog.csdn.net/qq_32835305/article/details/86560638