剑指Offer-Python题解(三)

45 扑克牌顺子

题目描述

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

解题思路

代码

# -*- coding:utf-8 -*-

# LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,

# 2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,

# 看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!

# “红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,

# 他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。

# 上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。

# LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,

# 然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。

# 为了方便起见,你可以认为大小王是0。

class Solution:

def IsContinuous(self, numbers):

if not numbers:

return 0

numbers.sort()

zeros = numbers.count(0)

for i, v in enumerate(numbers[:-1]):

if v != 0:

if numbers[i + 1] == v:

return False

zeros -= (numbers[i + 1] - numbers[i] - 1)

if zeros < 0:

return False

return True

if __name__ == '__main__':

S = Solution()

print(S.IsContinuous([1, 2, 3, 4, 5, 6, 7, 0]))

46 孩子们的游戏-圆圈中最后剩下的数

题目描述

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1) 如果没有小朋友,请返回-1

解题思路

代码

# -*- coding:utf-8 -*-

# 每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。

# HF作为牛客的资深元老,自然也准备了一些小游戏。

# 其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。

# 然后,他随机指定一个数m,让编号为0的小朋友开始报数。

# 每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,

# 并且不再回到圈中,从他的下一个小朋友开始,

# 继续0...m-1报数....这样下去....直到剩下最后一个小朋友,

# 可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。

# 请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)

class Solution:

def LastRemaining_Solution(self, n, m):

if n == 0 and m == 0:

return -1

stu = list(range(0, n))

cur = 0

while len(stu) > 1:

cur = (cur + m - 1) % len(stu)

stu.pop(cur)

return stu[0]

if __name__ == '__main__':

S = Solution()

print(S.LastRemaining_Solution(10, 5))

47 求1+2+3+...+n

题目描述

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

解题思路

代码

# -*- coding:utf-8 -*-

# 求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等

# 关键字及条件判断语句(A?B:C)。

class Solution:

def Sum_Solution(self, n):

if n == 1:

return 1

else:

return n + self.Sum_Solution(n - 1)

if __name__ == '__main__':

S = Solution()

print(S.Sum_Solution(100))

48 不用加减乘除做加法

题目描述

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

解题思路

代码

# -*- coding:utf-8 -*-

# 求1 + 2 + 3 + ... + n,要求不能使用乘除法、for、while、if、else、switch、case等

# 关键字及条件判断语句(A ? B : C)

# 思路:

# 不计进位的和为 a ^ b,进位就是 a & b

# a + b = a ^ b + (a & b) << 1

class Solution:

def Add_sum(self, num1, num2):

num = [num1, num2]

return sum(num)

def Add(self, num1, num2):

unit = num1 ^ num2

carry_bit = num1 & num2

while carry_bit != 0:

temp_a = unit

temp_b = carry_bit << 1

unit = temp_a ^ temp_b

carry_bit = temp_a & temp_b

return unit

if __name__ == '__main__':

S = Solution()

print(S.Add(100, 12))

49 把字符串转换成整数

题目描述

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

输入描述

输入一个字符串,包括数字字母符号,可以为空

输出描述

如果是合法的数值表达则返回该数字,否则返回0

示例1

输入

+2147483647

1a33

输出

2147483647

0

解题思路

代码

# -*- coding:utf-8 -*-

# 将一个字符串转换成一个整数(实现Integer.valueOf(string)的功能,

# 但是string不符合数字要求时返回0),要求不能使用字符串转换整数的库函数。

# 数值为0或者字符串不是一个合法的数值则返回0。

class Solution:

def StrToInt(self, s):

flag = True

pos = 1

res = 0

if s == '':

return 0

for i in s:

if i == '+' or i == '-':

if flag == True:

flag = False

if i == '+':

pos = 1

elif i == '-':

pos = -1

else:

return 0

else:

return 0

elif i >= '0' and i <= '9':

flag = False

res = res * 10 + int(i)

else:

return 0

res = pos * res

return res

S = Solution()

print(S.StrToInt('1234'))

50 数组中重复的数字

题目描述

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

解题思路

代码

# -*- coding:utf-8 -*-

# 在一个长度为n的数组里的所有数字都在0到n-1的范围内。

# 数组中某些数字是重复的,但不知道有几个数字是重复的。

# 也不知道每个数字重复几次。请找出数组中任意一个重复的数字。

# 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},

# 那么对应的输出是第一个重复的数字2。

class Solution:

def duplicate(self, numbers, duplication):

dic = {}

if not numbers:

return False

for i in numbers:

if i not in dic:

dic[i] = 1

else:

if dic[i] == 1:

duplication[0] = i

return True

return False

