个人感觉系列-_-||
顺时针打印矩阵(头条)
# -*- coding:utf-8 -*-
import numpy as np
class Solution:
# matrix类型为二维列表,需要返回列表
def printMatrix(self, matrix):
# write code here
res = []
if not matrix: return res
n = len(matrix) # n行
m = len(matrix[0]) # m列
# visted = # 记录是否被访问过
# for i in range(m):
# aa.append(False)
# print(aa)
# for j in range(n):
# visted.append(aa) # 这种初始化方式就是错的
visted = [[False for _ in range(m)] for _ in range(n)]
# print(visted)
x,y = 0,0 # 第一个点
d = 1 # 初始方向是向右
dx = [-1,0,1,0]
dy = [0,1,0,-1]
for i in range(n*m):
res.append(matrix[x][y])
visted[x][y] = True
a = x + dx[d]
b = y + dy[d]
if a<0 or a>=n or b<0 or b>=m or visted[a][b]:
# 撞墙啦! 就换方向
d = (d+1)%4
a = x + dx[d]
b = y + dy[d]
x, y = a, b
return res
if __name__ == '__main__':
matrix = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]]
print(Solution().printMatrix(matrix))
矩阵中的路径
# -*- coding:utf-8 -*-
# leetcode79:单词搜索
# newcoder上就是不通过
class Solution:
def hasPath(self, matrix, rows, cols, path):
# write code here
visited = [[False for _ in range(len(matrix[0]))] for _ in range(len(matrix))]
for i in range(rows):
# print()
for j in range(cols):
if self.dfs(matrix,path,i,j,0,visited):
# print("bbb")
return True
return False
def dfs(self,matrix,path,a,b,u,visited):
# print("path",len(path))
# print("u",u)
# print("m:",matrix[a][b])
# print("path",path[u])
# print(matrix[a][b] == path[u])
if matrix[a][b] != path[u]: return False
if len(path) == u+1:return True
dx = [-1,0,1,0]
dy = [0,1,0,-1]
for i in range(4):
visited[a][b] = True
x = a+dx[i]
y = b+dy[i]
if x>=0 and x<len(matrix) and y>=0 and y<len(matrix[0]) and not visited[x][y]:
# print("yes")
if self.dfs(matrix,path,x,y,u+1,visited):return True
# print("q")
visited[a][b] = False
# print("a")
return False
if __name__ == '__main__':
matrix = [["a","b","c","e"],
['s','f','c','s'],
['a','d','e','e']]
matrix = [["a"]]
matrix = [["A",'B','C',"E"],
["S",'F','C',"S"],
["A",'D','E',"E"]]
# print(matrix[2][3])
# matrix[2][3] = "@"
# print(matrix)
# lucky = "abc"
# lucky[1]="!"
# print(lucky)
# lucky[1]="!"
# TypeError: 'str' object does not support item assignment
row = 1
col = 1
row=3
col=4
path = "bcced"
path = "abcb"
path = "b"
path = "ABCCED"
print(Solution().hasPath(matrix,row,col,path))
机器人的运动范围
# -*- coding:utf-8 -*-
# 宽度优先遍历
class Solution:
def movingCount(self, threshold, rows, cols):
# write code here
cnt = 0
if not rows or not cols:return cnt
visited = [[False for _ in range(cols)] for _ in range(rows)]
# print(visited)
queue = []
queue.append([0,0]) # 从起点开始
dx = [-1,0,1,0]
dy = [0,1,0,-1]
while queue:
tmp = queue[0]
# print(tmp)
queue.pop(0)
if self.get_sum(tmp)>threshold or visited[tmp[0]][tmp[1]]:continue
cnt += 1
visited[tmp[0]][tmp[1]] = True
for i in range(4):
x = tmp[0]+dx[i]
y = tmp[1]+dy[i]
if x>=0 and x<rows and y>=0 and y<cols:
queue.append([x,y])
return cnt
def get_single_sum(self,x):
s = 0
while x:
s += x%10
x //= 10
return s
def get_sum(self,pair):
return self.get_single_sum(pair[0])+ \
self.get_single_sum(pair[1])
if __name__ == '__main__':
threshold = 7
rows = 4
cols = 5
# print(Solution().get_single_sum(12))
print(Solution().movingCount(threshold,rows,cols))
构建乘积数组
class Solution:
def multiply(self, A):
B = []
if not A:return B
n = len(A)
p = 1
for i in range(n):
B.append(p)
p *= A[i]
# print(i,A[i])
# print(B) # [1, 1, 2, 6, 24]
p = 1
for i in range(n-1,-1,-1):
print("B", B[i])
B[i] *= p
p *= A[i]
return B
字符串的全排列
# -*- coding:utf-8 -*-
class Solution:
def Permutation(self, ss):
# write code here
if len(ss) <= 0:
return []
res = list()
self.perm(ss, res, '')
uniq = list(set(res))
return sorted(uniq)
# 从子串中挑一个字符,插入新的字符
def perm(self, ss, res, path):
if ss == '':
res.append(path)
else:
for i in range(len(ss)):
self.perm(ss[:i]+ss[i+1:], res, path+ss[i])
逆序数
class Solution:
def InversePairs(self, data):
# 采用归并排序的思想,时间复杂度为O(nlogn)
global count
count = 0
def merge(array):
global count
if len(array) <= 1:
return array
k = len(array)//2
left = merge(array[:k])
right = merge(array[k:])
l = 0
r = 0
result = []
while l<len(left) and r<len(right):
if left[l]<=right[r]:
result.append(left[l])
l+=1
else:
result.append(right[r])
r += 1
count += len(left)+1
result += left[l:]
result += right[r:]
return result
merge(data)
return count%1000000007
if __name__ == '__main__':
data = [1,2,3,4,5,6,7,0]
print(Solution().InversePairs(data))
滑动窗口最大值
from collections import deque
# 主要思想是:
# 每次比末尾元素大的才可以入队列
class Solution:
def maxInWindows(self, num, size):
# write code here
res = []
if not size or not num: return res
# 可在两端进行插入和删除
q = deque()
# 队列存在的是下标,不是数值
for i in range(len(num)):
# 如果超出滑动窗口,那么把队首元素踢掉,双端队列是不排序的
while q and q[0] <= i-size:
q.popleft()
# 优胜劣汰,弱的出去,强的进来
# 如果当前元素大于队尾元素,入队
while q and num[i] >= num[q[-1]]:
q.pop()
q.append(i)
# 返回结果
if i >= size-1:
res.append(num[q[0]])
return res
two sum系列
两数之和(hashtable)
# 要求时间复杂度O(N)
# Python solution using hash
class Solution(object):
def twoSum(self, nums, target):
if len(nums) <= 1:
return False
buff_dict = {}
for i in range(len(nums)):
if nums[i] in buff_dict:
return [buff_dict[nums[i]], i]
else:
buff_dict[target - nums[i]] = i
和为S的两个数字
class Solution:
# 如果有多对数字的和等于S,输出两个数的乘积最小的
def FindNumbersWithSum(self, array, tsum):
hashmap = {}
rs = []
minval = 2**31
if not array:return rs
if len(array)<=1: return rs
for i in range(len(array)):
# 在hashmap中
if array[i] in hashmap:
if array[hashmap[array[i]]]*array[i]<minval:
minval = array[hashmap[array[i]]]*array[i]
rs.append([array[hashmap[array[i]]],array[i]])
# 不在hashmap中
else:
hashmap[tsum-array[i]] = i
print(rs)
if rs:return rs[-1]
return rs
和为S的连续正数序列
# 双指针
class Solution:
def FindContinuousSequence(self, tsum):
s,j = 1,1
res = []
for i in range(1,tsum+1):
while s<tsum:
j += 1
s += j
if s==tsum and j-i+1>1:
item = []
for k in range(i,j+1):
item.append(k)
res.append(item[:])
s -= i
return res
二分系列
不修改数组找出重复的数字
class Solution:
def findDuplicate(self, nums):
l = 1
r = len(nums)-1
while l<r:
mid = l+r>>1
sum = 0
for x in nums:
if x>=1 and x<=mid:sum+=1
if sum>mid:r=mid
else:l=mid+1
return r
if __name__ == '__main__':
nums = [1,3,4,2,2]
print(Solution().findDuplicate(nums))
旋转数组最小值
class Solution:
def findMin(self, nums: List[int]) -> int:
if not nums:return 0
l=0
r=len(nums)-1
while l<r:
mid = l+r>>1
if nums[mid]<=nums[-1]:r=mid
else:l=mid+1
return nums[r]
旋转数组找那个数字
0到n-1中缺失的数字
数字在排序数组中出现的次数
字符串相关
判断字符串是否表示数值
# -*- coding:utf-8 -*-
class Solution:
# E,e前后都要有东西
# 小数点只能出现一次
# +,-只能出现在s[0]或是e,E的后面
def isNumeric(self, s):
# write code here
s = s.replace(" ","")
if not s or (s[0]=='.' and len(s)==1):return False
if s.count('.')>1 or s.count('e')>1 or s.count('E')>1 \
or s.count('+')>2 or s.count('-')>2:return False
if s[0] in '+-':s=s[1:]
dot, e = 0, 0
i, n = 0, len(s)
while i < n:
if s[i]=='.' and e:
return False
elif s[i]=='e' or s[i]=='E':
e += 1
if i==0 or i == n-1:
return False
if s[i+1]=='+' or s[i+1]=='-':
if i+2==n:
# print(i+2)
# print(i, s[i])
return False
i += 1
elif s[i]!='.' and s[i] not in "0123456789":
return False
i += 1
return True
"""
定义两个标志位,分别表示E或者e是否出现过,以及小数点.是否出现过。
1. 以e(或E)为分隔,获得两个子字符串;e之前的字符串小数点只能出现一次;e之后的字符串不允许出现小数点;
2. 符号位+或-只可能出现在两个子字符串的首位;
3. e(或E)、小数点.不能出现在末尾
"""
if __name__ == '__main__':
# s = "-1E-16 "
s = " 1a3.14"
s = "123.45e+6"
print(Solution().isNumeric(s))
把字符串转成整数
# -*- coding:utf-8 -*-
class Solution:
def StrToInt(self, s):
if not s:return 0
k = 0
while k<len(s) and s[k]==' ':k+=1
num = 0
is_minus = False
if s[k] == '+': k += 1
elif s[k] == '-':
k += 1
is_minus = True
while k<len(s) and s[k]>='0' and s[k]<='9':
# num = num*10+(ord(s[k])-48)
num = num*10+(ord(s[k])-ord('0'))
k+=1
if k!=len(s):return 0
if is_minus:
num *= -1
return num
if __name__ == '__main__':
s = '1a33'
print(Solution().StrToInt(s))
动态规划
把数字翻译成字符串(leetcode91)
# 实际上有两个约束条件,1. 0不能单独解码 2. 两位数必须在1与26之间。
# 这道题目实际上是用DP去做,仔细想的话,可以发现就是约束版的f(n) = f(n-1) + f(n-2);
# 其中如果是s[n-1]为0,f(n-1) = 0,f(n) = f(n-2),
# 因为0无法单独解码,而f(n-2)的条件则是必须在1与26之间,否则f(n) = f(n-1)。
class Solution:
def numDecodings(self, s):
if s == "" or s[0]=='0': return 0
dp=[1,1]
for i in range(2,len(s)+1):
if 10 <=int(s[i-2:i]) <=26 and s[i-1]!='0':#编码方式为2
dp.append(dp[i-1]+dp[i-2])
elif int(s[i-2:i])==10 or int(s[i-2:i])==20:#编码方式为1
dp.append(dp[i-2])
elif s[i-1]!='0':#编码方式为0
dp.append(dp[i-1])
else:
return 0
#print(dp[len(s)])
return dp[len(s)]
if __name__ == "__main__":
s = "12"
print(Solution().numDecodings(s))
"""
s[i-2]和s[i-1] 两个字符是10----26之间但不包括10和20这两个数时,有两种编码方式,比如23------>[“BC”,“W”],所以dp[i] = dp[i-1]+dp[i-2]
s[i-2]和s[i-1] 两个字符10或20这两个数时,有一种编码方式,比如10------>[“J”], 所以dp[i] = dp[i-2]
s[i-2]和s[i-1] 两个字符不在上述两种范围时,编码方式为零,比如27,比如01,所以dp[i] = dp[i-1
"""
Python库的使用
把数组排成最小的数
# -*- coding:utf-8 -*-
import functools
# https://blog.csdn.net/u012436149/article/details/79952975
class Solution:
def helper(self,a,b):
# a<b一定有ab<ba
ab = int(a + b)
ba = int(b + a)
return 1 if ab > ba else -1
def PrintMinNumber(self, numbers):
numbers = [str(num) for num in numbers]
numbers = sorted(numbers,key=functools.cmp_to_key(self.helper))
print(numbers)
return "".join(numbers)
if __name__ == '__main__':
n = [32,3,321]
print(Solution().PrintMinNumber(n))
# 321323
看到别人考过的leetcode上的题目
leetcode5
# 马拉车算法——Manacher 算法
# 现将字符串通过添加特定字符'#',变成奇数个数。对新字符串使用中心扩展发即可,中心扩展法得到的半径就是子串的长度。
# 先转化字符串'35534321' ----> '#3#5#5#3#4#3#2#1#',然后求出以每个元素为中心的最长回文子串的长度。
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
# manacher 算法
s = '#' + '#'.join('{}'.format(s)) + '#'
lens=len(s)
max_str = ""
max_length = 0
for i in range(lens):
cur_length,cur_str = self.getLength(s,i)
if cur_length>max_length:
max_length = cur_length
max_str = cur_str
return max_str.replace('#','')
def getLength(self,s,index):
length = 0
string = s[index]
for i in range(1,index+1):
# 从index开始的原因是:从当前词开始向两边扩散
if i+index<len(s) and s[index-i]==s[index+i]:
length+=1
string = s[index-i:index+i]
else:
break
return length,string
无重复的最长子串
class Solution(object):
def lengthOfLongestSubstring(self, s):
hash_map = {}
left,res = 0,0
for i in range(len(s)): # i就是now,
# 如果当前字符从没出现过,或者是出现了,但不包含在当前窗口内:
if s[i] not in hash_map or left>hash_map[s[i]]:
res = max(res,i-left+1)
else:
left = hash_map[s[i]]+1
hash_map[s[i]] = i
# print(hash_map)
return res