剑指0ffer—67道在线编程—jz26~jz30
jz26 二叉搜索树与双向链表
题目描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思路分析:
二叉搜索树特点:
根节点的值大于其左子树中任意一个节点的值,小于其右节点中任意一节点的值,这一规则适用于二叉搜索树中的每一个节点。
根据二叉搜索树的特点,中序遍历二叉树可得到排序的结点。因此,可以中序遍历加上递归处理解决这问题。
【代码实现】
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def Convert(self, pRootOfTree):
# write code here
#1、如果树为空,或没有左右子树,则返回原树
if not pRootOfTree:
return pRootOfTree
if not pRootOfTree.left and not pRootOfTree.right:
return pRootOfTree
#中序遍历加递归
#2、处理左子树:先调用自身判断即前面那一部分,如果都存在,则继续下一行
self.Convert(pRootOfTree.left)
left=pRootOfTree.left
#2.1连接根与左子树最大节点
if left:
while (left.right):
left=left.right
pRootOfTree.left,left.right=left,pRootOfTree
#3.1处理右子树
self.Convert(pRootOfTree.right)
right=pRootOfTree.right
#3.2连接根与右子树最小结点
if right:
while(right.left):
right=right.left
pRootOfTree.right,right.left=right,pRootOfTree
#4、while循环更新BST
while(pRootOfTree.left):
pRootOfTree=pRootOfTree.left
return pRootOfTree
jz27 字符串的排列
题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
思路分析:
1、固定第一元素,第一元素的可能取值为字符串的不同字符
2、固定第一元素的情况下,其他元素随便排列
3、利用集合添加并去重的特点,创建一个集合,添加所有可能的排列
集合添加去重:
a=[1,2,3,2]
b=set(a)
b
{1, 2, 3}
b.add(3)
b
{1, 2, 3}
b.add(4)
b
{1, 2, 3, 4}
sorted(b)#集合b形式变为列表形式
[1, 2, 3, 4]
【代码实现】
# -*- coding:utf-8 -*-
class Solution:
def Permutation(self, string):
#1、判断字符串长度
if len(string)<=1:
return string
# 2、创建集合,以存放可能的字符串
res=set()
# 3、遍历字符串,固定第一个元素,第一个元素可取字符串中所有字母;然后递归
for i in range(len(string)):
for j in self.Permutation(string[:i]+string[i+1:]):#第一元素固定,其他元素随便排列
res.add(string[i]+j)#集合添加方法add(),添加的过程中会去重,如果添加元素,原集合中有,就不再添加了
return sorted(res)#集合排序以后,会变成列表的形式
jz28 数组中出现次数超过一半的数字
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路分析:
排序比较法
1、数组排序
2、计算出中位数
3、如果中位数的出现次数大于数组长度的一半,则返回中位数,否则不存在,返回0。
【代码实现】
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
numbers=sorted(numbers)
mid_len=len(numbers)//2
median=numbers[mid_len]#中位数
if numbers.count(median)>mid_len:
return median
else:
return 0
jz29 最小的k个数
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
思路分析:
这道题比较简单,只需将数组排序,然后再取前k个数即可
但是必须注意特殊情况的处理:
1、如果数组为空,则返回列表即可。
2、如果取出的个数大于数组的长度,返回空值。
【代码实现】
# -*- coding:utf-8 -*-
class Solution:
def GetLeastNumbers_Solution(self, lists, k):
# write code here
if lists is None:
return lists
n=len(lists)
if k>n:
return []
lists=sorted(lists)
return lists[:k]
jz30 连续子数组的最大和
题目描述
HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
思路分析:
动态规划法
初始化连续和max_sum为零,建一空列表list_sum存储连续和。
1、遍历数组的开头往下走,max_sum记录连续的和,并将连续和添加到list_sum表里。
- 若max_sum大于零,继续累加
- 若max_sum小于零,则令max_sum归零,从下一元素开始累计加和。
3、返回list_sum表里的最大值,即为所求。
【代码实现】
# -*- coding:utf-8 -*-
class Solution:
def FindGreatestSumOfSubArray(self, array):
# write code here
if len(array)<=0:
return []
max_sum=0
list_sum=[]
for a in array:
max_sum=max_sum+a
list_sum.append(max_sum)
if max_sum>0:
continue
else:
max_sum=0
print(list_sum)
return max(list_sum)