一、数组【简单题】
03 数组中重复的数
nums = list(map(int, input().split()))
nums.sort()
for i in range(0, len(nums)-1):
if nums[i] == nums[i+1]:
print(nums[i])
break
11 旋转数组的最小数字
方法一:暴力搜索,遍历数组找到第一个当前数比上一个数小的数进行输出,若遍历完整个数组都没有发现该数,说明数组没有进行翻转,直接输出数组的第一个数即可。
# numbers = list(map(int, input().split()))
# count = 0
# for i in range(len(numbers)-1):
# if numbers[i+1] < numbers[i]:
# print(numbers[i+1])
# count += 1
# if count == len(numbers)-1:
# print(numbers[0])
方法二: 采用二分查找
找到列表的最后一个元素记为x,那么在最小值的右侧的数字一定是<=x;在最小值左侧的数字一定是>=x
找到列表的中轴元素,记为mid。如果mid<=x,则最小值一定在mid的左侧,因此只用考虑[0,mid]这部分数据;同理,若mid>=x,则最小值一定在mid的右侧,只用考虑[mid,x]这部分数据。
numbers = list(map(int, input().split()))
low, high = 0, len(numbers)-1
while low < high:
mid = low + (high-low)//2
if numbers[mid] < numbers[high]:
high = mid
elif numbers[mid] > numbers[high]:
low = mid + 1
else:
high -= 1
print(numbers[high])
17 打印从1到最大的n位数
n = int(input())
a = []
b = pow(10, n)
print(b)
for i in range(1, b):
a.append(i)
print(a)
21 调整数组顺序使奇数位于偶数前面
nums = list(map(int, input().split()))
odd = []
even = []
new = []
for i in nums:
if i % 2 == 1:
odd.append(i)
else:
even.append(i)
new = odd + even
print(new)
29 顺时针打印矩阵
r, c = map(int, input().split())
matrix = []
for i in range(r):
matrix.append(list(map(int, input().split())))
rows, columns = len(matrix), len(matrix[0])
print(rows, columns)
order = list()
left, right, top, bottom = 0, columns - 1, 0, rows - 1 # 定义矩阵的四个角
while left <= right and top <= bottom: # 循环条件,当左顶角<=右顶角;当上顶角<=下顶角
for column in range(left, right + 1):
order.append(matrix[top][column]) # 行固定,列在变,按行把数据append到order中
for row in range(top + 1, bottom + 1): # 行在变,列固定,将该列的数据append到order中
order.append(matrix[row][right])
if left < right and top < bottom: # 每次填充完一行一列就看一下是否满足循环条件
for column in range(right - 1, left, -1): # 次层循环,行固定,列在变
order.append(matrix[bottom][column])
for row in range(bottom, top, -1): # 次层循环,列在变,行固定
order.append(matrix[row][left])
left, right, top, bottom = left + 1, right - 1, top + 1, bottom - 1 # 进入下一次循环
print(order)
39 数组中出现次数超过一半的数字
nums = list(map(int, input().split()))
nums.sort()
print(nums[len(nums)//2])
40 最小的k个数
arr = list(map(int, input().split()))
k = int(input())
arr.sort()
for i in range(k):
print(arr[i])
42 连续子数组的最大和
方法一:暴力搜索 O(N²),O(1)
方法二:分治思想 O(NlogN),O(logN)
方法三:动态规划 O(N),O(1)
nums = list(map(int, input().split()))
# 动态规划解法一:用一个dp[i]表示以nums[i]结尾的子数组的和
# dp = []
# for i in range(len(nums)):
# if i == 0:
# dp.append(nums[0])
# else:
# if dp[i-1] <= 0:
# dp.append(nums[i])
# else:
# dp.append(dp[i-1] + nums[i])
# print(max(dp))
## 动态规划解法二
pre = 0
maxAns = nums[0]
for i in nums:
pre = max(pre+i, i) ## 前面的和对当前值有无帮助
maxAns = max(pre, maxAns) ## 求所有子数组和中最大的那个,即求全局最大
print(maxAns)
53-1 在排序数组中查找数字I
nums = list(map(int, input().split()))
target = int(input())
if target in nums:
print(nums.count(target))
else:
print(0)
53-2 0~n-1中缺失的数字
nums = list(map(int, input().split()))
for i, j in enumerate(nums):
if i != j:
print(i)
print(i+1)
57 和为s的两个数字
方法一:暴力搜索
方法二:使用双指针,两个指针分别指向数组的两端,若s>target,则左指针向左移动;若s<target,则右指针向右移动;若相等则输出。
方法三:hash表
nums = list(map(int, input().split()))
target = int(input())
# new = []
# flag = 0
# for i in range(len(nums)):
# if nums[i] <= target:
# new.append(nums[i])
# print(new)
# # 超出时间限制
# for i in range(len(new)):
# for j in range(i+1, len(new)):
# if new[i] + new[j] == target:
# print(new[i], new[j])
# flag = 1
# break
# if flag == 1:
# break
## 方法二: 使用双指针,两个指针分别指向数组的两端,若s>target,则左指针向左移动;若s<target,则右指针向右移动;若相等则输出。
# left = len(new) - 1
# right = 0
# for i in range(len(new)):
# if new[left] + new[right] == target:
# print(new[left], new[right])
# break
# elif new[left] + new[right] > target:
# left -= 1
# else:
# right += 1
## 方法三: 使用hash表
# 需要注意的点:列表为空的时候需要用append来赋值
# python中的hash表一般用字典来实现
hashtable = {}
for i, num in enumerate(nums):
hashtable[nums[i]] = i
if target - num in hashtable:
print(num, target-num)
break
61 扑克牌中的顺子
巧妙思路:只要保证nums里除了0 其余数字无重复且最大牌-最小牌<5即可保证它是顺子
nums = list(map(int, input().split()))
## 方法一
# nums.sort()
# c = nums.count(0)
# flag = 0
#
# for i in range(len(nums)):
# if nums.count(nums[i]) > 1 and nums[i] != 0:
# print(False)
# flag = 1
# break
# if c == 0:
# if i < len(nums)-1 and nums[i+1] - nums[i] != 1:
# print(False)
# flag = 1
# break
# else:
# if i+c+1 < 5:
# if nums[i+c+1] - nums[i+c] != 1:
# if c < nums[i+c+1] - nums[i+c] - 1:
# print(False)
# flag = 1
# break
# if flag == 0:
# print(True)
## 方法二:只要保证nums里除了0 其余数字无重复且最大牌-最小牌<5即可保证它是顺子
flag = 0
new = []
for i in nums:
if i != 0:
new.append(i)
maxn = max(new)
minn = min(new)
for i in range(len(new)):
if new.count(new[i]) > 1:
print(False)
flag = 1
break
if maxn - minn < 5 and flag == 0:
print(True)
二、数组【中等题】
04 二维数组中的查找
m, n, target = map(int, input().split())
array = []
for i in range(m):
array.append(list(map(int, input().split())))
print(array)
i = 0
j = n - 1
flag = 0
if len(array) == 0 or len(array[0]) == 0:
print(False)
else:
while i < m and j >= 0:
x = array[i][j]
if x == target:
print(True)
flag = 1
break
elif x > target:
j -= 1
else:
i += 1
if flag == 0:
print(False)
12 矩阵中的路径
m, n = map(int, input().split())
word = list(input())
board = []
for i in range(m):
board.append(list(input()))
print(board)
def dfs(i, j, k): # 返回的是第i行和第j列的数是否与word[k]相匹配
# 回溯算法的终止条件,越界或元素不匹配
if not 0 <= i < len(board) or not 0 <= j < len(board[0]) or board[i][j] != word[k]: return False
# 如果word数组遍历完了,则返回True
if k == len(word)-1: return True
board[i][j] = '' # 作为标记,以免重复访问
res = dfs(i+1, j, k+1) or dfs(i-1, j, k+1) or dfs(i, j+1, k+1) or dfs(i, j-1, k+1) # 收集结果
board[i][j] = word[k] # 将空字符还原成原来的字符
return res
for i in range(len(board)):
for j in range(len(board[0])):
if dfs(i, j, 0):print(True)
else:
print(False)
47 礼物的最大价值
m, n = map(int, input().split())
grid = []
for i in range(m):
grid.append(list(map(int, input().split())))
print(grid)
for j in range(1, n):
grid[0][j] += grid[0][j-1]
for i in range(1, m):
grid[i][0] += grid[i][i-1]
for i in range(1, m):
for j in range(1, n):
grid[i][j] += max(grid[i-1][j], grid[i][j-1]) # 用原数组去存求和的结果,而非用一个数去存
print(grid)
print(grid[-1][-1])
56.1 数组中数字出现的次数
方法一: 使用python内置函数count进行查找
# nums = list(map(int, input().split()))
# a = []
# for i in nums:
# if nums.count(i) != 2:
# a.append(i)
# print(a)
方法二:使用异或
a, b, x = 0, 0, 0
# 列表中所有的数都进行异或操作
for i in nums:
x ^= i
print(x)
# 在异或结果中找到任意为1的位
div = 1
while div & x == 0:
div <<= 1
print(div)
# 根据这一位对所有的数字进行分组。
# 在每个组内进行异或操作,得到两个数字。
for j in nums:
if j & div:
a ^= j
else:
b ^= j
print(a, b)
56.2 数组中数字出现的次数
nums = list(map(int, input().split()))
for i in nums:
if nums.count(i) != 3:
print(i)
63 股票的最大利润
prices = list(map(int, input().split()))
if len(prices) == 0:
print(0)
else:
minPrice = prices[0]
profit = []
for i in range(len(prices)):
profit.append(prices[i] - minPrice)
if prices[i] < minPrice: minPrice = prices[i]
print(profit)
print(max(profit))
三、字符串【简单题】
05 替换空格
s = input()
print(s.count(' '))
print(s.replace(' ', '%20'))
50 第一个只出现一次的字符
方法一: 使用hash表存储频数
# 使用hash表存储频数
# import collections
# s = input()
# flag = 0
# frequency = collections.Counter(s)
# print(frequency)
# for i, ch in enumerate(s):
# if frequency[ch] == 1:
# print(ch)
# flag = 1
# break
# if flag == 0:
# print(' ')
方法二: 使用hash表存储索引
s = input()
flag = 0
hashmap = {} # 定义一个字典充当hash表
for i, ch in enumerate(s):
if ch in hashmap:
hashmap[ch] = -1
else:
hashmap[ch] = i
first = len(s)
for j in hashmap.values():
if j != -1 and j < first:
first = j
if first == len(s):
print('1')
else:
print(s[first])
58.1 翻转单词顺序
s = input().split()
nums = list(s)
print(nums)
nums_new = []
for i in range(len(nums)-1, -1, -1):
nums_new.append(nums[i])
print(' '.join(nums_new))
58.2 左旋转字符串
方法一:字符串切片
s = input()
n = int(input())
s1 = ''.join(s[n:])+s[0:n]
print(s1)
方法二:列表遍历拼接
n = int(input())
nums = list(input()) # 使用list将输入的字母都分开
nums_new = []
for i in range(n, n+len(nums)):
nums_new.append(nums[i % len(nums)]) # 使用求余巧妙简化代码
print(''.join(nums_new))
四、动态规划【简单题】
10.1 斐波那契数列
n = int(input())
if n < 2:
print(n)
f1 = 0
f2 = 1
MOD = 10 ** 9 + 7
for i in range(1, n):
f3 = (f1 + f2) % MOD
f1 = f2
f2 = f3
print(f3)
10.2 青蛙跳台阶问题
n = int(input())
a, b = 1, 1
for _ in range(n):
a, b = b, a + b
print('a:', a)
print('b:', b)
print(a % 1000000007)
42 连续子数组的最大和
nums = list(map(int, input().split()))
dp = [0] * len(nums)
for i in range(1, len(nums)):
dp[i] = max(nums[i], dp[i-1]+nums[i])
print(dp)
print(max(dp))
五、动态规划【中等题】
14.1 剪绳子
n = int(input())
dp = [0] * (n+1)
dp[2] = 1
for i in range(3, n+1):
for j in range(2, i):
dp[i] = max(dp[i], max(j*(i-j), j*dp[i-j]))
print(dp)
print(dp[n])
14.2 剪绳子2
class Solution:
def cuttingRope(self, n: int) -> int:
if n <= 3: return n - 1
a, b, p = n // 3, n % 3, 1000000007
if b == 0: return 3 ** a % p
if b == 1: return 3 ** (a - 1) * 4 % p
return 3 ** a * 2 % p
n = int(input())
print(Solution().cuttingRope(n))
47 礼物的最大价值
m, n = map(int, input().split())
grid = []
for i in range(m):
grid.append(list(map(int, input().split())))
print(grid)
for j in range(1, n):
grid[0][j] += grid[0][j-1]
for i in range(1, m):
grid[i][0] += grid[i][i-1]
for i in range(1, m):
for j in range(1, n):
grid[i][j] += max(grid[i-1][j], grid[i][j-1]) # 用原数组去存求和的结果,而非用一个数去存
print(grid)
print(grid[-1][-1])
63 股票的最大利润
prices = list(map(int, input().split()))
if len(prices) == 0:
print(0)
else:
minPrice = prices[0]
profit = []
for i in range(len(prices)):
profit.append(prices[i] - minPrice)
if prices[i] < minPrice: minPrice = prices[i]
print(profit)
print(max(profit))