"""

举例说明:{2,3,1,0,2,5,3}:

0(索引值)和2(索引值位置的元素)不相等,

并且2(索引值位置的元素)和1(以该索引值位置的元素2为索引值的位置的元素)不相等,

则交换位置,数组变为:{1,3,2,0,2,5,3};

0(索引值)和1(索引值位置的元素)仍然不相等,

并且1(索引值位置的元素)和3(以该索引值位置的元素1为索引值的位置的元素)不相等,

则交换位置,数组变为:{3,1,2,0,2,5,3};

0(索引值)和3(索引值位置的元素)仍然不相等,

并且3(索引值位置的元素)和0(以该索引值位置的元素3为索引值的位置的元素)不相等,

则交换位置,数组变为:{0,1,2,3,2,5,3};

0(索引值)和0(索引值位置的元素)相等,遍历下一个元素;

1(索引值)和1(索引值位置的元素)相等,遍历下一个元素;

2(索引值)和2(索引值位置的元素)相等,遍历下一个元素;

3(索引值)和3(索引值位置的元素)相等,遍历下一个元素;

4(索引值)和2(索引值位置的元素)不相等,

但是2(索引值位置的元素)和2(以该索引值位置的元素2为索引值的位置的元素)相等,

则找到了第一个重复的元素。

"""

class Solution1:

def duplicate(self, numbers, duplication):

n = len(numbers)

if n == 0:

return False

for i in range(n):

if numbers[i] < 0 or numbers[i] > n - 1:

return False

for i in range(n):

while numbers[i] != i:

if numbers[i] == numbers[numbers[i]]:

duplication[0] = numbers[i]

return True

numbers[numbers[i]], numbers[i] = numbers[i], numbers[numbers[i]]

return False

class Solution2:

def duplicate(self, numbers, duplication):

n = len(numbers)

if n == 0:

return False

for i in range(n):

index = numbers[i]

if index >= n:

index -= n

if numbers[index] >= n:

duplication[0] = index

return True

numbers[index] += n

return False

if __name__ == '__main__':

S = Solution1()

res = [1]

print(S.duplicate([2, 1, 3, 1, 4], res))

print(res)

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]。不能使用除法。

解题思路

代码

# -*- coding:utf-8 -*-

# 给定一个数组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]。

# 不能使用除法。

class Solution:

def multiply(self, A):

size = len(A)

B = [1] * size

# 下三角: B[i]=A[0]A[1]A[2]..A[i−1] = B[i−1]A[i−1]

for i in range(1, size):

B[i] = B[i - 1] * A[i - 1]

tmp = 1

# 上三角(从最后往前)tmp=A[−1]A[−2]A[−3]...

for i in range(size - 2, -1, -1):

tmp = tmp * A[i + 1]

B[i] = B[i] * tmp

return B

if __name__ == '__main__':

S = Solution()

print(S.multiply([2, 1, 3, 1, 4]))

52 正则表达式匹配

题目描述

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

解题思路

代码

# -*- coding:utf-8 -*-

# 请实现一个函数用来匹配包括'.'和'*'的正则表达式。

# 模式中的字符'.'表示任意一个字符,

# 而'*'表示它前面的字符可以出现任意次(包含0次)。

# 在本题中,匹配是指字符串的所有字符匹配整个模式。

# 例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,

# 但是与"aa.a"和"ab*a"均不匹配

class Solution:

# s和pattern都是字符串

def match(self, s, pattern):

# s和pattern都为空

if not s and not pattern:

return False

# s和pattern直接匹配

if s == pattern:

return True

# 当s为'', 如果pattern为'.',则返回True

# 当s为'', 如果pattern长度为1且不为'.', 或者pattern第二个字符不是*, 则pattern不可能为空, 返回False

# 若pattern长度不为1, 且第二个字符为*, pattern还有空的可能, 从第三个字符开始迭代

elif s == '':

if pattern == '.':

return True

elif len(pattern) == 1 or pattern[1] != '*':

return False

else:

return self.match(s, pattern[2:])

# 如果pattern长度不小于二, 而且pattern的第二个字符不是*的情况下

# 当 pattern[0] 不等于s[0], 且不为 . 的时候, s和pattern必不相等

# 否则, s 和 pattern 都右移一位, 继续比较

if len(pattern) >= 2 and pattern[1] != '*':

if s[0] != pattern[0] and pattern[0] != '.':

return False

else:

return self.match(s[1:], pattern[1:])

# 如果pattern长度不小于2, 且pattern第二个字符为*的情况下

# 如果s[0]不等于pattern[0], 且pattern[0]不为 . , 那么第一位比较不成功,

# pattern必须后移两位继续比较后面是否能和s第一位匹配

# 如果s[0]等于pattern[0], 或者pattern[0]为 . , 第一位匹配, 那么会有

# 1. aaa 和 a*a 这种情况, 星号代表了多个a, 因此s需要不断右移一位继续比较

