class Solution():
def twoSum(self, nums, target):
# nums: list->int
# target: 两数之和
# 遍历数组每一个元素
for i in nums:
# 计算另一个数
j = target - i
# 记录下开始索引
start_index = nums.index(i)
# 将i后面的数存放在一个临时list,防止出现6 = 3+3
temp = nums[start_index + 1:]
# 判断另一个数是否在该数组中
if j in temp:
# 输出
return (start_index , start_index + 1 + temp.index(j))
优化
class Solution():
def TwoSum(self, nums, target):
# 存储形式为{values:index, ...,}
dict = {
}
for i in range(len(nums)):
if (target - nums[i]) not in dict:
dict[nums[i]] = i
else:
return [dict[target - nums[i]], i]
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# 判断l1或者l2是否存在
if l1 == None:
return l2
if l2 == None:
return l1
dummy = ListNode(0)
p = dummy
carry = 0
# 若l1 和 l2存在,进行计算
while l1 and l2:
# 当前位相加后的值,carry为进位
p.next = ListNode((l1.val + l2.val + carry ) % 10)
carry = (l1.val + l2.val + carry) // 10
# 改变指针指向下一个节点
l1 = l1.next
l2 = l2.next
p = p.next
# 若l1 长度 < l2长度,相加完后,l2还有多余数据,进行相加
if l2:
while l2:
p.next = ListNode((l2.val + carry) % 10)
carry = (l2.val + carry) // 10
l2 = l2.next
p = p.next
# 若l1 长度 > l2
if l1:
while l1:
p.next = ListNode((l1.val + carry) % 10)
carry = (l1.val + carry) // 10
l1 = l1.next
p = p.next
# 若最后carry仍为1
if carry == 1:
p.next = ListNode(1)
return dummy.next
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 本质{'char1':index1, 'char2':index2...}
# 求上一个重复点到下一个重复点最大差值
start = -1
max = 0
dict = {
}
for i in range(len(s)):
if s[i] in dict and dict[s[i]] > start:
start = dict[s[i]]
dict[s[i]] = i
else:
dict[s[i]] = i
if i - start > max:
max = i - start
return max
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
m = len(nums1)
n = len(nums2)
total = m + n
i = total // 2
j = total // 2 - int(total & 1 == 0)
return (self.findKtn(nums1, m, nums2, n, i + 1) + self.findKtn(nums1, m, nums2, n, j + 1)) / 2
def findKtn(self, nums1, m, nums2, n, k):
if m > n:
return self.findKtn(nums2, n, nums1, m, k)
if m == 0:
return nums2[k - 1]
if k == 1:
return min(nums1[0], nums2[0])
p1 = min(k // 2, m)
p2 = k - p1
if nums1[p1 - 1] < nums2[p2 - 1]:
return self.findKtn(nums1[p1:], m - p1, nums2, n, k - p1)
elif nums1[p1 - 1] > nums2[p2 - 1]:
return self.findKtn(nums1, m, nums2[p2:], n - p2, k - p2)
else:
return nums1[p1 - 1]
class Solution:
def longestPalindrome(self, s: str) -> str:
# 定义一个空字符串,存储找到的回文子串
palindrome = ''
# 遍历字符串中每一个字符
for i in range(len(s)):
# 获取回文子串的长度,以最中间单个字母为中心
len1 = len(self.getLongestPalindrome(s, i, i))
# len1不为空或者大于已找到回文子串长度,说明找到了新的回文子串
if len1 > len(palindrome):
palindrome = self.getLongestPalindrome(s, i, i)
# 获取回文子串长度,以最中间两个字母为中心
len2 = len(self.getLongestPalindrome(s, i, i+1))
if len2 > len(palindrome):
palindrome = self.getLongestPalindrome(s, i, i+1)
return palindrome
# 判断是否为需要的回文子串
def getLongestPalindrome(self, s, l, r):
# s: 要判断的字符串
# l: 该字符串最左侧字符
# r: 该字符串最右侧字符
# s[l] == s[r] 为一个回文子串
while l >= 0 and r < len(s) and s[l] == s[r]:
# 向左边右边扩充字符,判断是否依旧满足条件
l -= 1
r += 1
# 返回找到的回文子串
return s[l+1 : r]
class Solution:
def convert(self, s: str, numRows: int) -> str:
# s = "PAYPALISHIRING", numRows = 3
# iter :1, 'P', row[0]
# +1
# iter :2, 'A', row[1]
# +1
# iter :3, 'Y', row[2]
# +1
# iter :4, 'P', row[1]
# -1
# iter :5, 'A', row[0]
# -1
# iter :6, 'L', row[1]
# +1
# iter :7, 'I', row[2]
# +1
# ...
# 规律
# 当row == 0: step = 1
# 当row == numRows - 1, step = -1
# row += step
# 判断str长度是否不满足zigzag形式
if len(s) < numRows or numRows == 1:
return s
# 初始化行索引和步长
row, step = 0, 1
# 初始化存储结果列表
zigzag = ['' for x in range(numRows)]
# 遍历并按规则进行存储每个字符
for char_ in s:
zigzag[row] += char_
# 存储一个字符后,对行索引进行更新
if row == 0:
step = 1
elif row == numRows - 1:
step = -1
row += step
# 返回拼接字符串
return ''.join(zigzag)
class Solution:
def reverse(self, x: int) -> int:
# 有符号整数范围:-2147483648~2147483647
# 定义一个初始变量,用于存储取出来的每一位整数
num = 0
# 获取输入整数的绝对值
x_ = abs(x)
while(x_ != 0):
# 从最后一位开始取值
temp = x_ % 10
# 每取一个值,需要向前移一个位,因此:
num = num * 10 + temp
# 更新已移除个位的原整数
x_ = int(x_ / 10)
# 判断整数是否越界及原本符号
if x >= 0 and num < 2147483647:
return num
elif x < 0 and num <= 2147483648:
return -num
else:
return 0
class Solution:
def myAtoi(self, s: str) -> int:
# 对输入字符串进行去空
stripS = s.strip()
# 判断是否为'-','+',''等单个字符
if stripS == '-' or stripS == '' or stripS == '+':
return 0
# 在去除左侧符号后,判断是否存在除了数字以外的内容
# re.match() 从头开始匹配到结束
s1 = re.match('[^\d]+', (stripS.lstrip('-')).lstrip('+'))
if s1 != None:
return 0
else:
# 提取包含符号在内的数字部分
# re.search()匹配到满足规则为止
# group()提取匹配到的结果
s1 = re.search(r'[-|+]*\d+', stripS).group()
# 若前两位为'--','++','-+'
if s1[0:2] == '--' or s1[0:2] == '++' or s1[0:2] == '-+':
return 0
# 去掉符号
res = int(s1)
# 判断是否越界
if res > 0:
return 2147483647 if res > 2147483647 else res
else:
return -2147483648 if res < -2147483648 else res
class Solution:
def isPalindrome(self, x: int) -> bool:
# 定义一个变量用于存储反转后的数字
num = 0
# 对原整数取绝对值
x_ = abs(x)
# 依次按位进行反转
while(x_ != 0):
# 一个临时变量存储每次需要反转的位置上的数
temp = x_ % 10
# 将该值放在相应位置
num = num * 10 + temp
# 去除已反转位置上的数
# x_ = int(x_ / 10)
x_ = x_ // 10
# 判断是否为回文数
if x >= 0 and x == num:
return True
else:
return False
class Solution:
def isMatch(self, s: str, p: str) -> bool:
cache = [[False] * (len(s) + 1) for _ in range(len(p) + 1)]
cache[0][0] = True
for i in range(1, len(p)):
cache[i + 1][0] = cache[i - 1][0] and p[i] == '*'
for i in range(len(p)):
for j in range(len(s)):
if p[i] == '*':
cache[i + 1][j + 1] = cache[i][j + 1] or cache[i - 1][j + 1]
if p[i - 1] == s[j] or p[i - 1] == '.':
cache[i + 1][j + 1] |= cache[i + 1][j]
else:
cache[i + 1][j + 1] = cache[i][j] and (p[i] == s[j] or p[i] == '.')
return cache[-1][-1]
class Solution(object):
def maxArea(self, height: List[int]) -> int:
# 初始化左右指针,表示当前位置
left = 0
right = len(height) - 1
# 初始化面积
res = 0
# 左右移动,并计算面积,直到左右指针相遇
# 若使用!= : left = 3, right = 2 这样是不合逻辑的
while (left < right):
# 面积 = 当前左右位置高度的最小值 * 左右指针的距离
area = min(height[left], height[right]) * (right - left)
# 当前面积如果大于上一次面积,则进行赋值
if area > res:
res = area
# 判断下一次该左移还是右移,原则尽可能保留较大的高度(保证面积最大),高度较低的位置进行移动
if height[left] < height[right]:
left += 1
else:
right -= 1
return res
class Solution:
def intToRoman(self, num: int) -> str:
# values = [100, 900, 500, 400..]
# numerals = ['M', 'CM', 'D', 'CD', ..]
# input = 1994
# 1994 > 1000 ? => M
# 994 > 900 ? => MCM
# 94> 90 ? => MCMXC
# 4 > 5 ? => MCMXCIV
values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
numerals = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I' ]
# 取values中的值 与输入num 依次判断位于哪个区间,并拼接numerals中的值
result = ''
for i in range(0, len(values)):
while num >= values[i]:
result += numerals[i]
# 拼接完成后,对num进行更新,减去最高位,降低一位再次进行比较
num -= values[i]
return result
class Solution:
def romanToInt(self, s: str) -> int:
# 判断两个相邻字母,左边的字母必小于右边字母代表的数字,则认为他们是一对组合,值为后面字母值-前面字母的值
# 定义一个字符和数值对照的字典
numeral_map = {
'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
# 初始化最终结果
result = 0
# 遍历字符串的每个字母
for i in range(len(s)):
# 识别出的每个字母对应的数字进行相加,即为最后的结果
# 但是 若前一个字母小于后一个字母,则认为他们是一组,需要进行相减
# 识别出的第一个和第二个字母 :result = M + C
# 当为第二和第三个字母时,由于CM C
# 前三个字母最终的结果:result += M - C
# 即 result = M + C + M - C = M + M
# 而 expected_res = M + (M - C)
# 因此 temp = M - 2C => result = M + M - C
if i > 0 and numeral_map[s[i]] > numeral_map[s[i - 1]]:
result += numeral_map[s[i]] - 2 * numeral_map[s[i - 1]]
else:
result += numeral_map[s[i]]
return result
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
# 首先判断是否是一个str
if not strs:
return ''
# 以list中第一个str为基准(公共前缀最大只会等于某一个单词长度,因此以第一个为基准即可))
for i in range(len(strs[0])):
# 从第二个单词开始 每个字符进行比较
for string in strs[1:]:
# 若当前单词长度超过与之比较的单词长度
# 或者没有找到公共前缀时
# 若strs = ["flower","flow","flight"]
# strs[0] => flower string[0][0] =>f
# string => flow string[0] => f
if i >= len(string) or string[i] != strs[0][i]:
# strs[0][:i] 截取开始到索引i位置的字母,但不包括i
return strs[0][:i]
# 若该字符为空即'',其本身也为str,直接返回该值本身即可
return strs[0]
或者
def longestCommonPrefix(self, strs: List[str]) -> str:
# 保存最后结果变量
result = ''
i = 0
while True:
try:
# 采用集合类型(该变量类型会自动去重并保留唯一一个不重复的变量)
# 遍历每个单词的每个字母,并使用set去重
sets = set(string[i] for string in strs)
# 若每次返回长度为1,则表示该位置为公共前缀
# 若strs = ["flower","flow","flight"]
# i = 0,sets = {'f'} len = 1
# i = 1, sets = {'l'} len = 1
# i = 2, sets = {'o','i'} len = 2
if len(sets) == 1:
# 索引+1遍历下一个字母
i += 1
# 拼接结果,需要用pop()进行取值
result += sets.pop()
else:
# 长度不为1 ,则表明当前位置的字符并非公共前缀的部分
break
except Exception as e:
break
return result
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 获取list 长度
n = len(nums)
# 初始化存储结果list
result = []
# 对list 进行排序
# sorted() 函数->sorted(list) 返回新list,原list无变化
# sort() list方法-> 直接原list修改
nums.sort()
# 由于要求为三数之和等于0
for i in range(n-2):
# list以从小到大方式排列,若前三数相加仍大于0,那这个list不会组合为三数为0的情况(最小三数都大于0,更大的数必然为正)
if nums[i] + nums[i+1] + nums[i+2] > 0:
break
# 若最小数和最大的两个数相加仍为负,那有可能存在等于0的情况
if nums[i] + nums[n-2] + nums[n-1] < 0:
continue
# 不包含重复的三元组
if i > 0 and nums[i] == nums[i-1]:
continue
# 初始化左右指针,加快查找速度
l, r = i + 1, n - 1
while l < r:
tmp = nums[i] + nums[l] + nums[r]
if tmp == 0:
# 满足条件存储结果
result.append([nums[i], nums[l], nums[r]])
while l+1 < r and nums[l] == nums[l+1]:
# 若遇到相等的值,则继续向右边查找
l += 1
# 更新外部l的值
l += 1
while r - 1 > l and nums[r] == [r-1]:
r -=1
r -= 1
elif tmp < 0:
# tmp<0说明左边值过小,右移
l += 1
else:
# 说明右边值过大,左移
r -= 1
return result
class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
# 对list进行排序
nums = sorted(nums)
# 初始化一个result
result = nums[0] + nums[1] + nums[len(nums) - 1]
# 遍历list中每个数,组合为三数之和
for i in range(len(nums) - 2):
# 当找到第二个及以后值时,判断当前找到的值是否和前一个相等
if i > 0 and nums[i] == nums[i - 1]:
continue
# 初始化左右指针
l = i + 1
r = len(nums) - 1
while l < r:
# 计算当前val
val = nums[l] + nums[i] + nums[r]
# 判断当前值是否小于初始值,若是,则进行重新赋值
if abs(val - target) < abs(result - target):
result = val
# 若差值刚好与目标值target相等,说明找到了
if val == target:
return target
# 若差值小于目标值,说明左边值过小,左移
elif val < target:
l += 1
# 若差值过大,说明右边值过大,右移
else:
r -= 1
return result
class Solution:
def letterCombinations(self, digits: str) -> List[str]:
# 判断输入digits是否为空
if len(digits) == 0:
return []
# 定义一个数字与字母对应的dict
digits_map = {
0:'0',
1:'1',
2:'abc',
3:'def',
4:'ghi',
5:'jkl',
6:'mno',
7:'pqrs',
8:'tuv',
9:'wxyz'
}
result = ['']
# 遍历每个输入数字,并取出dict中对应字母
for digit in digits:
# 定义一个list存放每次查找的结果
tmp_list = []
# 根据每个key查找每个对应字母的value,digit ->str
for ch in digits_map[int(digit)]:
# 将先前找到的字母与接下来找到的字母进行组合
for str in result:
tmp_list.append(str + ch)
result = tmp_list
return result
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
# 判断list 是否不足4个元素
if len(nums) < 4:
return []
# 对list 进行排序
nums.sort()
# 结果采用hash(自动去重)
ans = set()
# 遍历元素
for i in range(len(nums) - 3):
for j in range(i + 1, len(nums) - 2):
# 记录下当前两个值的和
now = nums[i] + nums[j]
# 定义左右指针
l = j + 1
r = len(nums) - 1
while l < r:
# 判断是否满足条件
if nums[l] + now + nums[r] == target:
# 判断是否是重复元素
if (nums[i], nums[j], nums[l], nums[r]) not in ans:
# set()使用add()添加元素
ans.add((nums[i], nums[j], nums[l], nums[r]))
if nums[l] + now + nums[r] > target:
r -= 1
else:
l += 1
# 最终结果转换为list
return list(ans)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
dummy = ListNode(0)
# 定义头结点
dummy.next = head
# 定义快慢指针
slow = fast = dummy
# 先让快指针移动n步
for _ in range(n):
fast = fast.next
# 此时移动慢指针
while fast.next:
slow = slow.next
fast = fast.next
# 移除要移除的节点
slow.next = slow.next.next
# 返回头结点
return dummy.next
class Solution:
def isValid(self, s: str) -> bool:
# 定义一个list存储每个字符
stack = []
# 定义每个括号对应的dict
lookup = {
'(':')', '[':']', '{':'}'}
# 遍历每个字符
for ch in s:
if ch in lookup:
stack.append(ch)
elif len(stack) == 0 or lookup[stack.pop()] != ch:
return False
return len(stack) == 0
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
curr = dummy = ListNode(0)
while l1 and l2:
# 判断 将值按从小到大进行插入
if l1.val < l2.val:
curr.next = l1
l1 = l1.next
else:
curr.next = l2
l2 = l2.next
curr = curr.next
curr.next = l1 or l2
return dummy.next
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
# 输入为空,直接返回
if n == 0:
return []
result = []
self.helper(n, n, '', result)
return result
def helper(self, l, r, item, result):
# 括号数量不匹配
if r < l:
return
# 将左右边遍历完的括号添加入结果
if l == 0 and r == 0:
result.append(item)
# 查找(
if l > 0:
self.helper(l-1, r, item + '(', result)
if r > 0:
self.helper(l, r-1, item + ')', result)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class MyListNode():
def __init__(self, l:ListNode):
self.l = l
def __eq__(self, other):
return self.l.val == other.l.val
def __lt__(self, other):
return self.l.val < other.l.val
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
dummy = ListNode(0)
curr = dummy
heap = [MyListNode(i) for i in lists if i]
heapq.heapify(heap)
while heap:
i = heapq.heappop(heap).l
curr.next = ListNode(i.val)
curr = curr.next
if i.next:
heapq.heappush(heap, MyListNode(i.next))
return dummy.next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
# 判断是否不存在节点或者只有一个节点
if not head or not head.next:
return head
p = head
new_start = p.next
while(True):
# 两两交换
q = p.next
temp = q.next
q.next = p
# 判断是否存在下两个节点
if not temp or not temp.next:
p.next = temp
break
p.next = temp.next
p = temp
return new_start
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
dumb = ListNode(10086)
dumb.next = head
end = prev = dumb
def swap(prev, k, end):
after = end.next
move = prev.next
prev.next = end
temp = move.next
end = move
for i in range(k - 1):
tnext = temp.next
temp.next = move
move = temp
temp = tnext
end.next = after
return end
while True:
try:
for _ in range(k):
end = end.next
prev = end = swap(prev, k, end)
except:
break
return dumb.next
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
# 判断list是否为空
if not nums:
return 0
# 初始化一个计数变量
count = 0
# 遍历元素
for i in range(len(nums)):
# 若元素不相等,count +1
# 本质将不重复元素都移至list前面
if nums[count] != nums[i]:
count += 1
# 同时更新基准值
nums[count] = nums[i]
# 返回长度
return count + 1
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
# 初始化左右指针
start, end = 0, len(nums) - 1
# 进行比较,若左右指针的某元素等于val,将该元素交换到尾部,进行删除
while start <= end:
if nums[start] == val:
nums[start], nums[end] = nums[end], nums[start]
# 删除最后一个元素(在这里并不是真的删除,end指针-1)
end -= 1
else:
# 若start指针元素与最后一个元素不等,则继续查找下一个
start += 1
return end + 1
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
# 遍历haystack
for i in range(len(haystack) - len(needle) + 1):
# 判断是否相等,每次移动needle长度
if haystack[i : i + len(needle)] == needle:
return i
return -1
位运算
class Solution:
def divide(self, dividend: int, divisor: int) -> int:
# 二进制运算,从右至左,每一位的数*2的[0,(n-1)]次方
# 二进制左移:右边补0-->左移后比原来数大2倍
# 位运算
flag = -1 if (dividend > 0 and divisor < 0) or ((dividend < 0 and divisor > 0)) else 1
dividend, divisor = abs(dividend), abs(divisor)
q, times = 0, 0
while dividend >= divisor:
cur = dividend - (divisor << times)
if cur >= 0:
q += (1 << times)
times += 1
dividend = cur
else:
times -= 1
return max(-2 ** 31, min(q * flag, 2 ** 31-1))
class Solution:
def findSubstring(self, s: str, words: List[str]) -> List[int]:
if len(words) == 0: return []
unilen = len(words[0])
res, sets = [], {
}
for word in words:
sets[word] = sets.setdefault(word, 0) + 1
for i in range(unilen):
count, start, match_set = len(words), i, {
}
for j in range(i, len(s), unilen):
substr = s[j : j+unilen]
if substr in sets:
match_set[substr] = match_set.setdefault(substr, 0) + 1
count -= 1
while (match_set[substr] > sets[substr]):
remove = s[start : start + unilen]
start += unilen
match_set[remove] -= 1
count += 1
if count == 0:
res.append(start)
else:
count, start, match_set = len(words), j + unilen, {
}
return res
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
if sorted(nums, reverse = True) == nums:
nums[:] = nums[::-1]
return
for i in range(len(nums) - 1)[::-1]:
if nums[i] < nums[i + 1]:
break
for j in range(i + 1, len(nums)):
if j == len(nums) - 1 or nums[j + 1] <= nums[i]:
nums[i], nums[j] = nums[j], nums[i]
break
nums[i + 1:] = nums[i + 1:][::-1]
return
class Solution:
def longestValidParentheses(self, s: str) -> int:
res = 0
stack = [-1]
for i, c in enumerate(s):
if c == '(':
stack.append(i)
elif len(stack) == 1:
stack.pop()
stack.append(i)
else:
stack.pop()
res = max(res, i - stack[-1])
return res
class Solution:
def search(self, nums: List[int], target: int) -> int:
# 采用二分查找的思想
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
return mid
if target >= nums[0]:
if nums[mid] >= nums[0] and target > nums[mid]:
left = mid + 1
else:
right = mid - 1
else:
if nums[mid] >= nums[0] or target > nums[mid]:
left = mid + 1
else:
right = mid - 1
return -1
bisect模块
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
from bisect import bisect_left, bisect_right
if len(nums) == 0: return [-1, -1]
res = [-1, -1]
left = bisect_left(nums, target)
if left < len(nums) and nums[left] == target:
res[0] = left
res[1] = bisect_right(nums, target) - 1
return res
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
try:
return [nums.index(target), len(nums) - (list(nums[::-1]).index(target))-1]
except:
return [-1, -1]
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
# 若target大于list中所有数,则它被插入到最后,索引为list长度
if target > nums[-1]:
return len(nums)
# 遍历所有元素
for i in range(len(nums)):
# 按顺序插入target,并返回其索引
if nums[i] >= target:
return i
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
return self.is_row_valid(board) and self.is_col_valid(board) and self.is_sqare_valid(board)
# 数字 1-9 在每一行只能出现一次
def is_row_valid(self, board):
for row in board:
if not self.is_unit_valid(row):
return False
return True
# 数字 1-9 在每一列只能出现一次
def is_col_valid(self, board):
print(board) # [['5', '3', '.', '.', '7', '.', '.', '.', '.'], ['6', '.', '.', '1', '9', '5', '.', '.', '.'], ...]
for col in zip(*board):
print(col) # ('5', '6', '.', '8', '4', '7', '.', '.', '.')
if not self.is_unit_valid(col):
return False
return True
# 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次
def is_sqare_valid(self, board):
# 以[0,0] = 5 为例,按行 下一个粗线区域为[0,3],下下个为[0,6]
for i in (0, 3, 6):
# 同理,每列对应相对位置
for j in (0, 3, 6):
sqare = [board[x][y] for x in range(i, i + 3) for y in range(j, j + 3)]
if not self.is_unit_valid(sqare):
return False
return True
# 数独部分空格内已填入了数字,空白格用 '.' 表示。
def is_unit_valid(self, unit):
unit = [i for i in unit if i != '.']
return len(set(unit)) == len(unit)
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
r3, r9, s9 = range(3), range(9), set(str(x) for x in range(1, 10))
def dfs():
for i, row in enumerate(board):
for j, char in enumerate(row):
if char != '.': continue
for x in s9-{
row[k] for k in r9} - {
board[k][j] for k in r9} - {
board[i//3*3+m][j//3*3+n] for m in r3 for n in r3}:
board[i][j] = x
if dfs(): return True
board[i][j] = '.'
return False
return True
dfs()
class Solution:
def countAndSay(self, n: int) -> str:
# 定义起始字符
seq = '1'
# 计算每一行的输出值
for i in range(n-1):
seq = self.getNext(seq)
return seq
def getNext(self, seq):
i, next_seq = 0, ''
while i < len(seq):
count = 1
while i < len(seq) - 1 and seq[i] == seq[i + 1]:
count += 1
i += 1
next_seq += str(count) + seq[i]
i += 1
return next_seq
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
result = []
candidates.sort()
self._combinationSum(candidates, target, 0, [], result)
return result
def _combinationSum(self, nums, target, index, path, res):
if target < 0:
return
if target == 0:
res.append(path)
return
for i in range(index, len(nums)):
self._combinationSum(nums, target - nums[i], i, path + [nums[i]], res)
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
if not candidates:
return []
def dfs(start_index, candidates, target, path, res):
if target == 0:
res.append(copy.deepcopy(path))
return
for i in range(start_index, len(candidates)):
if candidates[i] <= target:
if i > start_index and candidates[i] == candidates[i - 1]:
continue
path.append(candidates[i])
dfs(i + 1, candidates, target - candidates[i], path, res)
path.pop()
candidates.sort()
path = []
res = []
start_index = 0
dfs(start_index, candidates, target, path, res)
return res
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
# 定义首尾元素
nums += [2 ** 31] * 2
# 去除小于0或者大于length的元素
for i in range(len(nums)):
if nums[i] < 0 or nums[i] >= len(nums):
nums[i] = 0
# 将所有元素标记为负数,0标记为-cur
for i in range(len(nums)):
cur = abs(nums[i])
if nums[cur] == 0:
nums[cur] = -cur
else:
nums[cur] = -1 * abs(nums[cur])
# 返回结果
for i in range(1, len(nums)):
if nums[i] >= 0:
return i
class Solution:
def trap(self, height: List[int]) -> int:
if len(height) == 0 or max(height) == 0: return 0
self.res = 0
max_ = max(height)
index = height.index(max_)
self.area(height[:index])
self.area(height[index + 1:][::-1])
return self.res
def area(self, h):
if len(h) == 0 or max(h) == 0: return
maxh = max(h)
index = h.index(maxh)
self.res += ((len(h) - index - 1) * maxh - sum(h[index + 1:]))
self.area(h[:index])
class Solution:
def multiply(self, num1: str, num2: str) -> str:
if num1 == '0' or num2 == '0':
return '0'
if len(num1) < len(num2):
num1, num2 = num2, num1
num1 = num1[::-1]
num2 = num2[::-1]
add_list = []
for i in range(len(num2)):
for j in range(len(num1)):
newnum2_i = int(num2[i] + '0' * i)
newnum1_j = int(num1[j] + '0' * j)
add_list.append(newnum1_j * newnum2_i)
return str(sum(add_list))
class Solution:
def isMatch(self, s: str, p: str) -> bool:
# 初始化匹配索引
cache = [-1, -1]
p_ptr, s_ptr = 0, 0
while s_ptr < len(s):
if p_ptr < len(p) and p[p_ptr] in (s[s_ptr], '*', '?'):
if p[p_ptr] =='*':
cache[0], cache[1] = p_ptr, s_ptr
else:
s_ptr += 1
p_ptr += 1
elif cache[0] != -1:
p_ptr, s_ptr = cache[0] + 1, cache[1] + 1
cache[1] += 1
else:
return False
while p_ptr < len(p) and p[p_ptr] =='*':
p_ptr += 1
return (p_ptr == len(p))
class Solution:
def jump(self, nums: List[int]) -> int:
if len(nums) == 0:
return 0
step = 0
left = 0
right = 0
for i in range(len(nums) - 1):
right = max(right, i + nums[i])
if i == left:
step += 1
left = right
return step
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
# 判断list本身是否唯一元素
if len(nums) <= 1:
return [nums]
ans = []
for i, num in enumerate(nums):
n = nums[:i] + nums[i+1:]
# print(i,n)
# 0 [2, 3]
# 0 [3]
# 1 [2]
# 1 [1, 3]
# 0 [3]
# 1 [1]
# 2 [1, 2]
# 0 [2]
# 1 [1]
for y in self.permute(n):
ans.append([num] + y)
return ans
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
if len(nums) == 0: return [[]]
res = [[]]
for n in nums:
temp = []
for r in res:
for i in range(len(r) + 1):
temp.append(r[:i] + [n] + r[i:])
if i < len(r) and r[i] == n:
break
res = temp
return res
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
h = len(matrix)
n = h - 1
for i in range(h // 2):
for j in range(i, n - i):
tmp = matrix[i][j]
matrix[i][j] = matrix[n-j][i]
matrix[n-j][i] = matrix[n-i][n-j]
matrix[n-i][n-j] = matrix[j][n-i]
matrix[j][n-i] = tmp
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
# 利用dict进行存储每一个类别
solution = {
}
# 多创建一个列表是由于leetcode提交原因
res = []
# 判断是否为一个元素
if len(strs) < 1:
return strs
else:
# 遍历list中每个char
for i in range(len(strs)):
reg = strs[i]
# 对每个char的所有字母进行排序后拼接 判断其是否为一个组
regsort = ''.join(sorted(reg))
# 判断dict中是否存在该组,存在直接存储,不存在创建组
if regsort in solution:
solution[regsort].append(reg)
else:
solution[regsort] = [reg]
# return solution.values()
for val in solution.values():
res.append(val)
return res
class Solution:
# 方式1
# def myPow(self, x: float, n: int) -> float:
# return x ** n
def myPow(self, x: float, n: int) -> float:
# 2**10
# 10-> 二进制:1010:2^3 + 2^1
# 即 2**10:2^8 * 2^2
if n < 0:
return 1/self.myPow(x, -n)
res = 1
track = x
while n>0:
# 判断n的最右侧是否为1
if n&1:
res *= track
track *= track
# 二进制右移一位
n >>= 1
return res