以前也在博客里写过几个关于LeetCode里个人觉得有趣的题目,今天想想还是总结一下,这个博客以后会陆陆续续更新的,我还是简单说一下思路,贴一下代码,如果纯小白的话可能会看不懂。
我做过的题我会按照题目顺序添加进来的,我是按照题目顺序放的,看的时候也方便,下面正式开始。
1.两数之和
题目描述点这里
比较简单的题目,关键是要想到使用哈希映射来做,你甚至都不用把整个数组循环完就能出结果。
class Solution:
def twoSum(self, nums, target):
dic = {}
for i, num in enumerate(nums):
if num in dic:
return [dic[num], i]
else:
dic[target - num] = i
7.整数反转
题目描述
不断除十取余,然后反着加起来就行了
class Solution:
def reverse(self, x):
num=0
a = abs(x)
while(a != 0):
temp =a % 10
num =num*10 +temp
a = int(a/10)
if x>0 and num <2147483647:
return num
elif x<0 and num <=2147483647:
return -num
else:
return 0
9.回文数
class Solution:
def isPalindrome(self, x: int) -> bool:
if x < 0 or (x > 0 and x % 10 == 0):
return False
else:
tmp = 0
while x > tmp:
tmp = tmp * 10 + x % 10
x = x // 10
return tmp == x or tmp // 10 == x
20.有效的括号
题目描述
提示:使用栈,这个很快的,前括号进栈,遇到后括号匹配上就出栈否则就错了
class Solution:
def isValid(self, s):
long=len(s)
if long%2!=0:
return False
dic={"(":")","[":"]","{":"}"}
li=[]
for j in range(long):
if s[j] in dic.keys():
li.append(s[j])
else:
if not li:
return False
if dic[li[-1]]==s[j]:
li.pop()
elif dic[li[-1]]!=s[j]:
return False
return not li
21.合并两个有序链表
题目描述
两个链表都从头开始遍历,哪个数小就添加到新链表。
class Solution:
def mergeTwoLists(self, l1: 'ListNode', l2: 'ListNode') -> 'ListNode':
head = ListNode(0)
ret = head
while l1 != None and l2 != None:
if l1.val > l2.val:
head.next = l2
l2 = l2.next
else :
head.next = l1
l1 = l1.next
head = head.next
if l1 == None:
head.next = l2
elif l2 == None:
head.next = l1
return ret.next
35.插入的位置
题目描述
有些人先用 in 看一下是否在列表里,在的话返回的 target 的 .index,否则就插入然后 sort 在返回target的 .index,复杂度很高,但是运行时间可能比较短,内置函数的运行时间果然还是厉害,应该使用二分法来做,是比较好的思路
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
right = len(nums)
left = 0
mid = right // 2
while left < right:
if nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid
else:
return mid
mid = (right + left) // 2
return right
38.报数
题目描述
我觉得读懂这个题目就很难,读懂之后就简单了,233333·······
class Solution:
def countAndSay(self, n: int) -> str:
num = "1" #初始化num
def next_num(num):
"""
计算出下一个num
"""
pre_k, res, n = -1, "", len(num)
for k,v in enumerate(num):
if (k < n-1) and (v != num[k+1]):
res += str(k-pre_k) + num[k]
pre_k = k
elif k == n-1:
res += str(k-pre_k) + num[k]
return res
for i in range(1,n):
num = next_num(num)
return num
42.接雨水
题目描述点我
这个题是个困难题,我说两种方法,简单的和高端的。
普通方法:当然最简单的方法是暴力解题,对于数组中的每个元素,我们找出下雨后水能达到的最高位置,等于两边最大高度的较小值减去当前高度的值。这个可以试一下,但是时间复杂度是n的平方,太高了,就不说了,说一下下面的这个。
在暴力方法中,我们仅仅为了找到最大值每次都要向左和向右扫描一次。但是我们可以提前存储这个值。因此,可以通过动态编程解决。
官方有个图说明:
我感觉这个挺容易懂得,下面是代码:
class Solution:
def trap(self, height: List[int]) -> int:
lenth = len(height)
if not lenth:
return 0
ans = 0
left_nums = [0 for _ in range(lenth)]
left_nums[0] = height[0]
right_nums = [0 for _ in range(lenth)]
right_nums[-1] = height[-1]
for i in range(lenth):
left_nums[i] = left_nums[i-1] if left_nums[i-1] > height[i] else height[i]
for i in range(lenth-2,-1,-1):
right_nums[i] = right_nums[i+1] if right_nums[i+1] > height[i] else height[i]
for i in range(lenth):
left_nums[i] = min(left_nums[i],right_nums[i]) - height[i]
ans += left_nums[i]
return ans
使用栈数据结构做这个题目,刚开始看了几遍都没懂原理,自己试了一遍后明白了,但是要我讲给其他人够呛。别人是这么解释的:
我们可以不用像上面那样存储最大高度,而是用栈来跟踪可能储水的最长的条形块。使用栈就可以在一次遍历内完成计算。
我们在遍历数组时维护一个栈。如果当前的条形块小于或等于栈顶的条形块,我们将条形块的索引入栈,意思是当前的条形块被栈中的前一个条形块界定。如果我们发现一个条形块长于栈顶,我们可以确定栈顶的条形块被当前条形块和栈的前一个条形块界定,因此我们可以弹出栈顶元素并且累加答案到 ans 。
要是还不懂自己带个例子进去试一下,一步一步按照程序走,应该能有所收获。
class Solution:
def trap(self, height: List[int]) -> int:
my_stack = []
ans,cur = 0, 0
while cur < len(height):
while my_stack and height[cur] > height[my_stack[-1]]:
top = my_stack.pop()
if not my_stack:
break
distance = cur - my_stack[-1] - 1
bounded_height = min(height[cur],height[my_stack[-1]]) - height[top]
ans += distance * bounded_height
my_stack.append(cur)
cur += 1
return ans
155.最小栈
题目描述
这个用python来做太简单了,不得不说python的列表是万能的啊
class MinStack:
def __init__(self):
self.stack = [] #栈的全部数据
self.min_num = [] #返回当前最小数据
def push(self, x: int) -> None:
self.stack.append(x)
if not self.min_num or x <= self.min_num[-1]:
self.min_num.append(x)
def pop(self) -> None:
if self.stack.pop() == self.min_num[-1]:
self.min_num.pop()
def top(self) -> int:
return self.stack[-1]
def getMin(self) -> int:
return self.min_num[-1]
200.岛屿的数量
题目描述
使用栈或者队列都可以做出来这道题,先贴一下使用栈做这道题的代码,循环整个列表,遇到一(找到了陆地)就进栈,把这个数变为2,代表是已经检查过的陆地,然后开始检测其四周有没有1,只要有1也是同样的做法,进栈,标记为2,直到其四周都没有1为止,出栈,这样一趟下来能把一个1四周相连的1都标记一遍,也就是找到了一整块陆地,count加一。把整个数组都循环下来就能找到所有的陆地。
class Solution:
def numIslands(self, grid):
line = len(grid)
row = len(grid[0])
count = 0
dirs =[
lambda x,y:(x,y+1), #right
lambda x,y:(x+1,y), #down
lambda x,y:(x-1,y), #up
lambda x,y:(x,y-1), #left
]
stack = []
for i in range(line):
for j in range(row):
if grid[i][j] == "1":
stack.append((i,j)) #找到陆地,进栈
grid[i][j] = "2" #已找到的陆地变为2
while stack:
cur_pot = stack[-1]
for dir in dirs:
next_pot = dir(*cur_pot)
if 0 <= next_pot[0] <= line-1 and 0 <= next_pot[1] <= row-1: #越界检测
if grid[next_pot[0]][next_pot[1]] == "1":
stack.append(next_pot)
grid[next_pot[0]][next_pot[1]] = "2"
break
else:
#周围没有陆地了,出栈
stack.pop()
count += 1
return count
这个题使用队列也是能做的,使用栈的思想是深度优先,而队列就是广度优先了,使用队列解题的代码以后也贴出来,此博客一直在持续更新······