源于github上的一个10k+star项目
本系列记录思路,以作备忘
array 数组
- delete_nth
删除第n次出现的元素
import collections #input = [1,2,3,1,2,1,2,3] #target = [1,2,3,1,2,3] # 因count实现为遍历对象,构建dict返回,故时间复杂度为O(n^2) def delete_nth_naive(array,n): ans = [] for num in array: if ans.count(num) < n: ans.append(num) return ans #使用collections.defaultdict实际上是相当于自己实现了count方法构建了dict,时间复杂度O(1), 总时间复杂度为O(n) def delete_nth(array, n): result = [] counts = collections.defaultdict(int) for i in array: if counts[i] < n: result.append(i) counts[i] += 1 return result
- flatten
数组降维
from collections import Iterable # 递归思想实现数组降维,返回list def flatten(input_arr, output_arr=None): if output_arr is None: output_arr = [] for ele in input_arr: if isinstance(ele, Iterable): flatten(ele, output_arr) else: output_att.append(ele) return output_arr # 递归思想实现数组降维,返回generator, 好处惰性加载,节约内存 def flatten_iter(iterable): for element in iterable: if isinstance(element, Iterable): yield from flatten_iter(element) else: yield element #ps.python默认最大递归次数为1000,所以数组维数过大时会抛出 maximum recursion depth exceeded while calling a Python object 错误 #使用sys模块的sys.setrecursionlimit(1500)可以设置最大递归次数
- garage
停车场问题:0代表空位,每步只可移动一辆车到空位,最少步数达到目标要求
# 初始:[1,2,3,0,4], 目标:[0,3,2,1,4] #[1,2,3,0,4]→[0,2,3,1,4]→[2,0,3,1,4]→[2,3,0,1,4]→[0,3,2,1,4] def garage(initial, final): initial = initial[::] steps = 0 seq = [] while initial != final: zero = initial.index(0): if zero != final.index(0): car_to_move = final[zero] pos = initial.index(car_to_move) initial[zero],initial[pos] = initial[pos],initial[zero] else: for i in range(len(initial)): if initial[i] != final[i]: initial[zero],initial[i] = initial[i],initial[zero] break seq.append(initial[::]) steps += 1 return steps, seq # 思路:利用0来定位,获取initial里0的index,再获取final对应index值n,在initial里n值和0值位置互换,循环,直到initial==final # ps.seq.append(initial[::])里initial[::]的作用是复制,直接用initial会用最后一次的值覆盖前面的,原因是append添加的是地址、引用,当这个引用内容被改变时,前面添加的相同地址的内容也随之改变
- josephus_problem
约瑟夫环问题,一组数字围成圆,按某一步长剔除元素,剔除后下一元素按步长继续
def josephus(int_list, skip): skip = skip - 1 #list starts with 0 index idx = 0 len_list = len(int_list) whilel len_list > 0: idx = (skip+idx) % len_list #hash index to every 3rd yield int_list.pop(idx) len_list -= 1 #思路:pop出一个元素后,后面元素的index会依次-1,下一个需pop的元素index即当前index+2
- max_ones_index
例:[1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1]→[1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1] 得到最长的1的序列,返回0的index 3
def max_ones_index(arr): n = len(arr) max_count = 0 max_index = 0 prev_zero = -1 prev_prev_zero = -1 for curr in range(n): if arr[curr] == 0: if curr - prev_prev_zero > max_count: max_count = curr - prev_prev_zero max_index = prev_zero prev_prev_zero = prev_zero prev_zero = curr if n - prev_prev_zero > max_count: max_index = prev_zero return max_index #思路:替换后连续序列的长度取决于它两边0点的index,进行遍历时保存上一个0点index和上上个0点的index,curr - prev_prev_zero就是prev_zero替换后序列能达到的最大长度+1
- limit
给定一个不含重复元素的数组、最小值、最大值,返回相对位置不变的只包含最小值~最大值的数组,时间复杂度O(n)
例:limit([1,2,3,4,5],None,3) = [1,2,3]
def limit(arr, min_lim=None, max_lim=None): result = [] if min_lim == None: for i in arr: if i <= max_lim: result.append(i) elif max_lim == None: for i in arr: if i >= min_lim: result.append(i) else: for i in arr: if i >= min_lim and i <= max_lim: result.append(i) return result #思路:遍历的同时加限制条件
- longest_non_repeat
给定一个字符串,返回不含重复元素的最大子字符串长度。
例:'pwwkew',最大子字符串 'wke',长度3
def longest_non_repeat_v1(string): if string is None: return 0 temp = [] max_len = 0 for i in string: if i in temp: temp = [] temp.append(i) max_len = max(max_len,len(temp)) return max_len #思路:遍历的同时做判断,出现重复元素就清空,时间复杂度O(n^2) def longest_non_repeat_v2(string): if string is None: return 0 start, max_len = 0, 0 used_char = {} for index, char in enumerate(string): if char in used_char and start <= used_char[char]: start = used_char[char] else: max_len = max(max_len, index - start) used_char[char] = index return max_len #思路:start记录的是出现重复元素后该元素上次出现的index,当前index - start即为出现重复元素前最大值,由于引入字典,时间复杂度O(n) * O(1) = O(n)
- merge_intervals 合并区间
-。-没看懂题目。跳过
- missing_ranges 缺失范围
对于给定数组,找到给定下限值,上限值之间数组范围之外的range
例:[3,5],lo=1,hi=10 → answer : [(1,2),(4,4),(6,10)]
def missing_ranges(arr, lo, hi): res = [] start = lo for n in arr: if n == start: start += 1 elif n > start: res.append((start, n-1)) start = n + 1 if start <= hi: res.append((start, hi)) return res #思路:左边界值在遍历数组的同时随着数组元素值向右边界靠近
- plus_one +1运算
例:[1,2,3,9,9] → puls_one → [1,2,4,0,0]
def plus_one_v1(digits): digits[-1] = digits[-1] + 1 res = [] ten = 0 i = len(digits) - 1 while i >= 0 or ten == 1: summ = 0 if i >= 0: summ += digits[i] if ten: summ += 1 res.append(summ % 10) ten = summ // 10 i -= 1 return res[::-1] def plus_one_v2(digits): n = len(digits) for i in range(n-1,-1,-1): if digits[i] < 9: digits += 1 return digits digits[i] = 0 digits.insert(0, 1) return digits def plus_one_v3(num_arr): for idx, digit in reversed(list(enumerate(num_arr))): num_arr[idx] = (num_arr[idx] + 1) % 10 if num_arr[idx]: return num_arr return [1]+num_arr #思路:[...万,千,百,十,个],这样看数组,逐位进行判断
未完待续......
ps:编辑器有点不会用,可能有排版问题,望见谅