# 2. a 和 a*a 中这情况, 这时候星号代表0个a, 因此s不需要右移, pattern需要右移两位

# 3. abc 和 a*bc 这种情况, 星号代表了1个a, s右移一位, pattern右移两位继续比较

elif len(pattern) >= 2 and pattern[1] == '*':

if s[0] != pattern[0] and pattern[0] != '.':

return self.match(s, pattern[2:])

else:

return self.match(s[1:], pattern) or self.match(s, pattern[2:]) or self.match(s[1:], pattern[2:])

# 除去上述pattern不小于2情况, 只剩下pattern等于1的情况, 因此如果pattern为".", 而且s长度为1, 返回True

elif pattern == '.' and len(s) == 1:

return True

return False

class Solution1:

# s, pattern都是字符串

def __init__(self):

self.dic = {}

def match(self, s, p):

if (s, p) in self.dic:

return self.dic[(s, p)]

if p == '':

return s == ''

if len(p) == 1 or p[1] != '*':

self.dic[(s[1:], p[1:])] = self.match(s[1:], p[1:])

return len(s) > 0 and (p[0] == '.' or p[0] == s[0]) and self.dic[(s[1:], p[1:])]

while len(s) and (p[0] == '.' or p[0] == s[0]):

self.dic[(s, p[2:])] = self.match(s, p[2:])

if self.match(s[:], p[2:]):

return True

s = s[1:]

self.dic[(s, p[2:])] = self.match(s, p[2:])

return self.dic[(s, p[2:])]

if __name__ == '__main__':

S = Solution1()

print(S.match('aaa', 'a*a'))

53 表示数值的字符串

题目描述

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

解题思路

代码

# -*- coding:utf-8 -*-

# 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。

# 例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。

# 但是"12e","1a3.14","1.2.3","+-5"和"12e+4.3"都不是。

class Solution:

def isNumeric(self, s):

isAllowDot = True

isAllowE = True

for i in range(len(s)):

if s[i] in "+-" and (i == 0 or s[i - 1] in "eE") and i < len(s) - 1:

continue

elif isAllowDot and s[i] == ".":

isAllowDot = False

if i >= len(s) - 1 or s[i + 1] not in "0123456789":

return False

elif isAllowE and s[i] in "Ee":

isAllowDot = False

isAllowE = False

if i >= len(s) - 1 or s[i + 1] not in "0123456789+-":

return False

elif s[i] not in "0123456789":

return False

return True

class Solution1:

# s字符串

def isNumeric(self, s):

INVALID = 0

SPACE = 1

SIGN = 2

DIGIT = 3

DOT = 4

EXPONENT = 5

# 0invalid, 1space, 2sign, 3digit, 4dot, 5exponent, 6num_inputs

transitionTable = [[-1, 0, 3, 1, 2, -1], # 0 no input or just spaces

[-1, 8, -1, 1, 4, 5], # 1 input is digits

[-1, -1, -1, 4, -1, -1], # 2 no digits in front just Dot

[-1, -1, -1, 1, 2, -1], # 3 sign

[-1, 8, -1, 4, -1, 5], # 4 digits and dot in front

[-1, -1, 6, 7, -1, -1], # 5 input 'e' or 'E'

[-1, -1, -1, 7, -1, -1], # 6 after 'e' input sign

[-1, 8, -1, 7, -1, -1], # 7 after 'e' input digits

[-1, 8, -1, -1, -1, -1]] # 8 after valid input input space

state = 0

i = 0

while i < len(s):

inputtype = INVALID

if s[i] == ' ':

inputtype = SPACE

elif s[i] == '-' or s[i] == '+':

inputtype = SIGN

elif s[i] in '0123456789':

inputtype = DIGIT

elif s[i] == '.':

inputtype = DOT

elif s[i] == 'e' or s[i] == 'E':

inputtype = EXPONENT

state = transitionTable[state][inputtype]

if state == -1:

return False

else:

i += 1

return state == 1 or state == 4 or state == 7 or state == 8

if __name__ == '__main__':

S = Solution()

print(S.isNumeric('-1234'))

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

题目描述

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

输出描述:

如果当前字符流没有存在出现一次的字符,返回#字符。

解题思路

代码

# -*- coding:utf-8 -*-

# 请实现一个函数用来找出字符流中第一个只出现一次的字符。

# 例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。

# 当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。

class Solution:

def __init__(self):

self.queue = []

self.memory = dict()

# 返回对应char

def FirstAppearingOnce(self):

while len(self.queue) and self.memory[self.queue[0]] > 1:

self.queue.pop(0)

return self.queue[0] if len(self.queue) else '#'

def Insert(self, char):

if char not in self.memory:

self.memory[char] = 0

self.memory[char] += 1

if self.memory[char] == 1:

self.queue.append(char)

