剑指offer_Python解题(三)

31、从1到n的整数中1出现的个数

比如,1-13中,1出现6次,分别是1,10,11,12,13。

31.1 思路

  • 除以10 遍历

1- 一个数和10求余等于1则记录一次
2- 再将这个数整除10,再判断一条件

31.2 解题

def NumberOf1Between1AndN_Solution(n):
    res = 0
    for i in range(1, n+1):
        while i != 0:
            if i % 10 == 1:
                res += 1
            i //= 10
    return res

"""
>>> NumberOf1Between1AndN_Solution(13)
6
"""

32、把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323

32.1 思路

  • 遍历 对数组内的数字两两比较,寻找str1str2,和str2str1两种组合中较小的一个。

1- 先找到最小的前面两个组合
2- 再去找后续最小的两个组合
3- 每次调换顺序,最后合并

例如:
[123, 1, 9]
1-
1-1 比较 1231 & 1123 -->> 1123 -> [1, 123, 9]
1-2 比较 19 & 91 -->> 19 -> [1, 123, 9]
2- 已经确认第一位
2-1 比较 1239 & 9123 -->> 1239 -> [1, 123, 9]
-------- >>> [1, 123, 9] --> 11239

32.2 解题

def PrintMinNumber(numbers):
    if not numbers:
        return ''
    len_num = len(numbers)
    # 1- 转文本
    numbers = [str(num) for num in numbers]
    # 
    for i in range(len_num-1): # 从头遍历
        for j in range(i+1, len_num): # 从+1开始
            # 依次次比较组合,然后调换位置,一一比较
            if numbers[j] + numbers[i] < numbers[i] + numbers[j]:
                numbers[i],numbers[j] = numbers[j],numbers[i]
    return ''.join(numbers)

"""
>>> PrintMinNumber([123, 1, 9] )
'11239'
"""

33、丑数

把只包含质因子2、3和5的数称作丑数。例如6、8都是丑数,但14不是,因为它包含质因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

33.1 思路

  • 逐步生成丑数

1- 每次生成3个丑数
2- 最小的那个就是需要的第n个丑数
3- 计数器(loop_n)作为循环限制

例如:
第6个丑数
1- loop_n = 5, res = 1
1-1 增加(res)1 * 丑数因子[2, 3, 5] -> ugly_set = {2,3,5}
  取最小 -> res = 2
  去最小 -> {3, 5}
  loop_n = 4

1-2 增加(res)2 * 丑数因子[4, 6, 10] -> ugly_set = {3,5, 4, 6, 10}
  取最小 -> res = 3
  去最小 -> {5, 4, 6, 10}
  loop_n = 3

1-3 增加(res)3 * 丑数因子[6, 9, 15] -> ugly_set = {5, 4, 6, 10, 9, 15}
  取最小 -> res = 4
  去最小 -> {5, 6, 10, 9, 15}
  loop_n = 2

1-4 增加(res)4 * 丑数因子[8, 12, 20] -> ugly_set = {5, 6, 10, 9, 15, 8, 12, 20}
  取最小 -> res = 5
  去最小 -> {6, 10, 9, 15, 8, 12, 20}
  loop_n = 1

1-5 增加(res)5 * 丑数因子[10, 15, 25] -> ugly_set = {6, 10, 9, 15, 8, 12, 25}
  取最小 -> res = 6
  去最小 -> {10, 9, 15, 8, 12, 25}
  loop_n = 0 -> 停止循环

—>>> res = 6

33.2 解题

def GetUglyNumber_Solution(n):
    if n == 0:
        return 0
    loop_n = n - 1
    res = 1
    ugly_set = set()
    while loop_n:
        loop_n -= 1
        ugly_set.add(2 * res)
        ugly_set.add(3 * res)
        ugly_set.add(5 * res)
        res = min(ugly_set)
        ugly_set.remove(res)

    return res

"""
>>> GetUglyNumber_Solution(6)
6
"""

34、第一个只出现一次的字符

在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写)。

34.1 思路

  • 思路:创建哈希表,下标为ACII值,值为出现次数。

