topic36:有效的数独
题目描述:
请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
注意:
- 一个有效的数独(部分已被填充)不一定是可解的。
- 只需要根据以上规则,验证已经填入的数字是否有效即可。
- 空白格用
'.'
表示。
思路:分别遍历行,列,九宫格,用storage存储出现的数字,如果当前数字已经储存在storage里,说明重复了,不能构成数独。
def isValidSudoku(board):
for i in range(0, 9): # 遍历数独的所有行和列
storage1 = [] # 临时存储某行或某列中出现过的数字
storage2 = []
for j in range(0, 9):
# 对于每个位置,检查其所在的行和列是否合法
if board[i][j] != '.':
# 如果该位置上的数字不为空,则检查其是否已经出现过
if board[i][j] in storage1:
return False
else:
storage1.append(board[i][j])
if board[j][i] != '.':
# 如果该位置上的数字不为空,则检查其是否已经出现过
if board[j][i] in storage2:
return False
else:
storage2.append(board[j][i])
for i in range(0, 9, 3): # 遍历数独的所有 3x3 的子数独
for j in range(0, 9, 3):
storage3 = [] # 临时存储某个子数独中出现过的数字
for x in range(0, 3):
for y in range(0, 3):
# 对于子数独中的每个位置,检查其是否合法
if board[i + x][j + y] != '.':
# 如果该位置上的数字不为空,则检查其是否已经出现过
if board[i + x][j + y] in storage3:
return False
else:
storage3.append(board[i + x][j + y])
return True # 如果所有位置都合法,则返回 True
topic38:外观数列plus(看错题目版)
题目描述:
给定一个正整数 n ,输出外观数列的第 n 项。
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
你可以将其视作是由递归公式定义的数字字符串序列:
countAndSay(1) = "1"
countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。
前五项如下:
1. 1
2. 11 #第一个有1个1
3. 21 #第二个有2个1
4. 1211 #第三个有1个2,1个1
5. 1231 #第四个有1个2,3个1
6. 131221 #第 五个有1个3,1个2,2个1
def countAndSay(target):
storage = funcount('1') # 初始化存储计数的字典,将 '1' 的计数存入其中
if target == 1: # 如果 target 为 1,则直接返回字符串 '1'
return str(1)
n = 1 # n 用于记录当前的迭代次数
while n <= target-1: # 迭代 target-1 次
result = '' # 初始化 result 为空字符串
n += 1 # 增加迭代次数
# 从 9 到 1 遍历数字,如果该数字在 storage 中出现过,则将计数和数字添加到 result 中
for i in range(9, 0, -1):
if str(i) in storage:
result += str(storage[str(i)]) + str(i)
storage = funcount(result) # 将 result 中每个字符的计数存入 storage 中
return result # 返回最终结果
def funcount(string):
count = {} # 初始化计数字典
for c in string: # 遍历字符串中的每个字符
if c in count: # 如果字符已经在计数字典中,则将计数加 1
count[c] += 1
else: # 如果字符不在计数字典中,则将计数初始化为 1
count[c] = 1
return count # 返回计数字典
#print(funcount('21'))
print(countAndSay(5)) # 输出 countAndSay(5) 的结果
topic38:未看错版
题目描述:
给定一个正整数 n ,输出外观数列的第 n 项。
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
你可以将其视作是由递归公式定义的数字字符串序列:
countAndSay(1) = "1"
countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。
前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
第一项是数字 1
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"
思路:迭代,从1计算到输入的值,用funcount函数统计不连续相等元素和其连续次数
class Solution:
def countAndSay(self, target: int) -> str:
def funcount1(string): # 按照顺序统计不重复元素出现次数
n = len(string)
i, j = 0, 0 # 初始化双指针
result = [] # 储存结果
while j < n:
if j < n-1 and string[j] == string[j+1]: # 如果当前字符与后一个字符相同,则j向后移动一位
j += 1
else:
result.append((string[i], j-i+1)) # 存储当前字符的出现次数和字符
i, j = j+1, j+1
return result
storage = funcount1('1') # 初始字符串为'1'
if target == 1: # 如果目标值为1,则直接返回'1'
return str(1)
n = 1
while n <= target - 1: # 循环计算第target个字符串
result = ''
n += 1
for i in range(0, len(storage)):
result += str(storage[i][-1]) + storage[i][0] # 按照顺序统计每个不重复元素的出现次数
storage = funcount1(result) # 将统计结果作为下一个字符串的输入
return result
topic41:缺失的第一个正数(王道数据结构中出现过)
题目描述:给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
思路:先将不满足条件的元素置为0(负数或者大于max),然后初始化一个新数组,长度为max+1,元素初始化为0,随后将处理完的原数组的元素对应到新数组下标,如果存在,则将新数组下标置为1,循环result数组,找出第一个元素为0的下标,返回下标加一
def firstMissingPositive(nums):
length = len(nums)
max_num = len(nums) + 1 # 最大值为数组长度+1,因为缺失的正整数一定在[1, len(nums)+1]中
result = [0] * (length + 1) # 初始化一个全0的结果矩阵
for i in range(0, length):
if nums[i] < 0 or nums[i] >= max_num: # 将负数和大于等于max_num的元素置为0
nums[i] = 0
else:
result[nums[i] - 1] = 1 # 将出现的正整数在结果矩阵中标记为1
for j in range(0, length):
if result[j]==0: # 找到第一个未被标记的正整数
return j + 1
return max_num # 如果所有正整数都被标记,则返回max_num,即len(nums)+1