if __name__ == '__main__':

S = Solution()

S.Insert('1')

S.Insert('2')

S.Insert('1')

S.Insert('1')

print(S.FirstAppearingOnce())

55 链表中环的入口结点

题目描述

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

解题思路

代码

# coding:utf-8

# 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null

class Node(object):

"""节点"""

def __init__(self, elem):

self.elem = elem

self.next = None

class SingleLinkList(object):

"""单链表"""

def __init__(self, node=None):

self.__head = node

def is_empty(self):

"""链表是否为空"""

return self.__head == None

def length(self):

"""链表长度"""

# cur游标,用来移动遍历节点

cur = self.__head

# count记录数量

count = 0

while cur != None:

count += 1

cur = cur.next

return count

def travel(self):

"""遍历整个链表"""

cur = self.__head

while cur != None:

print(cur.elem, end=" ")

cur = cur.next

print("")

def add(self, item):

"""链表头部添加元素,头插法"""

node = Node(item)

node.next = self.__head

self.__head = node

def append(self, item):

"""链表尾部添加元素, 尾插法"""

node = Node(item)

if self.is_empty():

self.__head = node

else:

cur = self.__head

while cur.next != None:

cur = cur.next

cur.next = node

def insert(self, pos, item):

"""指定位置添加元素

pos 从0开始

"""

if pos <= 0:

self.add(item)

elif pos > (self.length() - 1):

self.append(item)

else:

pre = self.__head

count = 0

while count < (pos - 1):

count += 1

pre = pre.next

# 当循环退出后,pre指向pos-1位置

node = Node(item)

node.next = pre.next

pre.next = node

def remove(self, item):

"""删除节点"""

cur = self.__head

pre = None

while cur != None:

if cur.elem == item:

# 先判断此结点是否是头节点

# 头节点

if cur == self.__head:

self.__head = cur.next

else:

pre.next = cur.next

break

else:

pre = cur

cur = cur.next

def search(self, item):

"""查找节点是否存在"""

cur = self.__head

while cur != None:

if cur.elem == item:

return True

else:

cur = cur.next

return False

def Loop(self):

"""链表尾部指向头"""

if self.is_empty():

self.__head = self.__head

else:

cur = self.__head

while cur.next != None:

cur = cur.next

cur.next = self.__head

def EntryNodeOfLoop(self):

head = self.__head

if head == None or head.next == None:

return None

slow = fast = head

while fast and fast.next:

slow = slow.next

fast = fast.next.next

if slow == fast:

fast = head

while fast != slow:

fast = fast.next

slow = slow.next

return fast

return None

if __name__ == "__main__":

ll = SingleLinkList()

ll.append(1)

ll.append(2)

ll.append(3)

ll.append(4)

ll.append(5)

ll.append(6)

ll.travel()

ll.Loop()

res = ll.EntryNodeOfLoop()

print(res.elem)

56 删除链表中重复的结点

题目描述

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

解题思路

代码

# coding:utf-8

# 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,

# 重复的结点不保留,返回链表头指针。

# 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

class Node(object):

"""节点"""

def __init__(self, elem):

self.elem = elem

self.next = None

class SingleLinkList(object):

"""单链表"""

def __init__(self, node=None):

self.__head = node

def is_empty(self):

"""链表是否为空"""

return self.__head == None

def length(self):

"""链表长度"""

# cur游标,用来移动遍历节点

cur = self.__head

# count记录数量

count = 0

while cur != None:

count += 1

cur = cur.next

return count

def travel(self):

"""遍历整个链表"""

cur = self.__head

while cur != None:

print(cur.elem, end=" ")

cur = cur.next

print("")

def add(self, item):

"""链表头部添加元素,头插法"""

node = Node(item)

node.next = self.__head

self.__head = node

def append(self, item):

"""链表尾部添加元素, 尾插法"""

node = Node(item)

if self.is_empty():

self.__head = node

else:

cur = self.__head

while cur.next != None:

cur = cur.next

cur.next = node

def insert(self, pos, item):

"""指定位置添加元素

pos 从0开始

"""

if pos <= 0:

self.add(item)

elif pos > (self.length() - 1):

self.append(item)

else:

pre = self.__head

count = 0

while count < (pos - 1):

count += 1

pre = pre.next

# 当循环退出后,pre指向pos-1位置

node = Node(item)

node.next = pre.next

pre.next = node

def remove(self, item):

"""删除节点"""

cur = self.__head

pre = None

while cur != None:

if cur.elem == item:

# 先判断此结点是否是头节点

# 头节点

if cur == self.__head:

self.__head = cur.next

else:

pre.next = cur.next

break

else:

pre = cur

cur = cur.next

def search(self, item):

"""查找节点是否存在"""

cur = self.__head

while cur != None:

if cur.elem == item:

return True

else:

