剑指offer
1. 全排列
题目描述
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
示例1
输入
[3,32,321]
返回值
"321323"
# -*- coding:utf-8 -*-
"""
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,
打印能拼接出的所有数字中最小的一个
"""
import itertools #使用模块产生可迭代对象
class Solution(object):
def PrintMinNumber(self, numbers):
# write code here
assert len(numbers)>0 #
lis = []
for l in list(itertools.permutations(numbers)):#全排列迭代成元组
str0 = [str(i) for i in l] #l为元组类型转换成字符列表str0
l = ''.join(str0) #将字符数字连接成整体字符串
lis.append(int(l))#将字符l转换成整型存入到lis列表中
return min(lis)#返回lis列表中的最小值
# -*- coding:utf-8 -*-
import itertools
class Solution:
def PrintMinNumber(self, numbers):
if len(numbers)==0:
return ""
if len(numbers)==1:
return numbers[0]
res=[]
for i in numbers:
res.append(str(i))
temp = list(set(map("".join, itertools.permutations(res))))
return str(min(temp))
join()
:连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串
map(function, iterable, ...)
会根据提供的函数对指定序列做映射。第一个参数 function
以参数序列中的每一个元素调用 function 函数,返回包含每次 function
函数返回值的新列表。
2. 斐波那契数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
0、1、2、3、5、8、
#1、递归方法,python调试过程中速度太慢没有通过
class Solution:
def Fibonacci(self,n):
if n<=1:
return n
else:
return self.Fibonacci(n-1)+self.Fibonacci(n-2)
#2、利用for循环语句与数列的方法进行运算,将数列加入列表中,并对最后一个元素进行返回。
class Solution:
def Fibonacci(self, n):
num = []
for i in range(n+1): #最后1个数字不包含
if i == 0:
num.append(0)
elif i == 1:
num.append(1)
else:
num.append(num[-1]+num[-2])
return num[-1] #list[-1]表示最后一个元素,list[-2]表示倒数第二个元素
3. 最大连续子序列
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n).
示例1
输入:
[1,-2,3,10,-4,7,2,-5]
复制
返回值:
18
输入的数组为{1,-2,3,10,-4,7,2,-5},和最大的子数组为{3,10,-4,7,2},因此输出为该子数组的和 18。
设dp[i]为以下标i元素结尾的最大和
递推式:dp[i]=max(dp[i-1]+array[i],array[i])
初始状态 dp[0]=array[0]
思路就是:如果该元素之前的最大和加上当前元素值 小于 当前元素,那就从当前元素重新开始计算,否则按两者加和作为此处的最大和。
最后得到的dp数组中最大的那一个,就是答案。
class Solution:
def FindGreatestSumOfSubArray(self, array):
# write code here
dp = [0]*len(array)
dp[0] = array[0]
#或直接拷贝一份:dp = array[:],修改dp不会修改array
for i in range(1,len(array)): #因为有i-1,所以要从1开始循环
dp[i] = max(dp[i-1] + array[i], array[i])
return max(dp)
4. 跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
f(0)=0,f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5… 可以总结出f(n) =f(n-1) +f(n-2)的规律
class Solution:
def jumpFloor(self, number):
# write code here
num = []
for i in range(number+1): #最后1个数字不包含
if i == 0:
num.append(0)
elif i == 1:
num.append(1)
elif i == 2:
num.append(2)
else:
num.append(num[-1]+num[-2])
return num[-1] #list[-1]表示最后一个元素,list[-2]表示倒数第二个元素
5. 二维数组遍历
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]
给定 target = 7,返回 true。
给定 target = 3,返回 false。
class Solution:
# array 二维列表
def Find(self, target, array):
# write code here
for i in array:
if target in i:
return True
return False
6. 字符串内置函数
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
class Solution:
def replaceSpace(self , s ):
# write code here
arr = s.split(" ") # 字符串转列表,以" "分开,split传参分割符
res = ("%20").join(arr) # 列表转字符串,元素之间以"%20"连接,join传参列表
res1 = str(res) # str函数将参数转化为字符串
return res1
class Solution:
def replaceSpace(self , s ):
# write code here
return s.replace(' ','%20')
7. 链表
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
输入:
{67,0,24,58}
返回值:
[58,24,0,67]
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
if not listNode:
return []
stack = []
while listNode: # 遍历链表
stack.append(listNode.val) # 获取链表当前节点的 value 值,val即可获取
listNode = listNode.next # 当前节点向后移动
return stack[::-1] # 列表的切片操作,前两个参数是截取范围,缺省表示全长截取,第三个参数1表示正向,-1表示反向
OJ
1. 输入输出
两行输入:
# 第一行输入两个整数
# 第二行输入多个整数
def func():
a, b = map(int, input().strip().split())
l = input().strip().split()
if __name__ == "__main__":
func()
# 第一行输入1个整数
# 第二行输入多个整数
# 输出多个整数
def func():
n = int(input())
arr = list(map(int, input().split(" ")))
print("%d %d %d" % (a, b, c))
if __name__ == "__main__":
func()
多行输入(每行输入一个整数,输入到文件末尾结束*):
# 多行整数
def func():
while True:
try:
n = int(input())
print(res)
except EOFError:
break
if __name__ == "__main__":
func()
2. 硬币分法
在一个国家仅有1分、2分、3分硬币,将n块钱兑换成硬币,共有多少种分法。
#!/usr/bin/python3
# n = x + 2y +3z ,也就是求给定n值的情况下,x,y,z的组合有多少种
def func():
while True:
try:
n = int(input())
coin3 = n//3 # 先确定3分钱的个数,最多有coin3个三分钱硬币,3分钱硬币共有coin3种分法
res = 0
for i in range(coin3+1):
res = res + (n - 3*i)//2 + 1 # 剩余的钱多能有coin2=(n-3*i)//2个两分钱硬币,2分钱硬币共有coin2中分法,最后加上全是1分钱硬币的情况,1分钱的分法在3分钱和2分钱确定之后自动确定,只有唯一解
print(res)
except (ValueError, EOFError):
break
if __name__ == "__main__":
func()
python 中 // 和 int(a/b)的区别:
print(13/2) # 6.5
print(13//2) # 6
print(int(6.5)) # 6
print(-13/2) # -6.5
print(-13//2) # -7
print(int(-6.5)) # -6
"""
整除号://
整除运算,结果向负无穷方向去,取最近的整数
浮点数除法:/
返回float型
使用强制类型转换取整数:int()
结果向0靠近,取最近的整数
"""
3. 逆序对
若i<j,A[i]>A[j],则称A[i]、A[j]为一对逆序对
输入:
第一行输入一个正整数,表示数列A的个数
从第二行起的n行,每行按顺序输入数列A的1个元素
def func():
n = int(input())
arr = []
cnt = 0
for _ in range(n):
arr.append(int(input()))
for i in range(n):
for j in range(i+1,n):
if int(arr[i]) > int(arr[j]):
cnt = cnt +1
print(cnt)
if __name__ == "__main__":
func()
4. 升级加薪(区间覆盖问题)
H公司共有n个员工,每个人都有唯一的编号(从1到n),升级形式:在[l, r]区间内的所有员工升一级。每个员工刚入职都是0级。在一年之中H公司共进行了m此升级。请计算出一年每位员工的级别。
输入:
第一行有两个整数,n和m
接下来m行,每行包含两个整数l和r,表示编号在l和r之前的所有员工升一级。
输出:
n个整数,表示员工的级别
样例:
输入
3 2
1 3
2 3
输出:
1 2 2
def func():
n, m = (int(i) for i in input().split())
arr = [0] * (n+2)
for i in range(m):
l, r = (int(i), for i in input().split())
arr[l-1] += 1
arr[r] -= 1
t = 0
l = []
for i in range(n):
t += arr[i]
l.append(str(t))
print(" ".join(l))
if __name__ == "__main__":
func()
####
a = [1,2,3]
print(" ".join(str(i) for i in a)) # 输出整数列表,元素之间加空格
字符串和列表
列表转字符串列表、整数
list1 = [1, 2, 3]
str1 = "".join([str(i) for i in list1])
num1 = int(str1)
print(isinstance(num1, int))
>>>
True
字符串转列表
str1 = "a, b, c"
list1 = str1.split(",")
print(list1)
>>>
['a', ' b', ' c']
字符串和列表反转
a = 'i lova u'
b = a[::-1]
print(b)
>>> u avol i
a = ["i","love","u"]
b = a[::-1]
print(b)
>> ['u', 'love', 'i']
1. 字符串
https://blog.youkuaiyun.com/qq_39241986/article/details/107805010
# str.capitalize()、str.upper()、str.lower()、str.swapcase()、str.title()
# str.capitalize()将字符串的第一个字母变成大写,其他字母变小写。
str1 = "python go go go"
str2 = str1.capitalize()
print(str2)
>>> Python go go go
# str.upper()将字符串中的小写字母转为大写字母。
str1 = "python go go go"
str2 = str1.upper()
print(str2)
>>> PYTHON GO GO GO
# str.lower()转换字符串中所有大写字符为小写。
# str.swapcase()对字符串的大小写字母进行转换,小写变大写,大写变小写。
# str.title()返回"标题化"的字符串,所有单词的首个字母转化为大写,其余字母均为小写。
str1 = "python go go go"
str2 = str1.title()
print(str2)
>>> Python Go Go Go
# str.count(sub, start, end) 统计字符串里某个字符出现的次数。可选参数为在字符串搜索的开始与结束位置。
# start, end遵循**“左闭右开”**原则。
str1 = "banana"
sum1 = str1.count('a')
print(sum1)
>>> 3
# str.endswith(suffix, start, end)和str.startswith(substr, beg, end) 判断字符串是否以指定后缀结尾/开头,如果以指定后缀「结尾」/「开头」返回 True,否则返回 False。
# start, end遵循**“左闭右开”**原则。
str1 = 'Hello World!'
bool1 = str1.endswith('!')
bool2 = str1.startswith('H')
print(bool1,bool2)
>>> True True
# str.find(str, beg, end)和str.index(str, beg, end) 检测字符串中是否包含子字符串 str ,如果指定范围内如果包含指定索引值,返回的是索引值在字符串中的起始位置。如果不包含索引值,str.find()返回-1,str.index()报错
str0 = 'Hello World!'
index = str0.find('e')
print(index)
>>> 1
# str.isalnum()、str.isalpha()、str.isdigit()、str.isnumeric()、str.islower()、str.isspace()、str.istitle()、str.isupper()
# str.isalnum()检测字符串是否由字母和数字组成。
# str.isalpha()检测字符串是否只由字母或文字组成。
# str.isdigit()检测字符串是否只由数字组成。「True:」 Unicode数字,byte数字(单字节),全角数字(双字节)「False:」 汉字数字,罗马数字,小数
# str.isnumeric()检测字符串是否只由数字组成。「True:」 Unicode 数字,全角数字(双字节),汉字数字「False:」 小数,罗马数字
# str.islower()检测字符串是否由小写字母组成。
# str.isspace()检测字符串是否只由空白字符组成。
# str.istitle()检测字符串中所有的单词拼写首字母是否为大写,且其他字母为小写。
# str.isupper()检测字符串中所有的字母是否都为大写。
# str.join()将序列中的元素以指定的字符连接生成一个新的字符串。
s1 = "-"
s2 = ""
seq = ("r", "u", "n", "o", "o", "b") # 字符串序列
print (s1.join( seq ))
print (s2.join( seq ))
>>> r-u-n-o-o-b
runoob
# len() 返回对象(字符、列表、元组等)长度或项目个数。
# str.lstrip()、str.rstrip()、str.strip() 截掉字符串「左边」/「右边」/「左右」两侧的空格或指定字符。
str0 = ' Hello World!'
str0.lstrip()
>>> 'Hello World!'
str1 = 'aaaa Hello World!'
str1.lstrip('a')
>>> ' Hello World!'
# find()
#find函数(查找and是否在string_example字符串中)
string_example = "hello world itheima and itheimaApp"
index = string_example.find("and")
print(index)
#若未找到则返回-1
index1 = string_example.find("ans")
print(index1)
>> 20
-1
# str.replace(old, new, max)
# old -- 将被替换的子字符串。
# new -- 新字符串,用于替换old子字符串。
# max -- 可选字符串, 替换不超过 max 次
#replace函数把字符串中的old(旧的字符串)替换成new(新的字符串)
old_string = "hello world world itheima world and itheimaApp"
#参数说明:world:需要被替换掉的字符串;worlds:将world换成worlds;2:需要被替换的次数不超过2次
new_string =old_string.replace("world","worlds",2)
>>> hello worlds worlds itheima world and itheimaApp
# str.rfind(str, beg, end)和str.rindex(str, beg, end)
str.rfind()返回字符串最后一次出现的位置,如果没有匹配项则返回-1。
str.rindex()返回字符串最后一次出现的位置,如果没有匹配的字符串会报异常。
# str.split(str, num)
# str -- 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
# num -- 分割次数。默认为 -1, 即分隔所有。
txt = "print#hello#world#!"
txt.split("#")
>>> ['print', 'hello', 'world', '!']
2. 列表切片
https://www.cnblogs.com/xuchunlin/p/6045282.html
https://blog.youkuaiyun.com/weixin_43970977/article/details/88032412
https://www.cnblogs.com/twelvezuo/p/12068902.html
# len()
li = [1,2,3,4,5,6,7]
len1 = len(li)
print(len1)
>>> 7
# min()
li = [-1,1,2,3,4,5,6,7]
len1 = min(li)
print(len1)
>>> -1
# max()
li = [-1,1,2,3,4,5,6,7]
len1 = max(li)
print(len1)
>>> 7
# sum()
li = [-1,1,2,3,4,5,6,7]
len1 = sum(li)
print(len1)
>>> 27
# count()
list1 = [1,1,2,3,4,5,5,5]
count = list1.count(5)
print(count)
>>> 3
# append()
list1 = [1,1,2,3,4,5,5,5]
list1.append("a")
print(list1)
>>> [1, 1, 2, 3, 4, 5, 5, 5, 'a']
# 注意 append()和extend()的区别
list1 = [1,1,2,3,4,5,5,5]
list2 = ["a","b","c"]
list1.append(list2)
print(list1)
>>> [1, 1, 2, 3, 4, 5, 5, 5, ['a', 'b', 'c']]
# extend()
list1 = [1,1,2,3,4,5,5,5]
list2 = ["a","b","c"]
list1.extend(list2)
print(list1)
>>> [1, 1, 2, 3, 4, 5, 5, 5, 'a', 'b', 'c']
# index() 函数用于从列表中找出某个值第一个匹配项的索引位置。
list1 = [1,1,2,3,4,5,5,5]
index = list1.index(5)
print(index)
>>> 5
# insert()
list1 = [1,1,2,3,4,5,5,5]
list1.insert(2,"a")
print(list1)
>>> [1, 1, 'a', 2, 3, 4, 5, 5, 5]
# pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。可以指定弹出某个元素。该方法返回从列表中移除的元素对象。
list1 = [1,1,"a",3,4,5,5,5]
pop = list1.pop(2)
print(list1)
print(pop)
>>> [1, 1, 3, 4, 5, 5, 5]
>>> a
list1 = [1,1,"a",3,4,5,5,5]
list1.pop(2)
print(list1)
>>> [1, 1, 3, 4, 5, 5, 5]
# remove() 函数用于移除列表中某个值的第一个匹配项。
list1 = [1,1,"a",3,4,5,5,5]
list1.remove(5)
print(list1)
>>> [1, 1, 'a', 3, 4, 5, 5]
# reverse() 函数用于反向列表中元素。
list1 = [1,1,"a",3,4,5,5,5]
list1.reverse()
print(list1)
>>> [5, 5, 5, 4, 3, 'a', 1, 1]
# sort() 函数用于对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数。
# list.sort( key=None, reverse=False)参数:
#key:主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。reverse:排序规则,reverse = True降序,reverse = False升序(默认)。
list1 = [1,1,6,3,4,5,5,5]
list1.sort()
print(list1)
>>> [1, 1, 3, 4, 5, 5, 5, 6]
list1 = [1,1,6,3,4,5,5,5]
list1.sort(reverse=True)
print(list1)
>>> [6, 5, 5, 5, 4, 3, 1, 1]
# clear() 函数用于清空列表。
list1 = [1,1,6,3,4,5,5,5]
list1.clear()
print(list1)
>>> []
# copy() 函数用于复制列表。
list1 = [1,1,6,3,4,5,5,5]
list2 = list1.copy()
print(list2)
>>> [1, 1, 6, 3, 4, 5, 5, 5]
# 列表切片
li = [1,2,3,4,5,6,7]
print(li[1:]) #输出[2,3,4,5,6,7],省略终止索引,表示取起始索引之后的所有值,等效于li[1:len(li)]
print(li[:3]) #输出[1,2,3],省略起始索引,表示从0开始取,等效于li[0:3]
print(li[:]) #输出[1,2,3,4,5,6,7],省略起始索引、终止索引、步长值表示取全部,等效于li[0:len(li):1]
print(li[::]) #输出[1,2,3,4,5,6,7],省略起始索引、终止索引、步长值表示取全部,等效于li[0:len(li):1]
print(li[::-1]) #输出[7,6,5,4,3,2,1],省略起始索引、终止索引,步长值为-1,表示反向获取
>>>
[2, 3, 4, 5, 6, 7]
[1, 2, 3]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7]
[7, 6, 5, 4, 3, 2, 1]