34.2 解题

def FirstNotRepeatingChar(s):
    ls = [0]*256 # ASCII值
    for i in s:
        ls[ord(i)] += 1
    for j in s:
        if ls[ord(j)] == 1:
            return s.index(j)
            break
    return -1

35、数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

35.1 思路

  • 思路:暴力双指针遍历

35.2 解题

def InversePairs(lst):
    n = len(lst)
    cnt = 0
    for i in range(n-1):
        for j in range(i + 1, n):
            if lst[i] > lst[j]:
                cnt += 1
    return cnt%1000000007

"""
>>> InversePairs([3, 5, 6 ,1, 2, 3])
8
"""

37、统计一个数字在排序数组中的出现的次数

考虑数组为空的情况,直接返回0

37.1 思路

  • 思路:暴力双指针遍历

37.2 解题

def GetNumberOfK(lst, k):
    loop_times = 0
    if lst == []:
        return 0
    if (lst[0] > k) or (lst[-1] < k):
        return 0

    n = len(lst)
    i, j = 0, n-1
    while i < j and  lst[i] != lst[j]:
        loop_times += 1
        if lst[i] != k:
            i += 1
        if lst[j] != k:
            j -= 1

    print(f'loop times: {loop_times}')
    return j - i + 1

"""
>>> GetNumberOfK([1,1,2,3,4,5,6,6,7], 1)
2
"""

37.3 优化解题

  • 思路: 已经排好序,

1- 二分定位
2- 小范围双指针遍历