cur = cur.next

return False

def get_head(self):

return self.__head

class Solution:

def deleteDuplication(self, pHead):

if pHead == None or pHead.next == None:

return pHead

dummy = Node(0)

dummy.next = pHead

pre = dummy

cur = dummy.next

while cur != None:

while cur.next and cur.next.elem == pre.next.elem:

cur = cur.next

if pre.next == cur:

pre = pre.next

else:

pre.next = cur.next

cur = cur.next

return dummy.next

if __name__ == "__main__":

ll = SingleLinkList()

ll.append(1)

ll.append(1)

ll.append(3)

ll.append(4)

ll.append(5)

ll.append(6)

ll.travel()

S = Solution()

ll_res = SingleLinkList(S.deleteDuplication(ll.get_head()))

ll_res.travel()

57 二叉树的下一个结点

题目描述

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

解题思路

代码

# -*- coding:utf-8 -*-

# 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。

# 注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

class TreeLinkNode:

def __init__(self, x):

self.val = x

self.left = None

self.right = None

self.next = None

# 分三种情况:

# a. 如果该结点存在右子结点,那么该结点的下一个结点是右子结点树上最左子结点

# b. 如果该结点不存在右子结点,且它是它父结点的左子结点,那么该结点的下一个结点是它的父结点

# c. 如果该结点既不存在右子结点,且也不是它父结点的左子结点,则需要一路向祖先结点搜索,

# 直到找到一个结点,该结点是其父亲结点的左子结点。如果这样的结点存在,

# 那么该结点的父亲结点就是我们要找的下一个结点。

class Solution:

def GetNext(self, pNode):

if pNode == None:

return None

# case a

if pNode.right:

tmp = pNode.right

while (tmp.left):

tmp = tmp.left

return tmp

p = pNode.next

while (p and p.right == pNode):

pNode = p

p = p.next

return p

if __name__ == "__main__":

S = Solution()

node = TreeLinkNode(1)

node1 = TreeLinkNode(2)

node2 = TreeLinkNode(3)

node3 = TreeLinkNode(4)

node.left = node1

node.right = node2

node.next = node3

print(S.GetNext(node).val)

58 对称的二叉树

题目描述

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

解题思路

代码

# -*- coding:utf-8 -*-

class TreeNode:

def __init__(self, x):

self.val = x

self.left = None

self.right = None

class Solution:

def isSymmetrical(self, pRoot):

if not pRoot:

return True

return self.recursiveTree(pRoot.left, pRoot.right)

def recursiveTree(self, left, right):

if not left and not right:

return True

if not left or not right:

return False

if left.val == right.val:

return self.recursiveTree(left.left, right.right) and self.recursiveTree(left.right, right.left)

return False

if __name__ == '__main__':

S = Solution()

root = TreeNode(0)

node0 = TreeNode(2)

node1 = TreeNode(3)

node2 = TreeNode(4)

node3 = TreeNode(2)

node4 = TreeNode(4)

node5 = TreeNode(2)

root.left = node0

root.right = node1

node1.left = node2

node1.right = node3

node3.left = node4

node4.left = node5

print(S.isSymmetrical(root))

59 按之字形顺序打印二叉树

题目描述

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

解题思路

代码

# -*- coding:utf-8 -*-

#

# 请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,

# 第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

class TreeNode:

def __init__(self, x):

self.val = x

self.left = None

self.right = None

class Solution:

def Print(self, pRoot):

if not pRoot:

return []

printArr = []

flag = 0

stack = [pRoot]

while stack:

tmp = []

tmp_stack = []

for node in stack:

tmp.append(node.val)

if node.left:

tmp_stack.append(node.left)

if node.right:

tmp_stack.append(node.right)

if flag % 2 == 1:

printArr.append(tmp[::-1])

else:

printArr.append(tmp)

flag = flag + 1

stack = tmp_stack[:]

return printArr

if __name__ == '__main__':

S = Solution()

root = TreeNode(0)

node0 = TreeNode(2)

node1 = TreeNode(3)

node2 = TreeNode(4)

node3 = TreeNode(2)

node4 = TreeNode(4)

node5 = TreeNode(2)

root.left = node0

root.right = node1

node1.left = node2

node1.right = node3

node3.left = node4

node4.left = node5

print(S.Print(root))

60 把二叉树打印成多行

题目描述

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

解题思路

代码

# -*- coding:utf-8 -*-

# 从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

class TreeNode:

def __init__(self, x):

self.val = x

self.left = None

self.right = None

class Solution:

def Print(self, pRoot):

if not pRoot:

return []

printArr = []

stack = [pRoot]

while stack:

tmp = []

tmp_stack = []

for node in stack:

tmp.append(node.val)

if node.left:

tmp_stack.append(node.left)

if node.right:

