开始更新高级算法题目了,今天就更新数组和字符串,其实,高级算法题目也不难,主要考察基本的数据结构是否能灵活利用。在此,给出自己的解题看法,望大佬们给予指点。
问题一:除自身以外数组的乘积 |
内容: 给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。 提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。 说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。 进阶: 你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。) |
程序: class Solution: def productExceptSelf(self, nums: List[int]) -> List[int]: tem = 1 for i in nums: tem *= i res = [] if tem != 0: for i in nums: res.append(tem // i) return res else: if nums.count(0) == 1: cur = 1 for i in nums: if i == 0: continue else: cur *= i for i in nums: if i != 0: res.append(0) else: res.append(cur) return res else: return [0] * len(nums) |
问题二:螺旋矩阵 |
内容: 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。 |
程序: class Solution: def spiralOrder(self, matrix: List[List[int]]) -> List[int]: if not matrix: return [] def func(matrix): for i in range(len(matrix)): matrix[i] = matrix[i][::-1] res = [[0] * len(matrix) for _ in range(len(matrix[0]))] for i in range(len(matrix)): for j in range(len(matrix[0])): res[j][i] = matrix[i][j] return res res = [] while len(matrix) > 1: res += matrix[0] matrix = func(matrix[1:]) res += matrix[0] return res |
题目三:四数相加 |
内容: 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。 为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -228 到 228 - 1 之间,最终结果不会超过 231 - 1 。 |
程序:(将其转化为两树相加即可) class Solution: def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int: dic = {} for i in A: for j in B: if str(i+j) not in dic: dic[str(i+j)] = 1 else: dic[str(i+j)] += 1 res = 0 for i in C: for j in D: if str(-(i+j)) in dic: res += dic[str(-(i+j))] return res |
问题四:盛最多水的容器 |
内容: 给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 |
程序: class Solution: def maxArea(self, height: List[int]) -> int: """ 本题为积水问题 问题: 1、如何求积水的面积 2、如何进行遍历 解题: 求积水面积肯定是左边和右边的最矮的为边界,然后乘以距离即可 根据求面积的方法,我们考虑双指针遍历 双指针遍历的话,需要考虑如何更新指针? 肯定是哪个小就被更新,因为宽度变小,若想积水面积变大,需要高度变高 """ i = 0 j = len(height) - 1 res = 0 while i """" 直接计算长、宽 """ K = j - i if height[i] > height[j]: res = max(res,K*height[j]) j -= 1 else: res = max(res,K*height[i]) i += 1 return res |
问题五:生命游戏 |
内容: 根据 百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。 给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态:1 即为活细胞(live),或 0 即为死细胞(dead)。每个细胞与其八个相邻位置(水平,垂直,对角线)的细胞都遵循以下四条生存定律: 如果活细胞周围八个位置的活细胞数少于两个,则该位置活细胞死亡; 如果活细胞周围八个位置有两个或三个活细胞,则该位置活细胞仍然存活; 如果活细胞周围八个位置有超过三个活细胞,则该位置活细胞死亡; 如果死细胞周围正好有三个活细胞,则该位置死细胞复活; 根据当前状态,写一个函数来计算面板上所有细胞的下一个(一次更新后的)状态。下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的,其中细胞的出生和死亡是同时发生的。 |
程序: class Solution: def gameOfLife(self, board: List[List[int]]) -> None: """ Do not return anything, modify board in-place instead. """ ''' 直接暴力求解 时间复杂度为O(8*m*n) ''' s = [] m = len(board) n = len(board[0]) for i in range(m): for j in range(n): cur = 0 for x,y in [[1,0],[-1,0],[1,1],[1,-1],[0,1],[0,-1],[-1,1],[-1,-1]]: if 0 <= x+i and 0 <= y+j and board[x+i][y+j] == 1: cur += 1 if cur 2: if board[i][j] == 1: s.append([i,j,0]) elif cur > 3: if board[i][j] == 1: s.append([i,j,0]) elif cur == 3: if board[i][j] == 0: s.append([i,j,1]) for tem in s: board[tem[0]][tem[1]] = tem[2] |
问题六:缺失的第一个正数 |
内容: 给你一个未排序的整数数组,请你找出其中没有出现的最小的正整数。 |
class Solution: def firstMissingPositive(self, nums: List[int]) -> int: """ 本题也是简单题吧!!!! 解题思路: 1、直接进行排序 2、判断当前值,若是小于零直接continue 2、若是大于零,这考虑当前值是不是前一个的+1递进 3、这里有个问题就是需要考虑最开始的值得问题 时间复杂度O(n),空间复杂度O(1) """ if not nums: return 1 nums = sorted(list(set(nums))) for i in range(len(nums)): if i == 0 and nums[i] > 1: return 1 else: if nums[i] <= 0: continue else: if nums[i] == 1: continue else: if nums[i] == nums[i-1] +1: continue else: return max(nums[i-1] + 1,1) return max(nums[-1] + 1,1 |
问题七:最长连续序列 |
内容: 给定一个未排序的整数数组,找出最长连续序列的长度。 要求算法的时间复杂度为 O(n)。 |
程序: class Solution: def longestConsecutive(self, nums: List[int]) -> int: """ 本题直接动态规划即可求出,简单题类型 时间复杂度为O(n),空间复杂度为O(n) """ if not nums: return 0 dp = [1] * len(nums) nums = sorted(nums) for i in range(len(dp)): if i == 0: continue else: if nums[i] == nums[i-1] + 1: dp[i] = dp[i-1] + 1 elif nums[i] == nums[i-1]: dp[i] = dp[i-1] return max(dp) |
题目八:寻找重复数 |
内容: 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。 说明: 不能更改原数组(假设数组是只读的)。 只能使用额外的 O(1) 的空间。 时间复杂度小于 O(n2) 。 数组中只有一个重复的数字,但它可能不止重复出现一次。 |
程序: class Solution: def findDuplicate(self, nums: List[int]) -> int: nums = sorted(nums) for i in range(1,len(nums)): if nums[i] == nums[i-1]: return nums[i] return None |
问题九:基本计算器 |
内容: 实现一个基本的计算器来计算一个简单的字符串表达式的值。 字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。整数除法仅保留整数部分。 |
程序: class Solution: def calculate(self, s: str) -> int: s = s.replace(' ','') num = [] cur = '' i = 0 while i len(s): if s[i] not in ['/','*','+','-']: cur += s[i] else: num.append(cur) num.append(s[i]) cur = '' i += 1 num.append(cur) print(num) A = [] j = 0 while j len(num): if num[j] not in ['/','*']: A.append(num[j]) j += 1 else: if num[j] == '/': tem = A.pop() A.append(str(int(tem)// int(num[j+1]))) j += 2 else: tem = A.pop() A.append(str(int(tem) * int(num[j+1]))) j += 2 if len(A) == 1: return int(A[0]) B = [] k = 0 while k len(A): if A[k] not in ['+','-']: B.append(A[k]) k += 1 else: if A[k] == '-': tem = B.pop() B.append(str(int(tem) - int(A[k+1]))) k += 2 else: tem = B.pop() B.append(str(int(tem) + int(A[k+1]))) k += 2 return int(B[0]) |
问题十一:滑动窗口最大值 |
内容: 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口中的最大值。 进阶: 你能在线性时间复杂度内解决此题吗? |
程序: class Solution: def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: if k == 1: return nums tem = [max(nums[:k])] for i in range(1,len(nums)-k+1): if nums[i+k-1] > tem[-1]: tem.append(nums[i+k-1]) elif nums[i-1] -1]: tem.append(tem[-1]) else: tem.append(max(nums[i:i+k])) return tem |
问题十二:最小覆盖子串 |
内容: 给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。 |
程序: class Solution: def minWindow(self, s: str, t: str) -> str: if len(s) len(t): return '' if s == t: return s left = 0 right = 0 dic_target = {} dic_windom = {} for elem in t: dic_target[elem] = dic_target.get(elem,0) + 1 lenght_target = len(dic_target) lenght_cur = 0 lenght_init = len(s) res = '' while right len(s): if s[right] in dic_target: dic_windom[s[right]] = dic_windom.get(s[right],0) + 1 if dic_windom[s[right]] == dic_target[s[right]]: lenght_cur += 1 while lenght_cur == lenght_target: lenght_res = right - left+1 if lenght_init >= lenght_res: res = s[left:right+1] if len(res) == len(t): return res lenght_init = lenght_res if s[left] in dic_target: dic_windom[s[left]] -= 1 if dic_windom[s[left]] lenght_cur -= 1 left += 1 right += 1 return res |
人生无常,以后的时候还是要好好锻炼下身体了,不然身体吃不消啊。。。。马上要开学了,接下来的时候更多的是需要准备找工作了,感觉自己的编程还是不行啊,技术好烂,加油吧。。。。。