1.字符串交換位置
時間復雜度O(n) 空間復雜度O(1)
輸入 "abcde" 輸出 "edcba"
def jiaohuan(str1): s1 = list(str1) tmp = 0 for i in range(0, int(len(s1) / 2)): tmp = s1[i] s1[i] = s1[len(s1) - i - 1] s1[len(s1) - i - 1] = tmp return s1 list1 = jiaohuan("abcde") print("".join(list1)) # edcba
2.數組找最大值、最小值
定義了一個數組a = [1,3,4,55,29] 查找數組中最大值
定義一個for循環對數組所有元素遍歷一遍時間復雜度為O(n)
def max_value(l1): min = -1 max = -1 for i in range(len(l1)): if l1[i] > max: max = l1[i] min = i print(max) max_value([1, 2, 333, 4, 5, -1])
3.降低復雜度案例、 輸入數組a = [1,2,3,4,5,6,4,4,4,2] 中查找出現次數最多的數值
def max_count(l1): d1 = {} for i in l1: d1[i] = d1.get(i, 0) + 1 print(d1) max_key = -1 count_num = -1 for i, v in d1.items(): if v > count_num: count_num = v max_key = i print(max_key, count_num) max_count([1, 2, 3, 4, 5, 6, 4, 4, 4, 4])
4.棧:后進先出 給定一個只包括 '(',')','{','}','[',']' 的字符串,判斷字符串是否有效。
class Solution: def isValid(self, s: str) -> bool: len_s = len(s) if len_s % 2 != 0: return False if len_s == 0: return True # 利用進棧出棧的思想 str_dict = {'(': ')', '[': ']', '{': '}'} stacked = [] for i in range(len_s): # 如果符號為左括號進行壓棧 if s[i] in str_dict.keys(): stacked.append(s[i]) # 如果棧不為空且符號在右括號內且左符號和最后一個元素相等 if stacked and s[i] in str_dict.values() and s[i] == str_dict[stacked[-1]]: stacked.pop() if stacked == []: return True else: return False solution = Solution() print(solution.isValid("{[]}")) # True print(solution.isValid("{[[}")) # False
5.為支持瀏覽器前進和后退功能,利用棧記錄歷史訪問信息 后進先出
first_list = [] last_list = [] def chrome_a(url): if url not in last_list and url not in first_list: # 當用戶訪問一個新頁面 last_list.append(url) elif url in last_list: # 當用戶后退一個頁面 last_list.pop() first_list.append(url) else: # 用戶前進一個頁面 first_list.pop() last_list.append(url) for url in [1, 2, 3, 4, 5, 5, 4, 3, 4]: chrome_a(url) print(first_list) print(last_list)
6.隊列 先進先出
def josephus2(num, k, m): alist = list(range(1, num + 1)) index, step = k - 1, m # 從1號開始報數,數到3的那個人出列 for i in range(num - 1): index = (index + step - 1) % len(alist) print('出去的數:', alist.pop(index)) return '最后的一個數:%s' % alist[0] print(josephus2(13, 1, 3))
7.數組 數組在內存中是連續存放的,數組內的數據,可以通過索引值直接取出得到
數組 [1,4,3,5,2] 去掉一個最大值和最小值求平均數 要求不允許開辟O(n)空間復雜度的數據結構
def score_avge(l1): max_num = -1 max_number = -1 min_num = -1 min_number = 99 for index, value in enumerate(l1): if value > max_number: max_number = value max_num = index if min_number > value: min_number = value min_num = index print(min_num, max_num) del l1[max_num] del l1[min_num] scores = 0 for i, v in enumerate(l1): scores += v print("平均分:{}".format(scores / len(l1))) score_avge([1, 4, 3, 5, 2])
8.字符串 操作都是On
字符串替換將a替換為1aa替換為2 abaabccdaab==>1b2bccd2b
for i in s1: if i == "a": count += 1 else: if count != 0: s2 += str(count) count = 0 s2 += i print(s2)
9. 字符串 s = "goodgoogle",判斷字符串 t = "google" 在 s 中是否存在
s = "goodgoogle1ccc" t = "google" status = True num = 0 for i, v in enumerate(s): if v == t[num]: status = True num += 1 if len(t) == num: break else: status = False num = 0 if status: print("t字符串在s中") else: print("t字符串不在s中")
10.設置有且有兩個字符串a = "1345239" b = "12345" 由於"345"同時出現在a和b中因此輸出345
def getMaxCommonSubstr(s1, s2): # 求兩個字符串的最長公共子串 # 思想:建立一個二維數組,保存連續位相同與否的狀態 len_s1 = len(s1) len_s2 = len(s2) # 生成0矩陣,為方便后續計算,多加了1行1列 # 行: (len_s1+1) # 列: (len_s2+1) record = [[0 for i in range(len_s2 + 1)] for j in range(len_s1 + 1)] print(record) maxNum = 0 # 最長匹配長度 p = 0 # 字符串匹配的終止下標 for i in range(len_s1): for j in range(len_s2): if s1[i] == s2[j]: # 相同則累加 record[i + 1][j + 1] = record[i][j] + 1 if record[i + 1][j + 1] > maxNum: maxNum = record[i + 1][j + 1] p = i # 匹配到下標i # 返回 子串長度,子串 return maxNum, s1[p + 1 - maxNum: p + 1] print(getMaxCommonSubstr("1345239", "12345"))
11.二叉樹 樹的遍歷方法:前序遍歷、中序遍歷、后序遍歷
# 遞歸的核心思想是把規模大的問題轉換為規模小的相似的子問題 def move(n, a, b, c): if n == 1: print('%s-->%s' % (a, c)) else: move(n - 1, a, c, b) print('%s-->%s' % (a, c)) move(n - 1, b, a, c) move(3, 'A', 'B', 'C')
12.分治法、二分查找
l1 = [i for i in range(0, 9)] print("查找列表為:{}".format(l1)) start = 0 end = len(l1) - 1 number = 5 while True: middle = (start + end) // 2 if number == l1[middle]: print("索引位置為:{}".format(middle)) break elif number > l1[middle]: start = middle + 1 elif number < l1[middle]: end = middle - 1 if start > end: print("沒找到") break
13.在一個有序數組里面,查找出第一個大於9的數字,假設一定存在
l1 = [-1, 3, 3, 7, 10, 14, 14] start = 0 end = len(l1) - 1 number = 9 while True: middle = (start + end) // 2 if l1[middle] > number and l1[middle - 1] < number: print("第一個比{}大的數字是:{}".format(number, l1[middle])) break elif number > l1[middle]: start = middle + 1 elif number < l1[middle]: end = middle - 1 if start > end: break
14.排序 -- 二分查找必須為有序 常見4種排序:冒泡排序、插入排序、歸並排序、以及快速排序
冒泡排序:空間復雜度為O(1) 時間復雜度O(n*n)
l1 = [1, 0, -1, 22, 33, 99, 76, 54] for j in range(0, len(l1)): for i in range(0, len(l1) - 1 - j): if l1[i] < l1[i + 1]: l1[i], l1[i + 1] = l1[i + 1], l1[i] print("排序后的列表:{}".format(l1))
插入排序空間復雜度是O(1) 最好的時間復雜度O(n) 最壞的時間復雜度O(n*n)
l2 = [1, 0, -1, 22, 33, 99, 76, 54] for i in range(1, len(l2)): for j in ran ge(i, 0, -1): if l2[j] < l2[j - 1]: l2[j], l2[j - 1] = l2[j - 1], l2[j] else: break print("排序后的列表:{}".format(l2))
歸並排序
歸並排序采用二分的迭代方式,復雜度是logn
合並兩列表
def merge(a, b): # a,b是待合並的兩個列表,兩個列表分別都是有序的,合並后才會有序 merged = [] i, j = 0, 0 while i < len(a) and j < len(b): if a[i] <= b[j]: merged.append(a[i]) i += 1 else: merged.append(b[j]) j += 1 merged.extend(a[i:]) merged.extend(b[j:]) return merged
# 遞歸操作
def merge_sort(c): if len(c) <= 1: return c mid = len(c) // 2 # 除法取整 a = merge_sort(c[:mid]) b = merge_sort(c[mid:]) return merge(a, b) c = [7, 9, 1, 0, 4, 3, 8, 2, 5, 4, 6] print(merge_sort(c))
快速排序法 穩定性較差
左小右大函數,獲取一個中值,左放小右放大函數
def partition(arr, low, high): # 參數:列表,列表的第一個索引0,最后一個索引值N """ 【左小右大函數】 實現結果:提取列表中的最后一個元素為被比較值,≤該元素的值放在左邊,>該元素的值放在右邊 實現過程:≤最后一個元素的所有元素依次放在左邊索引0~i的位置,然后將最后一個元素放在索引i的位置,實現結果 arr: 列表 low: arr的第一個索引:0 high: arr的最后一個索引:high return: i,即被比較值所在的索引位置 """ i = low # 最小元素索引 pivot = arr[high] # 最后一個元素,我們把列表中的所有元素同它比較 for j in range(low, high): # 從第一個索引到倒數第二個索引 if arr[j] <= pivot: # 從第一個元素到倒數第二個元素依次判斷是否≤最后一個元素 arr[i], arr[j] = arr[j], arr[i] # ≤最后一個元素的所有元素依次放在左邊索引0~i的位置 i = i + 1 arr[i], arr[high] = arr[high], arr[i] # 然后將最后一個元素放在索引i的位置,實現:該元素左邊的都比它小,右邊的都比它大的排序 return (i) # 返回該元素的索引位置 # 快速排序函數 def quickSort(arr, low, high): if low < high: # 如果列表有1個以上的元素 pi = partition(arr, low, high) # 獲取左小右大函數中的 被比較數所在的索引 quickSort(arr, low, pi - 1) # 反復循環,左排序 quickSort(arr, pi + 1, high) # 反復循環,右排序 arr = [10, 22, 78, 3, 12, 9, 1, 11, 33, 2] low = 0 high = len(arr) - 1 quickSort(arr, low, high) print(arr)
15.動態規划是一種運籌學方法,是在多輪決策過程中的最優方法
16.在一個數組 a = [1, 3, 4, 3, 4, 1, 3] 中,找到出現次數最多的那個數字。如果並列存在多個,隨機輸出一個。
a = [1, 3, 4, 3, 4, 1, 3] d1 = {} for i in a: d1[i] = d1.get(i, 0) + 1 print(d1) max_count = -1 max_value = -1 for i, v in d1.items(): if v > max_count: max_count = v max_value = i print("出現次數最多的數字:{} 次數為:{}".format(max_value, max_count))
17.這個問題是力扣的經典問題,two sums。給定一個整數數組 arr 和一個目標值 target,請你在該數組中找出加和等於目標值的兩個整數,並返回它們在原數組中的下標。
arr = [1, 2, 3, 4, 5, 6],target = 4。因為,arr[0] + arr[2] = 1 + 3 = 4 = target,則輸出 0,2。
l1 = [1, 2, 3, 4, 5, 6, 10] target = 10 d1 = {} for i, v in enumerate(l1): d1[target - v] = i print(d1) # {3: 0, 2: 1, 1: 2, 0: 3, -1: 4, -2: 5} result = [] for i in range(0, len(l1)): # 相減得到另一個數值 num1 = target - l1[i] num2 = target - num1 if num1 in d1 and num2 in d1: print(d1[num1], d1[num2]) break
18.遞歸 斐波那契數列是:0,1,1,2,3,5,8,13,21,34,55,89,144……。
你會發現,這個數列中元素的性質是,某個數等於它前面兩個數的和;
也就是 a[n+2] = a[n+1] + a[n]。至於起始兩個元素,則分別為 0 和 1。在這個數列中的數字,就被稱為斐波那契數。
【題目】寫一個函數,輸入 x,輸出斐波那契數列中第 x 位的元素。
例如,輸入 4,輸出 2;輸入 9,輸出 21。要求:需要用遞歸的方式來實現。
def fun(x): if x == 1: return 0 if x == 2: return 1 return fun(x - 1) + fun(x - 2) def fb_main(x): print(fun(x)) fb_main(4)
19.給定一個字符串,逐個翻轉字符串中的每個單詞。
例如,輸入:"This is a good example",
輸出:"example good a is This"。如果有多余的空格需要刪除。
棧 后進先出
l1 = "This is a good example".split(" ") print(l1) l2 = [] new_str = "" for i in l1: l2.append(i) print(l2) n = 0 while l2: if n == 0: new_str += l2.pop() else: new_str += " " + l2.pop() n += 1 print(new_str)
20.
【題目】 給定一個排序數組,你需要在原地刪除重復出現的元素,使得每個元素只出現一次,
返回移除后的數組和新的長度,你不需要考慮數組中超出新長度后面的元素。
要求:空間復雜度為 O(1),即不要使用額外的數組空間。
例如,給定數組 nums = [1,1,2],函數應該返回新的長度2,並且原數組 nums 的前兩個元素被修改為 1, 2。
又如,給定 nums = [0,0,1,1,1,2,2,3,3,4],函數應該返回新的長度 5,並且原數組 nums 的前五個元素被修改為 0, 1, 2, 3, 4。
nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4] index = 1 for i in range(len(nums) - 1): if nums[index] == nums[index - 1]: del nums[index] else: index += 1 print(len(nums)) print(nums)
21.例題 1:判斷數組中所有的數字是否只出現一次
arr = {1, 2, 3},輸出 YES。又如,arr = {1, 2, 1},輸出 NO。
arr = [1, 2, 3, 1] d1 = {} status = True for i in arr: if not d1.get(i): d1[i] = 1 status = True else: status = False break print(status)
22.找出數組中出現次數超過數組長度一半的元素你可以假設一定存在這個出現次數超過數組長度的一半的數字,即不用考慮輸入不合法的情況。
要求時間復雜度是 O(n),空間復雜度是 O(1)。例如,輸入 a = {1,2,1,1,2,4,1,5,1},輸出 1。
a = [1, 2, 2, 2, 2, 2, 1, 5, 1] result = a[0] times = 1 for i in range(len(a)): if a[i] != result: times -= 1 else: times += 1 if times == -1: times = 1 result = a[i] print(result)