tmp_stack.append(node.right)

printArr.append(tmp)

stack = tmp_stack[:]

return printArr

if __name__ == '__main__':

S = Solution()

root = TreeNode(0)

node0 = TreeNode(2)

node1 = TreeNode(3)

node2 = TreeNode(4)

node3 = TreeNode(2)

node4 = TreeNode(4)

node5 = TreeNode(2)

root.left = node0

root.right = node1

node1.left = node2

node1.right = node3

node3.left = node4

node4.left = node5

print(S.Print(root))

61 序列化二叉树

题目描述

请实现两个函数,分别用来序列化和反序列化二叉树

二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。

二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。

解题思路

代码

# -*- coding:utf-8 -*-

# 请实现两个函数,分别用来序列化和反序列化二叉树

# 先序遍历,root->left->right

class TreeNode:

def __init__(self, x):

self.val = x

self.left = None

self.right = None

class Solution:

def Serialize(self, pRoot):

serializeStr = ''

if pRoot == None:

return '#'

stack = []

while pRoot or stack:

while pRoot:

serializeStr += str(pRoot.val) + ','

stack.append(pRoot)

pRoot = pRoot.left

serializeStr += '#,'

pRoot = stack.pop()

pRoot = pRoot.right

serializeStr = serializeStr[:-1]

return serializeStr

def Deserialize(self, s):

serialize = s.split(',')

tree, sp = self.deserialize(serialize, 0)

return tree

def deserialize(self, s, sp):

if sp >= len(s) or s[sp] == '#':

return None, sp + 1

node = TreeNode(int(s[sp]))

sp += 1

node.left, sp = self.deserialize(s, sp)

node.right, sp = self.deserialize(s, sp)

return node, sp

if __name__ == '__main__':

S = Solution()

root = TreeNode(0)

node0 = TreeNode(2)

node1 = TreeNode(3)

node2 = TreeNode(4)

node3 = TreeNode(2)

node4 = TreeNode(4)

node5 = TreeNode(2)

root.left = node0

root.right = node1

node1.left = node2

node1.right = node3

node3.left = node4

node4.left = node5

ser = S.Serialize(root)

print(ser)

ser = S.Serialize(S.Deserialize(ser))

print(ser)

62 二叉搜索树的第k个结点

题目描述

给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。

解题思路

代码

# -*- coding:utf-8 -*-

# 给定一棵二叉搜索树,请找出其中的第k小的结点。

# 例如,(5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4。

class TreeNode:

def __init__(self, x):

self.val = x

self.left = None

self.right = None

class Solution:

def KthNode(self, pRoot, k):

stack = []

while True:

if pRoot:

stack.append(pRoot)

pRoot = pRoot.left

else:

if not stack:

return

pRoot = stack.pop()

k = k - 1

if k == 0:

return pRoot.val

else:

pRoot = pRoot.right

if __name__ == '__main__':

S = Solution()

root = TreeNode(0)

node0 = TreeNode(2)

node1 = TreeNode(3)

node2 = TreeNode(4)

node3 = TreeNode(2)

node4 = TreeNode(4)

node5 = TreeNode(2)

root.left = node0

root.right = node1

node1.left = node2

node1.right = node3

node3.left = node4

node4.left = node5

print(S.KthNode(root, 1))

63 数据流中的中位数

题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

解题思路

代码

# -*- coding:utf-8 -*-

# 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,

# 那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,

# 那么中位数就是所有数值排序之后中间两个数的平均值。

# 我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。

from heapq import *

class Solution:

def __init__(self):

self.left = []

self.right = []

self.count = 0

def Insert(self, num):

if self.count & 1 == 0:

self.left.append(num)

else:

self.right.append(num)

self.count += 1

def GetMedian(self, x):

if self.count == 1:

return self.left[0]

self.MaxHeap(self.left)

self.MinHeap(self.right)

if self.left[0] > self.right[0]:

self.left[0], self.right[0] = self.right[0], self.left[0]

self.MaxHeap(self.left)

self.MinHeap(self.right)

if self.count & 1 == 0:

return (self.left[0] + self.right[0]) / 2.0

else:

return self.left[0]

def MaxHeap(self, alist):

length = len(alist)

if alist == None or length <= 0:

return

if length == 1:

return alist