def GetNumberOfK_fst(lst, k):
    if lst == []:
        return 0
    if (lst[0] > k) or (lst[-1] < k):
        return 0
    n = len(lst)
    i, j = 0, n-1
    loop_times = 0
    print(f'now the range of lst: [{i} , {j}]' )
    # 1- 缩小区间
    while i < j:
        loop_times += 1
        tmp_i , tmp_j = i, j
        if lst[(j - i)//2] < k :
            i = (j - i)//2
        elif lst[(j - i)//2] > k :
            j = (j - i)//2
        # 当中间位置就是需要查找的值的时候退出
        if tmp_i == i and tmp_j == j:
            # 当中间值刚刚好是最后个或第一个K时
            if lst[(j - i)//2] == k and  lst[(j - i)//2 + 1] > k:
                    j = (j - i)//2
            if lst[(j - i)//2] == k and  lst[(j - i)//2 - 1] < k:
                    i = (j - i)//2    
            break

    print(f'now the range of lst: [{i} , {j}]' )
    # 2- 小范围内遍历
    while i < j and  lst[i] != lst[j]:
        loop_times += 1
        if lst[i] != k:
            i += 1
        if lst[j] != k:
            j -= 1
    print(f'loop times: {loop_times}')
    return j - i +1
    
"""
>>> lst = [1]*9 + [2]*10 + [3]*10000
>>> GetNumberOfK_fst(lst, 1)
now the range of lst: [0 , 10018]
now the range of lst: [0 , 9]
loop times: 12
9
>>> GetNumberOfK(lst, 1)
loop times: 10010
9

>>> lst = [1]*9999 + [3]*10001
>>> GetNumberOfK_fst(lst, 3)
now the range of lst: [0 , 19999]
now the range of lst: [9999 , 19999]
loop times: 1
10001
>>> GetNumberOfK(lst, 3)
loop times: 9999
10001

"""

38、二叉树的深度

38.1 思路

  • 思路:递归,左右遍历取最长的

38.2 解题

def maxDepth(tree):
    if tree is None:
        return 0
    # 每递归计数一次
    return max(maxDepth(tree.left), maxDepth(tree.right)) + 1

from scc_function.Struct import BTree
btree = BTree(1, left = BTree(2, left=BTree(1), right=BTree(1))
               , right = BTree(2, left=BTree(1, left=BTree(1)), right=BTree(1)))

"""
>>> maxDepth(btree)
4
"""

39、平衡二叉树

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

39.1 思路

  • 思路:递归

1- 利用39的求数深的函数求得左右子树的深度
2- 比较两者的差值,大于1为非平衡树

39.2 解题

def isBalanced(tree):
    if tree is None:
        return True
    elif abs(maxDepth(tree.left)-maxDepth(tree.right))>1:
        return False
    else:
        return  isBalanced(tree.left) and isBalanced(tree.right)

btree = BTree(1, left = BTree(2, left=BTree(1)
                               , right=BTree(1))
               , right = BTree(2, left=BTree(1
                                            , left=BTree(1,
                                                        left=BTree(1)))
                                , right=BTree(1)))
"""
>>> isBalanced(btree)
False
"""

40、数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字

# 当只有一个数字不一样的时候:
def FindNumsAppearOnce(lst):
    a = 0
    for num in lst:
        a ^= num
    return a

"""
>>> FindNumsAppearOnce([1,1,2,3,3,4,4])
2
"""

40.1 思路

  • 思路:遍历

1- 字典遍历并记录
2- 最后在遍历字典,将只出现一次的记录列表,最后返回

40.2 解题

def FindNumsAppearOnce(lst):
    dct = {}
    res = []
    for i in lst:
        dct[i] = dct[i] + 1 if i in dct else 1
    for k, v in dct.items():
        if v == 1:
            res.append(k)
    return res
    
"""
>>> lst = [1,1,2,2,4,4,5,6,7,7,8,8]
>>> FindNumsAppearOnce(lst)
[5, 6]
"""

40.3 优化

参考:知乎-半情调:剑指offer-python版(下)

  • 思路:存在一个不一样的数字的时候可以用异或,那么分成两个数组就能同样的操作了

1- 找到拆分成两个子列表的值(该数和其中一个目标数的并为0)
1-1 异或之后末尾为1,则两个数的最右是不一样的,即a & 1 == 1,这时候可以用1做拆分
1-2 异或之后末尾为0, 则两个数的最右是一样的,即a & 1 == 0
这时候用1拆分就会存在问题,所以这时候需要向左移动直到找到 a & x == 1
2- 分两组做异或

def FindNumsAppearOnce(lst):
    a = 0
    for num in lst:
        a ^= num
    splitBit = 1
    while splitBit & a == 0:
        splitBit = splitBit << 1
        print(splitBit)
    
    res1 = 0
    res2 = 0
    for i in lst:
        if i & splitBit == 0:
            res1 ^= i
        else:
            res2 ^= i
    return [res1,res2]

41、和为S的连续正数序列

输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序。

41.1 思路

  • 思路:双指针偏移

1- 现在最小正数定下头指针(1)和尾指针(2)
2- 比较当前和累计与目标值的大小
2-1 当当前累计等于目标值的时候输出, 头指针到尾指针的序列,尾指针后移,并加上后移的值
2-2 当当前累计大于目标值的时候, 头指针后移,并减去之前的值
2-3 当当前累计小于目标值的时候, 尾指针后移,并加上后移的值
2-4 当头指针到达目标值一半以上的时候停止

41.2 解题

def findlist(tsum):
    res = []
    i, j = 1, 2
    csum = i + j
    while i <= tsum/2:
        if csum == tsum:
            res.append(list(range(i, j+1)))
            j += 1
            csum += j
        elif csum > tsum:
            csum -= i
            i += 1
        else:
            j += 1
            csum += j
    return res 

"""
>>> findlist(30)
[[4, 5, 6, 7, 8], [6, 7, 8, 9], [9, 10, 11]]
"""

42、和为S的两个数字

输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的

42.1 思路

  • 思路:双指针变量

1- 由于已经排好序,需要乘积最小,那么两者距离越远乘积越小
2- 当头+尾指针的和大于目标值的时候,移动尾指针
3- 当头+尾指针的和小于目标值的时候,移动头指针

41.2 解题

def FindNumbersWithSum(array, tsum):
    n = len(array)
    if n < 2:
        return []
    i = 0
    j = n - 1
    while i < j:
        if array[i] + array[j] > tsum:
            j -= 1
        elif array[i] + array[j] < tsum:
            i += 1
        else:
            return [array[i],array[j]]
    return []

"""
>>> FindNumbersWithSum([1,2,3,4,5,8], 6)
[1, 5]
"""

43、左旋转字符

对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”

43.1 思路

  • 思路:切片

43.2 解题

def leftturn(s, n):
    return  s[n:] + s[:n]

"""
>>> leftturn('abcXYZdef', 3)
'XYZdefabc'
"""

44、翻转单词顺序列

例如,“student. a am I”翻转为“I am a student.”。

44.1 思路

  • 思路:split join

44.2 解题

def IsContinuous(s):
    s = s.split(' ')
    s.reverse()
    return ' '.join(s)

45、扑克牌顺子

一副扑克牌,里面有2个大王,2个小王,从中随机抽出5张牌,如果牌能组成顺子就输出true,否则就输出false。为了方便起见,大小王是0,大小王可以当作任何数字。

45.1 思路

  • 思路:遍历(共5张牌)

1- 找出大王小王的数量
2- 相邻的相等False, 存在2返回False

45.2 解题

def IsContinuous(lst):
    """
    随机抽5张牌
    """
    if not lst or lst==[]:
        return False
    
    trans_dct = {'J':11, 'Q':12, 'K':13, 'A':14  
                 ,'king_big':0,  'king_small':0
    }
    lst_deal = [trans_dct[i] if i in trans_dct else i for i in lst  ]
    lst_deal = sorted(lst_deal)
    king_cnt = 0
    while lst_deal[king_cnt] == 0:
        king_cnt += 1

    gap_cnt = 0
    for i in range(king_cnt, 4):
        if (lst_deal[i+1] == lst_deal[i]) or (lst_deal[i] == 2):
            return False
        gap_cnt += lst_deal[i+1] - lst_deal[i] - 1 # 相差1的不算间隙
    return True if gap_cnt <= king_cnt else False

"""
>>> IsContinuous(['J', 'Q', 'K', 'king_big', 2])
False
>>> IsContinuous(['J', 'Q', 'K', 'king_big', 'A'])
True
"""

46、孩子们的游戏(圆圈中最后剩下的数)

游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列,不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友获胜,获胜的小朋友编号多少?(注:小朋友的编号是从0到n-1)

46.1 思路

  • 思路:求余

移动位置求余 来排除

46.2 解题

def LastRemaining_Solution(n, m):
    if not n and not m :
        return -1
    
    lst = list(range(n))
    i = 0
    while len(lst) > 1:
        # 移动位置求余
        i = (m-1 + i) % len(lst) 
        lst.pop(i)
    return lst[0]


"""
>>> LastRemaining_Solution(5, 3)
3
"""

47、求1+2+3+…+n

求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

47.1 思路

  • 思路:递归

47.2 解题

def Sum_Solution(n):
    """
    不能使用乘除法,
    使用if else来确定终止条件
    利用and来实现递归的终止
    """
    return n and n + Sum_Solution(n-1)

"""
>>> Sum_Solution(100)
5050
"""

48、不用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

48.1 思路

  • 思路:位运算

1-可以考虑将加法分成两部分 (1)0+1 = 1 1+0 = 1; (2) 0+0=0 1+1=10
2- (1)部分的运算其实和 ^ (异或一致) 01|10-> 1 00|11->0
3- (2)部分可以分解成 & + << 00-> 0 << 1 -> 00; 11-> 1 << 1 -> 10
4- 循环直到(2)部分的数为0

48.2 解题

def Add(num1, num2):
    while num2 !=0:
        sum_ = num1 ^ num2
        sum_add = (num1 & num2) << 1
        num1 = sum_
        num2 = sum_add
    return sum_


"""
>>> Add(100,1000)
1100
"""

48.3 优化

知乎博主指出python的负数相加需要特殊处理,否则会陷入死循环
在早期版本中如Python2.7中,整数的有int和long两个类型。int类型是一个固定位数的数;long则是一个理论上可以存储无限大数的数据类型。当数大到可能溢出时,为了避免溢出,python会把int转化为long。而Python3.x之后整数只有一个可以放任意大数的int了。可是无论哪种,都是采用了特殊的方法实现了不会溢出的大整数。 所以会使程序无限的算下去,这也是Python效率低的一个原因。(python2和python3都有这个问题。)
已经知道了右移过程中大整数的自动转化,导致变不成0,那么只需要在移动的过程中加一下判断就行了,把sum_add的值和0xFFFFFFFF做一下比较就可以了,具体代码如下所示

def Add(num1, num2):
    while num2 !=0:
        sum_ = num1 ^ num2
        sum_add = 0xFFFFFFFF&(num1 & num2)<<1
        sum_add = -(~(sum_add - 1) & 0xFFFFFFFF) if sum_add > 0x7FFFFFFF else sum_add
        num1 = sum_
        num2 = sum_add
    return sum_

"""
>>> Add(100,-1)
99
"""

49、把字符串转换成整数

将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,但是string不符合数字要求时返回0),
要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0。

49.1 思路

  • 思路:int

1- 先去除两边空值,然后判断正负
2- 用try except输出

49.2 解题

def StrToInt(s):
    s = s.strip()
    if not s:
        return 0
    symbol = 1
    if s[0] == '-':
        s = s[1:]
        symbol = -1
    if s[0] == '+':
        s = s[1:]
    num_dct = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
    out_num = 0
    n = 1
    for i in s[::-1]:
        if i in num_dct:
            out_num += n * num_dct[i]
            n *= 10
        else:
            return 0
    return  out_num * symbol
    
## 可以直接用int 在内会自己判断

def StrToInt(s):
    try:
        return  int(s)
    except:
        return  0

50、数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。
也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

50.1 思路

  • 思路:字典+遍历

1- 当某个数字出现了两次就停止

50.2 解题

def duplicate(numbers, duplication):
    cnt_dct = {}
    loop_n = 0
    # 仅仅当某个数字出现2次就停止
    for i in numbers:
        cnt_dct[i] = cnt_dct.get(i,0) + 1
        if cnt_dct[i] > 1:
            duplication[0] = i
            print(f'获取重复数字循环了:{loop_n}次')
            return True
        loop_n += 1
    print(f'获取重复数字循环了:{loop_n}次')
    return False

50.3 优化解题

  • 双指针遍历
def duplicate_qk(numbers, duplication):
    cnt_dct = {}
    loop_n = 0
    n = len(numbers)
    i, j = 0, n - 1
    # 仅仅当某个数字出现2次就停止
    while i < j:
        num_i, num_j = numbers[i], numbers[j]
        cnt_dct[num_i] = cnt_dct.get(num_i, 0) + 1
        cnt_dct[num_j] = cnt_dct.get(num_j, 0) + 1
        if cnt_dct[num_i] > 1:
            duplication[0] = num_i
            print(f'获取重复数字循环了:{loop_n}次')
            return True
        if cnt_dct[num_j] > 1:
            duplication[0] = num_j
            print(f'获取重复数字循环了:{loop_n}次')
            return True
        i += 1
        j -= 1
        loop_n += 1
    print(f'获取重复数字循环了:{loop_n}次')
    return False
  • 测试比较
import numpy as np
for _ in range(5):
    # 产生20000个0-10000的随机数列表
    hundred_lst = list(range(0,10000))
    hundred_lst_plus = hundred_lst * 2
    np.random.shuffle(hundred_lst_plus)

    lst = [0]
    print('\n', '--'*20)
    print('单指针:')
    a = duplicate(hundred_lst_plus, lst)
    print('双指针:')
    b = duplicate_qk(hundred_lst_plus, lst)
   
"""
 ----------------------------------------
单指针:
获取重复数字循环了:154次
双指针:
获取重复数字循环了:46次

 ----------------------------------------
单指针:
获取重复数字循环了:230次
双指针:
获取重复数字循环了:27次

 ----------------------------------------
单指针:
获取重复数字循环了:80次
双指针:
获取重复数字循环了:80次

 ----------------------------------------
单指针:
获取重复数字循环了:326次
双指针:
获取重复数字循环了:169次

 ----------------------------------------
单指针:
获取重复数字循环了:70次
双指针:
获取重复数字循环了:70次
"""

51、构建乘积数组

给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]* A[1]* …* A[i-1]* A[i+1]* …* A[n-1]。不能使用除法。

51.1 思路

  • 思路:遍历

1- 每一位都进行遍历

51.2 解题

# 构建乘积数组
def multiply(lst):
    len_ = len(lst)
    res_out = []
    # 构建一个累积的数据
    for index_r in  range(len_):
        res = 1
        for index_ in  range(len_):
            if  index_ == index_r:
                continue
            res *= lst[index_]
        res_out.append(res)

    return res_out

multiply([1, 2, 3])

51.3 解题2

def multiply_2(lst):
    all_mult = 1
    for i in  lst:
        all_mult *= i
    
    res_out = []
    for num in lst:
        sign_ = (all_mult > 0) ^(num > 0)
        a, b = abs(num), abs(all_mult)
        # 获取第一次向左移动的位数
        cnt = 0
        while a <= b:
            a <<= 1
            cnt += 1
        
        # 开始计算'除法'
        res_num = 0
        while cnt > 0:
            a >>= 1
            cnt -= 1
            if a <= b:
                res_num += 1 << cnt
                b -= a
        # 获取除后的数
        res_out.append(-res_num if sign_ else res_num)
    return res_out

"""
>>> multiply_2([1, 2, -3])
[-6, -3, 2]
>>> multiply([1, 2, -3])
[-6, -3, 2]
"""

52、正则表达式匹配

请实现一个函数用来匹配包括’.‘和’ * ’ 的正则表达式。模式中的字符’.‘表示任意一个字符,而’ * '表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab * ac * a"匹配,但是与"aa.a"和"ab * a"均不匹配。

52.1 思路

  • 思路:递归

1- 当text与parttern一致时返回True, 当pattern为空时, 返回 not text
2- 将’.‘与其他字母一并判断,并结合text是否为空
3- 发现并处理’*’ ,分两种情况后移,1) pattern后移两位,2) text后移一位

