Leetcode上的第一题,看下题目:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定: nums = [2, 7, 11, 15], target = 9
因为: nums[0] + nums[1] = 2 + 7 = 9
# 使用暴力解法,复杂度O(n**2)
class Solution:
def twoSum(self, nums, target):
for i , val in enumerate(nums):
for j in range(i+1, len(nums)):
if target == nums[i] + nums[j]:
return [i, j]
方法二:使用哈希表,类似于字典的感觉,不过要把值作为key, 索引看做value值。
class Solution:
def twoSum(self, nums, target):
records = {}
for idx, val in enumerate(nums):
# 检查键是否在
if target - val not in records:
records[val] = idx
else:
return [records[target - val], idx]
题目:给你两个按非递减顺序排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你合并nums2 到 nums1中,使合并后的数组同样按非递减顺序排列。
注意:最终 合并后数组不应由函数返回,而是存储在数组 nums1 中
为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n
方法一:使用python内置的排序函数。
def merge(nums1, m, nums2, n):
nums1[m:] = nums2
# python内置的排序算法
nums1.sort()
return nums1
nums1 = [1,2,3,0,0,0]
m = 3
nums2 = [2,5,6]
n = 3
print(merge(nums1, m, nums2, n))
方法二:类似于快排了,利用两边数组有序。新建一个temp数组,取nums1和nums2的值比较大小,判断停止条件,当temp= m+n的时候。
def merge(nums1, m, nums2, n):
k = m + n
temp = []
i, j = 0, 0
while len(temp) < k:
# 判断两个数组是否有一个用完了,需要把剩余的直接加过去
if i >= m:
temp.extend(nums2[j:n])
elif j >= n:
temp.extend(nums1[i:m])
elif nums1[i] >= nums[j]:
temp.append(nums2[j])
j += 1
else:
temp.append(nums1[i])
i += 1
# 由于要求nums1不变,返回给nums1
for i in range(len(temp)):
nums1[i] = temp[i]
方法三:先合并两个数组,再使用快速排序
def merge(nums1, m, nums2, n):
for i in nums2:
nums1[m] = i
m += 1
def quick_sort(li):
if len(li)<=1:
return li
else:
mid = li[0]
left_list = [x for x in li[1:] if x<=mid]
right_list = [x for x in li[1:] if x>mid]
# 递归调用
return quick_sort(left_list) + [mid] + quick_sort(right_list)
new_li = quick_sort(nums1)
for i in range(len(new_li)):
nums1[i] = new_li[i]
方法四:快排的另外一种写法, 定义left=0的值为tmp,比它大的移到右边,比它小的移到左边,递归调用。
def merge(nums1, m, nums2, n):
for i in nums2:
nums1[m] = i
m += 1
def partition(li, left, right):
tmp = li[left]
while left < right:
while li[right] >= tmp and right > left: # 从右边找比tmp小的数
right -= 1 # 比tmp大就往左走一步
li[left] = li[right] # 把右边值写到左边空位
while li[left] < tmp and left < right: # 从左边找比tmp大的数
left += 1
li[right] = li[left]
li[left] = tmp
return left
def quick_sort(li, left, right):
if left < right:
mid = partition(li, left, right)
quick_sort(li, left, mid-1)
quick_sort(li, mid+1, right)
quick_sort(nums1, 0, len(nums1)-1)
题目:假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
递归的思想,一般可以考虑动态规划,
方法一: 考虑最后还剩一阶时到顶,则有一种方法,如果还剩两阶到顶则有两种方法,
递归公式:
f ( n ) = { 1 n = 1 2 n = 2 f ( n − 1 ) + f ( n − 2 ) n > 3 f(n)= \begin{cases}1 & n=1 \\ 2 & n=2 \\ f(n-1)+f(n-2) & n>3\end{cases} f(n)=⎩ ⎨ ⎧12f(n−1)+f(n−2)n=1n=2n>3
终止条件为最后剩一个楼梯,或者最后剩两个楼梯。
def climbStairs(n):
# 使用递归
if n == 1:
return 1
elif n == 2:
return 2
else:
return climbStairs(n-1) + climbStairs(n-2)
print(climbStairs(3))
跟斐波拉契数列是一样的
# 斐波拉契数列 Fn = F(n-1) + F(n-2)
# 使用递归和非递归 1,1,2,3,5,...
def fibnacci(n):
if n == 1 or n == 2:
return 1
return fibnacci(n-1) + fibnacci(n-2)
方法二:使用哈希表,将前面的值都存着。动态规划,自底向上。
# 使用哈希表加递归,动态规划,自底向上。
def climbStairs1(n):
result = {1:1, 2:2}
if n > 2:
for i in range(3, n+1):
result[i] = result.get(i, result[i-1] + result[i-2])
return result[n]
用数组存着一样的
def climbStairs2(n):
# 动态规划 自己写的 (本质是从下到上,)
result = [1,2]
if n > 2:
for step in range(3, n+1):
result.append(result[-1] + result[-2])
return result[n-1]
leetcode给的答案:
def climbStairs3(n):
s = [1,2]
if n <= 2:
return s[n-1]
while len(s)<n:
s.append(s[-1] + s[-2])
return s[-1]