力扣-剑指offer第2版-python实现

一、数组【简单题】

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))
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值