for i in range(length // 2 - 1, -1, -1):

k = i

temp = alist[k]

heap = False

while not heap and 2 * k < length - 1:

index = 2 * k + 1

if index < length - 1:

if alist[index] < alist[index + 1]: index += 1

if temp >= alist[index]:

heap = True

else:

alist[k] = alist[index]

k = index

alist[k] = temp

def MinHeap(self, alist):

length = len(alist)

if alist == None or length <= 0:

return

if length == 1:

return alist

for i in range(length // 2 - 1, -1, -1):

k = i

temp = alist[k]

heap = False

while not heap and 2 * k < length - 1:

index = 2 * k + 1

if index < length - 1:

if alist[index] > alist[index + 1]: index += 1

if temp <= alist[index]:

heap = True

else:

alist[k] = alist[index]

k = index

alist[k] = temp

class Solution1:

def __init__(self):

self.heaps = [], []

def Insert(self, num):

small, large = self.heaps

heappush(small, -heappushpop(large, num))

if len(large) < len(small):

heappush(large, -heappop(small))

def GetMedian(self, x):

small, large = self.heaps

if len(large) > len(small):

return float(large[0])

return (large[0] - small[0]) / 2.0

if __name__ == '__main__':

S = Solution1()

S.Insert(1)

S.Insert(2)

S.Insert(3)

S.Insert(4)

S.Insert(5)

print(S.GetMedian(1))

64 滑动窗口的最大值

题目描述

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。

解题思路

代码

# -*- coding:utf-8 -*-

# 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。

# 例如,如果输入数组{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]}。

class Solution:

def maxInWindows(self, num, size):

if size <= 0 or len(num) <= 0:

return []

res = []

for i in range(len(num) - size + 1):

res.append(max(num[i:i + size]))

return res

def maxInWindows_deque(self, num, size):

if num == None or size <= 0:

return []

deque = []

if len(num) >= size:

index = []

for i in range(size):

while len(index) > 0 and num[i] > num[index[-1]]:

index.pop()

index.append(i)

for i in range(size, len(num)):

deque.append(num[index[0]])

while len(index) > 0 and num[i] > num[index[-1]]:

index.pop()

if len(index) > 0 and index[0] <= i - size:

index.pop(0)

index.append(i)

deque.append(num[index[0]])

return deque

if __name__ == '__main__':

S = Solution()

print(S.maxInWindows_deque([1, 2, 3, 4, 5, 6], 2))

65 矩阵中的路径

题目描述

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

解题思路

代码

# -*- coding:utf-8 -*-

# 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。

# 路径可以从矩阵中的任意一个格子开始,

# 每一步可以在矩阵中向左,向右,向上,向下移动一个格子。

# 如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。

# 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,

# 但是矩阵中不包含"abcb"路径,

# 因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,

# 路径不能再次进入该格子。

class Solution:

def hasPath(self, matrix, rows, cols, path):

if len(matrix) == 0 or len(matrix) != rows * cols or len(path) == 0:

return False

visited = [False] * len(matrix)

pathlength = [0]

# 以矩阵中每一个位置作为起点进行搜索

for i in range(rows):

for j in range(cols):

if self.haspath(matrix, rows, cols, path, j, i, visited, pathlength):

return True

return False

# 判断矩阵位置(x,y)的字符能否加入已找到的路径中

def haspath(self, matrix, rows, cols, path, x, y, visited, pathlength):

'''

:param matrix:字符矩阵

:param rows:矩阵的行数

:param cols:矩阵的列数

:param path:需要寻找的路径

:param x:当前位置的横坐标(对应列数)

:param y:当前位置的纵坐标(对应行数)

:param visited:访问标志数组

:param pathlength:已经找到的路径长度

:return:是否存在路径

'''

if pathlength[0] == len(path):

return True

curhaspath = False

# 参数校验:

# 1、位置坐标不超过行列数

# 2、当前位置字符等于路径中对应位置的字符

# 3、当前位置未存在于当前已找到的路径中

if 0 <= x < cols \

and 0 <= y < rows \

and matrix[y * cols + x] == path[pathlength[0]] \

and not visited[y * cols + x]:

visited[y * cols + x] = True

pathlength[0] += 1

# 分别向左,向右,向上,向下移动一个格子,任一方向能够继续往下走均可

curhaspath = self.haspath(matrix, rows, cols, path, x - 1, y, visited, pathlength) \

or self.haspath(matrix, rows, cols, path, x, y - 1, visited, pathlength) \

or self.haspath(matrix, rows, cols, path, x + 1, y, visited, pathlength) \

or self.haspath(matrix, rows, cols, path, x, y + 1, visited, pathlength)

# 如果不能再走下一步,需要回退到上一状态

if not curhaspath:

pathlength[0] -= 1

visited[y * cols + x] = False

return curhaspath

if __name__ == '__main__':

S = Solution()

print(S.hasPath(['a', 'b', 'c', 'e', 's', 'f', 'c', 's', 'a', 'd', 'e', 'e'], 3, 4, 'bcced'))

66 机器人的运动范围

题目描述

地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

解题思路

代码

# -*- coding:utf-8 -*-

# 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,

# 每一次只能向左,右,上,下四个方向移动一格,

# 但是不能进入行坐标和列坐标的数位之和大于k的格子。

# 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。

# 但是,它不能进入方格(35,38),因为3+5+3+8 = 19。

# 请问该机器人能够达到多少个格子?

class Solution:

def movingCount(self, threshold, rows, cols):

memories = set()

def dfs(i, j):

if not (sum(map(int, str(i) + str(j))) <= threshold) or (i, j) in memories:

return

memories.add((i, j))

if i != rows - 1:

dfs(i + 1, j)

if j != cols - 1:

dfs(i, j + 1)

dfs(0, 0)

return len(memories)

if __name__ == '__main__':

S = Solution()

print(S.movingCount(18, 40, 40))

print(str(123) + str(543))

print(list(map(int, str(123) + str(543))))

print(list(map(int, '123543')))

print(sum(map(int, str(123) + str(543))))

python中myf什么意思_剑指Offer-Python题解(三)相关推荐

  1. python 二维数组长度_剑指offer二维数组中的查找【Java+Python】

    点击上方"蓝字",关注了解更多 二维数组中的查找 1. 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序 ...

  2. python删除链表中重复的节点_剑指offer:删除链表中重复的节点

    题目描述 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针. 例如,链表1->2->3->3->4->4->5 处理后 ...

  3. python36块砖36人搬算法_剑指offer python实现 66道算法题

    所有题目均采用牛客网在线编程实现,代码均在github上. 数组 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组 ...

  4. 在数组中查找指定元素_剑指 offer 第一题: 二维数组中的查找

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  5. python剑指offer面试题_剑指Offer(Python语言)面试题38

    面试题38:字符串的排列 题目:输入一个字符串,打印出该字符串中字符的所有排列.例如,输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca和cba. # - ...

  6. leetcode 打印_剑指 Offer 总结 - leetcode 剑指offer系列

    剑指 Offer 系列完结撒花!! 本篇文章是对整个系列的精华总结, 对系列的每篇文章进行了分类, 并用一句话概括每道题的思路, 方便大家理解和记忆, 当然也包含原文完整链接供大家参考 总的来说, 写 ...

  7. 字符串全排列算法_C#版_剑指OFFER

    字符串全排列算法_C#版_剑指OFFER 题目描述 ​题目描述 输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组. 例如输入字符串ABC,则输出由字符A, ...

  8. 剑指offer 面试题三 找出数组中重复的数字

    1 import org.junit.Test; 2 3 import java.util.Arrays; 4 import java.util.HashSet; 5 6 public class D ...

  9. 剑指Offer(Python多种思路实现):树的子结构

    剑指Offer(Python多种思路实现):树的子结构 面试26题: 题目:树的子结构 题:输入两棵二叉树A和B,判断B是不是A的子结构. 解题思路一:递归,注意空指针的情况. class Solut ...

最新文章

  1. 浏览器快捷键_用浏览器输入框代替Alfred - 介绍快速唤起浏览器输入框的方法,以及它能怎么取代 Alfred...
  2. 堆栈 cookie 检测代码检测到基于堆栈的缓冲区溢出_WhatsApp缓冲区漏洞曝光 攻击者可通过MP4文件执行远程代码...
  3. 经典谷歌面试题-扔鸡蛋问题
  4. 【自用】手工编译lnmp环境
  5. Red5开发第一步-Hello World
  6. 如何使用iMazing为iPad创建配置文件
  7. 计算机二级c语言上机答案全,计算机二级C语言上机题库答案大全及上机说明
  8. 2021软考软件设计师真题
  9. 大学英语综合教程四 Unit 2 课文内容英译中 中英翻译
  10. Spatial Dropout
  11. 亚马逊云科技助力学习者轻松开启云计算知识学习之旅
  12. 抽丝拨茧——EventBus源码解析
  13. Neodynamic Barcode Professional for Windows Forms 14.0
  14. 思科路由器配置GRE隧道
  15. 大学计算机教学内容体系,大学计算机教学内容体系建设与改革论文
  16. linux crash工具用法,使用crash工具看懂slab
  17. css玻璃雨滴效果,CSS实现雨滴动画效果的实例代码
  18. 华为手机配什么蓝牙耳机好?适合华为手机的蓝牙耳机推荐
  19. 等保测评--工业控制系统安全扩展要求
  20. 用python对文件内容差异对比

热门文章

  1. C语言如何翻译一个语句
  2. Matlab三角网线和三角曲面图绘制
  3. php 所有版本下载地址
  4. 处理系统装机后BitLocker锁硬盘问题
  5. 被问 Linux 命令 su 和 sudo 的区别?当场蒙了!
  6. 流程控制之分支结构:英制单位英寸与公制单位厘米互换
  7. 正厚知识 | 什么是操作系统
  8. 1.开源单点登录系统CAS 入门
  9. これ/それ/あれ/どれ
  10. 内核地址消毒剂(KASAN)