文章目錄
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 優化
- 思路:存在一個不一樣的數字的時候可以用異或,那麼分成兩個數組就能同樣的操作了
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
- 2進制除法
參考LeetCode 兩數相除
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'
"""