class Solution: def fib(self, n: int) -> int: # 计算过程中,答案需要取模 1e9+7 MOD = 10 ** 9 + 7 if n < 2: return n else: # 使用滚动数组减小空间复杂度 # f0=0 f1=1 p = 0 q = 0 r = 1 for i in range(2, n + 1): p = q q = r r = (p + q) % MOD return r
if __name__ == '__main__': n = 100
f = Solution() b = f.fib(n) print(b)
剑指 Offer II 069. 山峰数组的顶部
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class Solution: def peakIndexInMountainArray(self, arr: List[int]) -> int: s_len = len(arr) left=0 right=s_len-2 ans=1 while left <= right: mid = (left+right)//2 if arr[mid]>arr[mid+1]: ans = mid right = mid - 1 else: left =mid +1 return ans
class Solution { public: int missingNumber(vector<int>& nums) { // 先排序 sort(nums.begin(), nums.end()); // for (int v:nums) // cout<<v; // 遍历对应位置 索引与数组值不对应 则返回该索引 for (int i=0;i<nums.size();i++){ if (nums[i]!=i) return i; } return nums.size(); } };
405. 数字转换为十六进制数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class Solution: def toHex(self, num: int) -> str: CONV = "0123456789abcdef" ans =[] # 32位二进制数 转成十六进制 共8位 4*8 for _ in range(8): temp = num % 16 num = num//16 ans.append(temp) if not num: break # 倒着输出 return ''.join(CONV[j] for j in ans[::-1])
class Solution: def countSegments(self, s: str) -> int: ans =0 # s=s.strip() for i in range(len(s)): if(s[i]==" " and s[i-1]!=" " and i>0) or (i==(len(s)-1) and s[i]!=" "): ans+=1 return ans # return len(s.split())
class Solution: def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]: res = {} stack = [] for num in reversed(nums2): while stack and num >= stack[-1]: stack.pop() res[num] = stack[-1] if stack else -1 stack.append(num) return [res[num] for num in nums1]
598. 范围求和 II
求出区间交集即可
用不着暴力模拟 而且会超时
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class Solution { public: int maxCount(int m, int n, vector<vector<int>>& ops) { // 求解 对于mxn的矩阵M 操作的交集区间 即为最大值区间 int max_a=m,max_b=n; for(vector<int>op : ops) { max_a = min(op[0],max_a); max_b=min(op[1],max_b); } return max_b*max_a; } };
700. 二叉搜索树中的搜索
左子树严格小于根结点 右子树严格大于根结点
1 2 3 4 5 6 7 8 9 10 11 12 13
class Solution { public: TreeNode* searchBST(TreeNode* root, int val) { //遍历二叉搜索树 // 左子树严格小于根结点 右子树严格大于根结点 if (root==nullptr) return NULL; if (root->val == val) return root; return searchBST(val < root->val ? root->left : root->right, val);
class Solution: def balancedStringSplit(self, s: str) -> int: s_list = list(s) ch = 0 ans = 0 # 遍历字符串 统计两种字符出现数量之差 ch=0时 说明前缀字符串数量相同 构成平衡字符串 ans+1 for i in s_list: if i == 'R': ch += 1 else: ch -= 1 if ch == 0: ans += 1 return ans
if __name__ == '__main__': s = "RLRRLLRLRL"
f = Solution() b = f.balancedStringSplit(s) print(b)
class Solution: def destCity(self, paths: List[List[str]]) -> str:
city_dict = dict() for i in paths: if city_dict.get(i[1]): city_dict[i[1]] += 1 else: city_dict[i[1]] = 1 for i in paths: if city_dict.get(i[0]): city_dict[i[0]] -= 1 # 输出值为1的城市 for k, v in city_dict.items(): if v == 1: return k
class Solution: def divide(self, dividend: int, divisor: int) -> int: # 边界情况 INT_MIN = -(2<<30) INI_MAX = (2<<30)-1 # 判断特殊情况 # 被除数为0 if dividend==0: return 0 if divisor==-1: # INT_MIN/-1 为2^31 正数越界 if dividend == INT_MIN: return INI_MAX return -dividend # 方便后面找倍数关系 转为正数计算 # 记录符号 sign = -1 if (dividend>0 and divisor>0 ) or (dividend<0 and divisor<0): sign = 1 dividend = dividend if dividend>0 else -dividend divisor = divisor if divisor>0 else -divisor # 计算结果 # print(dividend,divisor) ans = self.div(dividend,divisor)
if sign == 1: return ans else: return -ans
def div(self,x,y): # 判断 x/y可以除几轮 不能用除号 用倍数来代替 if x<y : return 0 # x > y x中至少包含一个y times =1 ty= y while (ty<<1) <= x: times += times ty = ty<<1 return times + self.div(x-ty,y)
class Solution: def isValidSudoku(self, board: List[List[str]]) -> bool:
dict_col = {} # 先进行行检测 确保不出现重复数字 row = self.signal_num(board) # print(row) if row: # 再进行列检测 确保每一列数据不包含重复数字 # 矩阵转置 t_board = np.transpose(np.array(board)) col = self.signal_num(list(t_board)) # print(col) if col: # 判断3x3 区间是否有重复数字 # 使用numpy实现矩阵切片 np_board = np.transpose(np.array(board)) # print(np_board) for j in range(3): for i in range(3): index_i = i * 3 index_j = j * 3 new_board = np_board[index_i:index_i + 3, index_j:index_j + 3] # 矩阵展开成一纬度 d1_new_board = new_board.flatten() # print(d1_new_board) if not self.signal_num(list([d1_new_board])): return False else: return False
else: return False return True
def signal_num(self, board_self: List[List[str]]) -> bool: for row in board_self: dict_row = {} for i in row: if i != '.' and dict_row.get(i): return False else: dict_row[i] = i return True
38. 外观数列
可以当作双指针来做 一个记录开始位置 一个记录结束为止 相减即为字符串长度
循环次数不确定的时候要用 while
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
class Solution: def countAndSay(self, n: int) -> str: prev = "1" # 循环n-1次 因为第一次为确定的'1' # 每次循环解释 prev for i in range(n - 1): curr = "" pos = 0 start = 0
while pos < len(prev): while pos < len(prev) and prev[pos] == prev[start]: pos += 1 curr += str(pos - start) + prev[start] start = pos prev = curr
import copy class Solution: def permute(self, nums: List[int]) -> List[List[int]]: # 回溯算法实现 # 定义一个布尔数组 标记每个节点的访问状态 used = [False for i in range(len(nums))]
# def depth = 0 #遍历层的深度 res=[] len_nums = len(nums) path=[] def dfs(depth,len_nums,path): if depth == len_nums: # 遍历到最后一层 添加一个排列结果 # 用path会出错 必须用 path[:] 它复制列表old到new res.append(path[:]) for i in range(len_nums): if used[i]: continue else: path.append(nums[i]) used[i]=True dfs(depth+1,len_nums,path) path.pop() used[i]=False dfs(depth,len_nums,path) return res
import copy class Solution: def permuteUnique(self, nums: List[int]) -> List[List[int]]:
# 回溯算法实现 # 定义一个布尔数组 标记每个节点的访问状态 used = [False for i in range(len(nums))] # 必须要排序 nums.sort() # def depth = 0 #遍历层的深度 res=[] len_nums = len(nums) path=[] def dfs(depth,len_nums,path): if depth == len_nums: # 遍历到最后一层 添加一个排列结果 # 用path会出错 必须用 path[:] 它复制列表old到new res.append(path[:]) for i in range(len_nums): if used[i] or (i > 0 and not used[i - 1] and nums[i] == nums[i - 1]): # 遇到相同的数字 只有当前一个相同的数字没有被使用才可以 continue else: path.append(nums[i]) used[i]=True dfs(depth+1,len_nums,path) path.pop() used[i]=False dfs(depth,len_nums,path) return res
class Solution { public String fractionToDecimal(int numerator, int denominator) { // 转 long 计算,防止溢出 long a = numerator, b = denominator; // 如果本身能够整除,直接返回计算结果 if (a % b == 0) return String.valueOf(a / b); StringBuilder sb = new StringBuilder(); // 如果其一为负数,先追加负号 if (a * b < 0) sb.append('-'); a = Math.abs(a); b = Math.abs(b); // 计算小数点前的,部分,并将余数赋值给 a sb.append(String.valueOf(a / b) + "."); a %= b; Map<Long, Integer> map = new HashMap<>(); while (a != 0) { // 记录当前余数所在答案的位置 map.put(a, sb.length()); a *= 10; sb.append(a / b); a %= b; // 如果当前余数之前出现过,则将 [出现位置 - 当前位置] 的部分抠出来(循环小数部分) if (map.containsKey(a)) { int u = map.get(a); return String.format("%s(%s)", sb.substring(0, u), sb.substring(u)); } } return sb.toString(); } }
class Solution: def findRepeatedDnaSequences(self, s: str) -> List[str]: ans =[] substr=defaultdict(int) for i in range(len(s)-10+1): temp = s[i:i+10] # 切片时间复杂度 O(N) substr[temp]+=1 if substr[temp]==2: ans.append(temp) return ans
class Solution { private: void dfs(vector<vector<char>>& grid, int r, int c) { // 行列范围 int nr = grid.size(); int nc = grid[0].size(); //将已经便利过的岛屿标记为2 grid[r][c] = '2'; //判断边界情况 if (r - 1 >= 0 && grid[r-1][c] == '1') dfs(grid, r - 1, c); if (r + 1 < nr && grid[r+1][c] == '1') dfs(grid, r + 1, c); if (c - 1 >= 0 && grid[r][c-1] == '1') dfs(grid, r, c - 1); if (c + 1 < nc && grid[r][c+1] == '1') dfs(grid, r, c + 1); } public: int numIslands(vector<vector<char>>& grid) { // dfs遍历 int nr = grid.size(); if (!nr) return 0; int nc = grid[0].size();
int num_islands = 0; for (int r = 0; r < nr; ++r) { for (int c = 0; c < nc; ++c) { // dfs搜索未访问过的岛屿 if (grid[r][c] == '1') { ++num_islands; dfs(grid, r, c); } } }
from collections import defaultdict from math import sqrt from typing import List
class Solution: def numberOfBoomerangs(self, points: List[List[int]]) -> int: ans = 0 for p in points: # defaultdict,当字典里的key不存在但被查找时,返回的不是keyError而是一个工厂函数的默认值,比如list对应[ ],str对应的是空字符串,set对应set( ),int对应0 hash_points = defaultdict(int) # 使用哈希表存储到该点距离相等的point个数 for temp_q in points: dis = sqrt(pow((p[0] - temp_q[0]), 2) + pow((p[1] - temp_q[1]), 2)) hash_points[dis] += 1 for v in hash_points.values(): # 全排列 ans += v * (v - 1)
class Solution: def findLongestWord(self, s: str, dictionary: List[str]) -> str: # 使用双指针实现字符串匹配 ans = '' # 循环匹配字典中的字符串 for word in dictionary: # 双指针 i, j = 0, 0 while i < len(word) and j < len(s): # 在字符串s中寻找word 也就是说word中的每个字母都要在s中按顺序出现 if word[i] == s[j]: i += 1 j += 1 if i == len(word): # 匹配成功 维护最长字串 长度相同 返回长度最长且 字典序 最小的字符串 if (len(word) > len(ans)) or (len(word) == len(ans) and word < ans): ans = word
return ans
if __name__ == '__main__': s = "abpcplea" dictionary = ["ale", "apple", "monkey", "plea"]
f = Solution() b = f.findLongestWord(s,dictionary) print(b)
from functools import lru_cache class Solution: def shoppingOffers(self, price: List[int], special: List[List[int]], needs: List[int]) -> int: # 价格 price # 大礼包种类 special # 总需求 need
# 1. 过滤掉 不优惠的大礼包组合 filter_sp=[] for sp in special: temp_sp=[] for i in range(len(sp)-1): temp_sp.append(sp[i]*price[i]) if sum(temp_sp)>sp[-1]: # 比直接购买便宜 filter_sp.append(sp) # 2.计算最优组合 @lru_cache(None) # 缓存 加速重复计算 def dfs(cur_needs): # 不购买任何大礼包,原价购买购物清单中的所有物品 min_price = sum(need * price[i] for i, need in enumerate(cur_needs)) for sp in filter_sp: # 大礼包价格 sp_price =sp[-1] # 当前需求为 cur_needs 剩余需求为 next_needs next_needs=[] for good_index in range(len(price)): if sp[good_index]>cur_needs[good_index]: # 不能购买超过需求的商品 break next_needs.append(cur_needs[good_index]-sp[good_index]) if len(next_needs)==len(cur_needs): #大礼包可以购买 没有超出数量限制 # 比较最优价格 min_price=min(min_price,sp_price+dfs(tuple(next_needs))) return min_price
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution: def splitListToParts(self, head: ListNode, k: int) -> List[ListNode]: print(head) cur, l = head, 0 # 计算链表长度 while cur: l += 1 cur = cur.next # 均分 求余 each, remain = l // k, l % k cur, ans, idx = head, [None] * k, 0 while cur: ans[idx] = cur # 使用last断开链表 last.next = None last = None # idx < remain控制左侧数链表于右侧链表 for i in range(each + (idx < remain)): last = cur cur = cur.next idx += 1 last.next = None return ans
class Solution { public: int longestSubsequence(vector<int>& arr, int difference) { // 动态规划 // unordered_map存储dp值 unordered_map<int, int> dp; int ans =0; for (vector<int>::iterator it=arr.begin();it!=arr.end();it++) { dp[*it]=dp[*it-difference]+1; // 以当前数值为结尾的等差序列长度 ans = max(ans,dp[*it]); } return ans; } };
for temp_len in words: if len(temp_len) + self.get_sum(signalLineWord) + len(signalLineWord) <= maxWidth: signalLineWord.append(temp_len) # print(signalLineWord) else: totalLineWords.append(signalLineWord) signalLineWord = [temp_len] totalLineWords.append(signalLineWord) ans = self.put_blank(totalLineWords, maxWidth) print(ans) for lens in ans: print(len(lens)) return ans
# 得到单词总长度 def get_sum(self, word_lsits: List[str]): # 统计每个单词长度 word_len = [len(i) for i in word_lsits] return sum(word_len)
# 填充空格 def put_blank(self, totalLineWords: List[List[str]], maxWidth: int): # print(totalLineWords[:-1]) ans = [] for line in totalLineWords[:-1]: if len(line) == 1: ans.append(line[0] + self.insert_blank(maxWidth - len(line[0]))) else: # 计算平均可插入空格 temp_sum_word = self.get_sum(line) mean_blank = int((maxWidth - temp_sum_word) / (len(line) - 1)) # 计算从左到右的空格数 mod_blank = (maxWidth - temp_sum_word) % (len(line) - 1) # print(temp_sum_word) # print(temp_blank, mod_blank) # 填充空格 temp_str = '' temp_word_line = line[:-1] # mean for word_index in range(len(line[:-1])): temp_word_line[word_index] = line[:-1][word_index] + self.insert_blank(mean_blank) # mod for index in range(mod_blank): temp_word_line[index] += ' ' # str for word in temp_word_line: temp_str += word temp_str += line[-1] ans.append(temp_str) # 最后一行 if len(totalLineWords[-1]) == 1: ans.append(totalLineWords[-1][0] + self.insert_blank(maxWidth - len(totalLineWords[-1][0]))) else: temp_str = '' for word in totalLineWords[-1][:-1]: temp_str += word + ' ' temp_str += totalLineWords[-1][-1] ans.append(temp_str + self.insert_blank(maxWidth - len(temp_str))) return ans
def insert_blank(self, num: int): return ' ' * num
if __name__ == '__main__': words = ["What", "must", "be", "acknowledgment", "shall", "be"] maxWidth = 16 f = Solution() b = f.fullJustify(words, maxWidth)