1.两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
试例
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
res = []
for i in range(len(nums)):
another_num = target - nums[i]
if another_num in nums[i+1:]:
res.append(i)
res.append(nums[i+1:].index(another_num)+i)
break
return res
def twoSum(nums, target):
lens = len(nums)
j=-1
for i in range(1,lens):
temp = nums[:i]
if (target - nums[i]) in temp:
j = temp.index(target - nums[i])
break
if j>=0:
return [j,i]
2.两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
两个列表同时遍历,逐位相加,保留进位 。carry保存的是进位。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
re = ListNode(0)
r = re
carry = 0
while l1 or l2:
x = l1.val if l1 else 0
y = l2.val if l2 else 0
sum = x + y + carry
carry = sum // 10
r.next = ListNode(sum % 10)
r = r.next
if l1 != None: l1 = l1.next
if l2 != None: l2 = l2.next
#当l1和l2都走到了最后,假如是5+5,那么还得需要一个ListNode(1)
if carry > 0:
r.next = ListNode(1)
return re.next
3、无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
index_dict记录了str[i]之前所有字符的位置
i-start+1表示子字符串的距离
start表示与上一个子字符串最后一个位置(例如:pwwkew,当i=2时候,因为两个ww,所以此时start的位置变成2,这样子算距离i-start+1才对)。start也可以解释为上一个重复字符的位置(后面那一个)
class Solution:
def lengthOfLongestSubstring(self, str):
"""
:type s: str
:rtype: int
"""
start = 0
index_dict = {}
max = 0
for i in range(len(str)):
if str[i] in index_dict and index_dict[str[i]] >= start:
start = index_dict[str[i]] + 1
index_dict[str[i]] = i
else:
index_dict[str[i]] = i
if i-start + 1 > max:
max = i-start + 1
print(index_dict)
return max
5、最长回文子串
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
令dp[j][i]从字符串j到i是否为回文串
动态回归方程 dp[j][i]是看j+1和i-1是否为回文串.
class Solution(object):
def longestPalindrome(self, s):
n = len(s)
dp = [[0] * n for _ in range(n)]
max_len = 0
res = ""
for i in range(n):
# dp[i][i] = 1
for j in range(i, -1, -1):
if s[i] == s[j] and (i - j < 2 or dp[i - 1][j + 1]):
dp[i][j] = 1
if dp[i][j] and i - j + 1 > max_len:
max_len = i - j + 1
res = s[j:i + 1]
# print(dp)
return res
7、整数反转
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321示例 2:
输入: -123
输出: -321示例 3:
输入: 120
输出: 21
class Solution:
def reverse(self, x: int) -> int:
flag = 1 if x >= 0 else -1
x = abs(x)
str_x = str(x)
str_x = str_x[::-1]
reverse_x = int(str_x) * flag
if -2**31 <= reverse_x <= 2**31 -1:
return reverse_x
else:
return 0
8、字符串转换为整数
#-*-coding:utf-8-*-
class Solution(object):
def myAtoi(self, str):
"""
:type str: str
:rtype: int
"""
#去掉左边字符
str=str.lstrip()
#如果字符串空,返回
if len(str)==0:
return 0
#设置默认输出为0
last=0
#如果有符号设置起始位置2,其余的为1
i=2 if str[0]=='-'or str[0]=='+' else 1
#循环,直到无法强转成int,跳出循环
while i <= len(str):
try:
last=int(str[:i])
i+=1
except:
break
#如果数字超出范围,返回范围最大值
if last<-2147483648 :
return -2147483648
if last>2147483647:
return 2147483647
return last
14、最长公共前缀
输入: ["flower","flow","flight"] 输出: "fl"
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
if strs == []: # 字符串为空返回''
return ''
elif len(strs) == 1: # 若列表仅有一个单词,返回该单词
return strs[0]
else:
minlen = len(min(strs, key=len)) # 找到最短的单词长度
s = ''
for i in range(1, minlen + 1): # 最多遍历 minlen 次
# 每次遍历同时从每个单词取相同长度的前缀加入集合,集合中不会有重复单词
# 列表中每个单词的相同长度前缀相同,因此集合长度为1
if len({s[:i] for s in strs}) == 1:
# 将s值更新为当前s长度与任意一个单词[:i]的部分中较大的那个值
# 为了避免不存在strs[1],此处默认为第一个
s = max(s, strs[0][:i])
return s
15、三数之和
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
'''
算法思路:最外层控制一个元素的循环,
内层用双指针,一个从头到尾扫描,另一个从尾到头扫描,判断三个元素的值之和是否为零
注意:相同的元素需要跳过
'''
# 对列表进行排序
nums.sort()
res, k = [], 0
for k in range(len(nums) - 2):
# 如果出现最小元素为正数,则不存在和为0的情况,直接返回
if nums[k] > 0:
break
# 如果出现第一个元素重复的情况,为避免重复结果,跳过后续执行
if k > 0 and nums[k] == nums[k - 1]:
continue
# 定义接下来的两个元素的双指针
i, j = k + 1, len(nums) - 1
while i < j:
s = nums[k] + nums[i] + nums[j]
if s < 0:
i += 1
# 跳过重复元素
while i < j and nums[i] == nums[i - 1]:
i += 1
elif s > 0:
j -= 1
# 跳过重复元素
while i < j and nums[j] == nums[j + 1]:
j -= 1
else:
# 当出现元素满足条件是,将结果加入到列表
res.append([nums[k], nums[i], nums[j]])
# 接着更新索引(注意跳过相同元素)
i += 1
j -= 1
while i < j and nums[i] == nums[i - 1]:
i += 1
while i < j and nums[j] == nums[j + 1]:
j -= 1
return res
19、删除链表的倒数第N个节点
#-*-coding:utf-8-*-
def FindKthToTail(self, head, k):
if not head:
return None
pFast = head
pSlow = head
for i in range(k - 1):
if pFast.next:
pFast = pFast.next
else:
return None
while pFast.next:
pFast = pFast.next
pSlow = pSlow.next
return pSlow
27. 移除元素
给定 nums = [3,2,2,3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
你不需要考虑数组中超出新长度后面的元素。
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
i = 0
for j in range(len(nums)):
if nums[j] != val:
nums[i] = nums[j]
i += 1
return i
28、实现 strStr()
实现 strStr() 函数。
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
输入: haystack = "hello", needle = "ll" 输出: 2
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
n = len(haystack)
m = len(needle)
res = -1
for i in range(n-m+1):
if haystack[i:i+m] == needle:
res =i
break
return res
31. 下一个排列
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须原地修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
34、在排序数组中查找元素的第一个和最后一个位置
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]
1 采用二分查找方法找到与target相等的那个下标mid,让first = last = mid;
2 找到以后,如果mid > 0并且前一个值也等于target, first = mid -1,while循环遍历一下;
3 找到以后,如果mid < 列表长度并且后一个值也等于target, last = mid +1,while循环遍历一下。
不知道时间会不会超出O(log n) ,但是仿真时间比官方题解要快。哈哈哈尴尬一笑。
# -*-coding:utf-8-*-
class Solution:
def searchRange(self, nums, target):
left = 0
right = len(nums) - 1
while left <= right:
middle = (left + right) // 2
if nums[middle] == target:
m = middle
first = last = middle
while m < right and nums[m] == nums[m + 1]:
m += 1
last += 1
m = middle
while m > 0 and nums[m] == nums[m - 1]:
m -= 1
first -= 1
return [first, last]
elif nums[middle] < target:
left = middle + 1
else:
right = middle - 1
return [-1, -1]
38. 报数
报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1 被读作 "one 1" ("一个一") , 即 11。
11 被读作 "two 1s" ("两个一"), 即 21。
21 被读作 "one 2", "one 1" ("一个二" , "一个一") , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。
注意:整数顺序将表示为一个字符串。
39. 组合总和
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]示例 2:
输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
42. 接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
#-*-coding:utf-8-*-
#暴力解法
def tracp(array):
res = 0
for i in range(len(array)):
l_max = max(array[0:i+1])
r_max = max(array[i:])
res += min(l_max, r_max) - array[i]
return res
#双指针解法
def tracp1(array):
res = 0
left = 0;right = len(array)-1
l_max = array[0];r_max = array[-1]
while left <= right:
l_max = max(l_max, array[left])
r_max = max(r_max, array[right])
if l_max <= r_max:
res += l_max - array[left]
left += 1
else:
res += r_max - array[right]
right -= 1
return res
array = [0,1,0,2,1,0,1,3,2,1,2,1]
res = tracp1(array)
print(res)
46.全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
res = []
def backtrack(nums, tmp):
if not nums:
res.append(tmp)
return
for i in range(len(nums)):
backtrack(nums[:i] + nums[i+1:], tmp + [nums[i]])
backtrack(nums, [])
return res
48. 旋转图像
给定一个 n × n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
# -*-coding:utf-8-*-
class Solution:
def rotate(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: void Do not return anything, modify matrix in-place instead.
"""
n = len(matrix[0])
# transpose matrix
for i in range(n):
for j in range(i, n):
matrix[j][i], matrix[i][j] = matrix[i][j], matrix[j][i]
# reverse each row
for i in range(n):
matrix[i].reverse()
return matrix
62.不同路径
个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dp = [[0]*n for _ in range(m)]
for i in range(m):
for j in range(n):
if i == 0 and j == 0:
dp[i][j] = 1
elif i == 0: dp[i][j] = 1
elif i == 0: dp[i][j] = 1
else:
dp[i][j] = dp[i-1][j] + dp[i][j-1]
return dp[-1][-1]
64. 最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。
class Solution:
def minPathSum(self, grid):
if not grid:
return
m = len(grid)
n = len(grid[0])
for i in range(m):
for j in range(n):
if i == 0 and j == 0:
continue
elif i == 0: grid[i][j] = grid[i][j-1] + grid[i][j]
elif j == 0: grid[i][j] = grid[i-1][j] + grid[i][j]
else:
grid[i][j] = min(grid[i-1][j], grid[i][j-1]) + grid[i][j]
return grid[-1][-1]
55.跳跃游戏
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
输入: [2,3,1,1,4] 输出: true 解释: 从位置 0 到 1 跳 1 步, 然后跳 3 步到达最后一个位置。
70. 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
class Solution:
def climbStairs(self, n: int) -> int:
res = [1,2]
for i in range(2, n):
res.append(res[i-2] + res[i-1])
return res[n-1]
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if head == None or head.next == None:
return head
phead = head
while phead.next:
if phead.val == phead.next.val:
phead.next = phead.next.next
else:
phead = phead.next
return head