52.2 解题

def isMatch(text, pattern) -> bool:
    if  text == pattern:
        return True
    if not pattern:
        return not text
    match = bool(text) and pattern[0] in {'.', text[0]}
    if len(pattern) >=2 and pattern[1] == '*':
        # 匹配该字符0次,然后跳过该字符和'*', 一般在最后判断的时候(text已经为空) 
        # 当 pattern[0] 与 text[0]匹配后 后移 text
        return isMatch(text, pattern[2:]) or\
            (match and isMatch(text[1:], pattern))
    return match and isMatch(text[1:], pattern[1:])

"""
>>> isMatch('asdasd', 'a.*')
True
"""

53、表示数值的字符串

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

53.1 思路

  • 思路:float

53.2 解题


def isNumeric(self, s):
    try:
        s = float(s)
        return True
    except:
        return False

54、字符流中第一个不重复的字符

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
如果当前字符流没有存在出现一次的字符,返回#字符。

54.1 思路

  • 思路:dct + 双指针遍历 (类似 50、数组中重复的数字)

54.2 解题

def FirstAppearingOnce(s):
    cnt_dct = {}
    n = len(s)
    i, j = 0, n - 1
    while i <= j:
        s_i, s_j = s[i], s[j]
        cnt_dct[s_i] = cnt_dct.get(s_i, 0) + 1
        cnt_dct[s_j] = cnt_dct.get(s_j, 0) + 1
        if i == j:
            cnt_dct[s_j] = cnt_dct.get(s_j, 0) - 1
        i += 1
        j -= 1
    
    for i in s:
        if cnt_dct[i] == 1:
            return i
    return '#'

"""
>>> FirstAppearingOnce('gooogle')
{'g': 2, 'e': 1, 'o': 3, 'l': 1}
'l'
"""
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Scc_hy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值