1. 程式人生 > 其它 >echarts地圖展示

echarts地圖展示

常見演算法

演算法與資料結構是面試考察的重中之重,也是日後刷題時需要著重訓練的部分。

簡單的總結一下,大約有這些內容:

演算法 - Algorithms

1、排序演算法:快速排序、歸併排序、計數排序
2、搜尋演算法:回溯、遞迴、剪枝技巧
3、圖論:最短路、最小生成樹、網路流建模
4、動態規劃:揹包問題、最長子序列、計數問題
5、基礎技巧:分治、倍增、二分、貪心

資料結構 - Data Structures

1、陣列與連結串列:單/雙向連結串列、跳舞鏈
2、棧與對列
3、樹與圖:最近公共祖先、並查集
4、雜湊表
5、堆:大/小根堆、可並堆
6、字串:字典樹、字尾樹

遞迴與迭代的區別

遞迴(recursion):遞迴常被用來描述以自相似方法重複事物的過程,在數學和電腦科學中,指的是在函式定義中使用函式自身的方法。(A呼叫A)

迭代(iteration):重複反饋過程的活動,每一次迭代的結果會作為下一次迭代的初始值。(A重複呼叫B)

遞迴是一個樹結構,從字面可以其理解為重複“遞推”和“迴歸”的過程,當“遞推”到達底部時就會開始“迴歸”,其過程相當於樹的深度優先遍歷。

迭代是一個環結構,從初始狀態開始,每次迭代都遍歷這個環,並更新狀態,多次迭代直到到達結束狀態。

# 理論上遞迴和迭代時間複雜度方面是一樣的,但實際應用中(函式呼叫和函式呼叫堆疊的開銷)遞迴比迭代效率要低。

連結:https://www.jianshu.com/p/32bcc45efd32
來源:簡書

演算法的時間複雜度和空間複雜度

  • 時間複雜度和空間複雜度是用來評價演算法效率高低的2個標準。

  • 時間複雜度:就是說執行演算法需要消耗的時間長短,越快越好。比如你在電腦上開啟計算器,如果一個普通的運算要消耗1分鐘時間,那誰還會用它呢,還不如自己口算呢。

  • 空間複雜度:就是說執行當前演算法需要消耗的儲存空間大小,也是越少越好。本來計算機的儲存資源就是有限的,如果你的演算法總是需要耗費很大的儲存空間,這樣也會給機器帶來很大的負擔。

時間複雜度的計算

表示方法

我們一般用“大O符號表示法”來表示時間複雜度:T(n) = O(f(n)) n是影響複雜度變化的因子,f(n)是複雜度具體的演算法。

常見的時間複雜度量級

  • 常數階O(1)

  • 線性階O(n)

  • 對數階O(logN)

  • 線性對數階O(nlogN)

  • 平方階O(n²)

  • 立方階O(n³)

  • K次方階O(n^k)

  • 指數階(2^n)

常見的時間複雜度(按效率排序) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)

接下來再看一下不同的複雜度所對應的演算法型別。

常數階O(1)

int a = 1;
int b = 2;
int c = 3;

線性階O(n)

for(i = 1; i <= n; i++) {
j = i;
j++;
}

對數階O(logN)

int i = 1;
while(i < n) {
i = i * 2;
}

線性對數階O(nlogN)

for(m = 1; m < n; m++) {
i = 1;
while(i < n) {
i = i * 2;
}
}

平方階O(n²)

for(x = 1; i <= n; x++){
for(i = 1; i <= n; i++) {
j = i;
j++;
}
}

空間複雜度計算

空間複雜度 O(1)

如果演算法執行所需要的臨時空間不隨著某個變數n的大小而變化,即此演算法空間複雜度為一個常量,可表示為 O(1)。

int i = 1;
int j = 2;
++i;
j++;
int m = i + j;

程式碼中的 i、j、m 所分配的空間都不隨著處理資料量變化,因此它的空間複雜度 S(n) = O(1)。

空間複雜度 O(n)

int[] m = new int[n]
for(i = 1; i <= n; ++i) {
j = i;
j++;
}

這段程式碼中,第一行new了一個數組出來,這個資料佔用的大小為n,後面雖然有迴圈,但沒有再分配新的空間,因此,這段程式碼的空間複雜度主要看第一行即可,即 S(n) = O(n)。

十大經典排序演算法

# 氣泡排序
比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。
對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。這步做完後,最後的元素會是最大的數。
針對所有的元素重複以上的步驟,除了最後一個。
持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。
import sys
sys.setrecursionlimit(1000000)
## 氣泡排序 (******)
### 時間複雜度:O(n^2)
def Bubble_sort(li):
for i in range(len(li)-1):
for j in range(len(li)-1-i):
if li[j] > li[j+1]:
li[j], li[j+1] = li[j+1], li[j
return li


## 選擇排序
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。
重複第二步,直到所有元素均排序完畢。
#### 時間複雜度:O(n^2)
def select_sort(li):
for i in range(len(li)):
minLoc = i ###i = 0
for j in range(i+1, len(li)):
if li[j] < li[minLoc]:
li[j], li[minLoc] = li[minLoc], li[j]
return li


##### 插入排序(打撲克牌)
將第一待排序序列第一個元素看做一個有序序列,把第二個元素到最後一個元素當成是未排序序列。
從頭到尾依次掃描未排序序列,將掃描到的每個元素插入有序序列的適當位置。(如果待插入的元素與有序序列中的某個元素相等,則將待插入元素插入到相等元素的後面。)
#### 時間複雜度: O(n^2)
def insert_sort(li):
for i in range(1, len(li)):
tmp = li[i]
j = i - 1
while j >=0 and li[j] > tmp:
li[j+1] = li[j]
j = j - 1
li[j+1] = tmp


## 快速排序
1、從數列中挑出一個元素,稱為 "基準"(pivot);
2、重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割槽退出之後,該基準就處於數列的中間位置。這個稱為分割槽(partition)操作;
3、遞迴地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序;

def partition(li, left, right):
tmp = li[left]
while left < right:
while left < right and li[right] >= tmp:
right = right - 1
li[left] = li[right]
while left < right and li[left] <= tmp:
left = left + 1
li[right] = li[left]
li[left] = tmp

return left

## 時間複雜度:O(nlogn)
def quick_sort(li, left, right):
if left < right:
mid = partition(li, left, right)
quick_sort(li, left, mid-1)
quick_sort(li, mid+1, right)
return li


# 計算時間複雜度
import time,random
li = [random.randint(1,100) for _ in range(100000)]
start = time.time()
quick_sort(li, 0, len(li)-1)
cost = time.time() - start
print('quick_sort:%s' % (cost))

import time,random
li = [random.randint(1,100) for _ in range(100000)]
start = time.time()
Bubble_sort(li)
cost = time.time() - start
print('bubble_sort:%s' % (cost))

import time,random
li = [random.randint(1,100) for _ in range(100000)]
start = time.time()
insert_sort(li)
cost = time.time() - start
print('insert_sort:%s' % (cost))

演算法-力扣(LeetCode)

連結串列反轉

反轉一個單鏈表:

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
進階:
你可以迭代或遞迴地反轉連結串列。你能否用兩種方法解決這道題?
# 雙向指標迭代
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
# 申請兩個節點,pre和 cur,pre指向None
pre = None
cur = head
# 遍歷連結串列,while迴圈裡面的內容其實可以寫成一行
# 這裡只做演示,就不搞那麼騷氣的寫法了
while cur:
# 記錄當前節點的下一個節點
tmp = cur.next
# 然後將當前節點指向pre
cur.next = pre
# pre和cur節點都前進一位
pre = cur
cur = tmp
return pre

# 2、遞迴解法
class Solution(object):
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
# 遞迴終止條件是當前為空,或者下一個節點為空
if(head==None or head.next==None):
return head
# 這裡的cur就是最後一個節點
cur = self.reverseList(head.next)
# 這裡請配合動畫演示理解
# 如果連結串列是 1->2->3->4->5,那麼此時的cur就是5
# 而head是4,head的下一個是5,下下一個是空
# 所以head.next.next 就是5->4
head.next.next = head
# 防止連結串列迴圈,需要將head.next設定為空
head.next = None
# 每層遞迴函式都返回cur,也就是最後一個節點
return cur

來源:力扣(LeetCode)

反轉字串

編寫一個函式,其作用是將輸入的字串反轉過來。輸入字串以字元陣列 char[] 的形式給出。

示例
輸入:["h","e","l","l","o"]
輸出:["o","l","l","e","h"]

簡單實現
class Solution:
def reverseString(self, s):
s.reverse()

# 1、遞迴實現
class Solution:
def reverseString(self, s):
def helper(left, right):
if left < right:
s[left], s[right] = s[right], s[left]
helper(left + 1, right - 1)

helper(0, len(s) - 1)

# 2、一步實現
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
# one step by python
s[:] = s[::-1]


來源:力扣(LeetCode)

二叉樹的最大深度

給定一個二叉樹,找出其最大深度。

二叉樹的深度為根節點到最遠葉子節點的最長路徑上的節點數。

說明: 葉子節點是指沒有子節點的節點。

示例: 給定二叉樹 [3,9,20,null,null,15,7]

  3
/ \
9 20
/ \
15 7

方法:遞迴

直觀的方法是通過遞迴來解決問題。在這裡,我們演示了 DFS(深度優先搜尋)策略的示例。

class Solution:
def maxDepth(self,root): # root子節點
if root is None:
return 0
else:
left_height = self.maxDepth(root.left)
right_height = self.maxDepth(root.right)
return max(left_height,right_height)+1 #左右對比 基於子節點+1

整數反轉

給出一個 32 位的有符號整數,你需要將這個整數中每位上的數字進行反轉。

示例:

輸入: 123
輸出: 321
方法:字串的反轉,記錄符號位。
class Solution:
def reverse(self, x: int) -> int:
flag = -1 if x < 0 else 1
res = flag * int(str(abs(x))[::-1])
return res if (-2**31)<=res<=(2**31-1) else 0

作者:powcai

刪除排序中陣列中的重複項

給定一個排序陣列,你需要在 原地 刪除重複出現的元素,使得每個元素只出現一次,返回移除後陣列的新長度。

不要使用額外的陣列空間,你必須在 原地 修改輸入陣列 並在使用 O(1) 額外空間的條件下完成。

示例:

給定 nums = [0,0,1,1,1,2,2,3,3,4],

函式應該返回新的長度 5, 並且原陣列 nums 的前五個元素被修改為 0, 1, 2, 3, 4
你不需要考慮陣列中超出新長度後面的元素。

思路:

用兩個指標,指向第一個和第二個元素,如果他們相等,刪除第二個元素。指標還指向原來的位置,繼續比較。不等的話,兩個指標位置都加一。遍歷結束即可。

解題思路 題意:刪除有序陣列重複項,把去重後的數字放在輸入陣列的前面 n 個位置,返回 n.

看到題目標題的第一反應,當然是用 set !set 就是為了實現去重的。但是題目要求我們進行原地操作,並且時間複雜度是 O(1)O(1),因此就不能開闢另外的空間。

雙指標 題目需要我們把去重後的結果儲存到原本的陣列中,所以想到必須有一個指標指向當前需要把結果放在哪個位置。還要一個指標指向當前應該放到哪個元素。

慢指標作為基準,快指標用於尋找與慢指標不同的元素。 如果快指標和慢指標指向的元素不等,則把快指標指向的元素放到慢指標的下一個位置。 慢指標右移,把新的元素作為基準。

作者:fuxuemingzhu 連結:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/solution/fu-xue-ming-zhu-shuang-zhi-zhen-jie-fa-s-hp71/

class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
pre,cur=0,1 # 指標初始指向數
while cur<len(nums):
if nums[pre]==nums[cur]:
nums.pop(cur) # 取出重複數
else:
pre,cur=pre+1,cur+1 # 交換並加一往後
return len(nums)# 陣列的長度

# 第二種解法
class Solution(object):
def removeDuplicates(self, nums):
N = len(nums)
left = 0
for right in range(1, N):
if nums[right] != nums[left]:
left += 1
nums[left] = nums[right]
return left + 1

存在重複元素

給定一個整數陣列,判斷是否存在重複元素。

如果任意一值在陣列中出現至少兩次,函式返回 true 。如果陣列中每個元素都不相同,則返回 false

示例:

輸入: [1,2,3,1]
輸出: true

輸入: [1,2,3,4]
輸出: false

集合判斷法:利用Python獨有的資料類集合特性。 用nums = list(set(nums))就可以輕鬆排除了

class Solution(object):
def containsDuplicat(self,nums:list[int]) ->bool:
if len(self(nums) == len(nums))
return Flase
else:
return True

只出現一次的數字

給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。

示例:

輸入: [4,1,2,1,2]
輸出: 4

思路:通過數學的解法

先通過set把資料去重,然後把所有的值相加*2去減之前的值,剩下的值就是答案

1、數學
class Solution(object):
def singleNumber(self, nums):
return 2 * sum(set(nums)) - sum(nums)

2、counter函式
from collections import Counter
class Solution:
def singleNumber(self, nums: List[int]) -> int:
datas = Counter(nums)
for each in datas:
if datas[each] == 1: return each

兩數之和

給定一個整數陣列 nums 和一個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。

你可以假設每種輸入只會對應一個答案。但是,陣列中同一個元素不能使用兩遍。

示例:

給定 nums = [2, 7, 11, 15], target = 9
因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
#思路:兩層for迴圈,取出值進行相加,判斷是否等於target
用兩個for迴圈解決,注意,第二個for迴圈的值得是第一個的值+1
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
for j in range(i+1,len(nums)):# 基於第一次之上
if nums[i] + nums[j] == target:
return [i,j]

加一

示例:

輸入: [1,2,3]
輸出: [1,2,4]
解釋: 輸入陣列表示數字 123
class Solution(object):
def plusOne(self, digits):
"""
:type digits: List[int]
:rtype: List[int]
"""
digits_str=''
for i in range(len(digits)):
digits_str+=str(digits[i])
digits_num=int(digits_str)+1
digits_list=list(str(digits_num))
return digits_list

小猿取經-部落格

查詢list中最大的數

  • 思路:遍歷整個列表 獲得對應的元素,元素與元素之間進行比較,記錄最大值


list0 = [12,45,-2,6,-9,78,99,154]
1、max內建函式
res=max(list0)
print(res)

2、for遍歷比較
max_item = list0[0]
for item in range(0,len(list0)):
if max_item < list0[item]:
max_item=list0[item]
print(max_item)

3、for迴圈
for item in list0:
if max_item <item:
max_item = item
print(max_item)

兩個列表中找出相同和不相同的元素

1、set集合去重,取交集
list1 = [1,2,3]
list2 = [3,4,5]
set1 = set(list1)
set2 = set(list2)
print(set1&amp;set2)
print(set1^set2)

2、列表推導式
list1 = [1,3,65,78]
list2 = [1,3,8,58,78,23]
c = [x for x in list1 if x in list2]
b = [y for y in (list1+list2) if y not in c]
print(c)
print(b)

3、for迴圈
list1 = [1,3,5,8,9]
list2 = [2,3,5,12,45]
list3 = []
list4 = []
for i in list1:
for j in list2:
if i == j:
list3.append(i)
for b in (list1+list2):
if b not in list3:
list4.append(b)

print(list3)
print(list4)

列表去重

列表去重的幾種方式
1. for 迴圈去重
list1 = [2, 1, 3, 6, 2, 1]
temp = []
for i in list1:
if not i in temp:
temp.append(i)

2. 列表推導式去重
list1 = [2, 1, 3, 6, 2, 1]
temp = []
[temp.append(i) for i in list1 if i not in temp]
print(temp)

3. set去重
list1 = [2, 1, 3, 6, 2, 1]
temp = list(set(list1))
print(temp)
set去重保持原來的順序,參考5,6
4. 使用字典fromkeys()的方法來去重
原理是: 字典的key是不能重複的
list1 = [2, 1, 3, 6, 2, 1]
temp = {}.fromkeys(list1)
print(temp)
print(temp.keys())

5 . 使用sort + set去重
list1 = [2, 1, 3, 6, 2, 1]
list2 = list(set(list1))
list2.sort(key=list1.index)
print(list2)

6. 使用sorted+ set函式去重
list1 = [2, 1, 3, 6, 2, 1]
temp = sorted(set(list1), key=list1.index)
print(temp)
刪除列表中的重複項
list1 = [2, 1, 3, 6, 2, 1]
temp = [item for item in list1 if list1.count(item) == 1]
print(temp)

list1 = [2, 1, 3, 6, 2, 1]
temp = list(filter(lambda x:list1.count(x) ==1, list1))
print(temp)

9*9乘法表

for row in range(1, 10):
for col in range(1, row+1):
print('{}*{}={}'.format(col, row, col * row), end='\t')
print()

# 左下三角九九乘法表
for row in range(1,10): #列印行
for col in range(1,row+1): #列印列
print("{0}*{1}={2:2d}".format(row,col,row*col),end=" ")
#這裡是用format函式進行格式化輸出控制,{2:2d}是給{2}這個位置兩倍的空間,對齊乘法表
#同時end是print函式內建方法,設定end=""print就不會進行換行操作
print(" ") #這裡是用print的特性,進行換行輸出
————————————————

# author : Eric
a = 1
sum = 0
for i in range(1,10):
for j in range(1,i+1):
sum = i*j
print("%dx%d=%d"%(i,j,sum),end=" ")
print("")
————————————————
# 一行實現
print('n'.join([' '.join(['%s*%s=%-2s' % (y, x, x*y) for y in range(1, x+1)]) for x in range(1, 10)]))

完數

完數的定義:

什麼是因子? 假如整數n除以m,結果是無餘數的整數 n % m == 0,那麼我們稱m就是n的因子.需要注意的是,唯有被除數,除數,商皆為整數,餘數為零時,此關係才成立.

什麼是“完數”: 一個數如果恰好等於它的因子之和,這個數就稱為”完數”。例如6=1+2+3.

如一個數恰好等於它的因子之和,這個數就稱為“完數”。

如:6=1+2+3,請實現1000內的所有完數。

for i in range(2,1001):  # 遍歷1000以內的所有數,從2 開始
s = i # 把取出的數賦值給另一個變數s,用於與所有因子作差,若果減去所有的因子後結果為0,這個數即為完數。
for j in range(1,i): # 查詢因子
if i % j == 0: # 找出因子
s -= j # 與因子作差
if s == 0: # 判斷是否是完數
print(i) # 列印完數

# 優化
for i in range(2,1001):
k = [] # 用於收集一個數的所有因子
n = -1 #
s = i
for j in range(1,i):
if i % j == 0:
n += 1
s -= j
k.append(j) # 收集所有因子

if s == 0:
print(i,":") # 列印完數
for j in range(n): # 遍歷完數的所有因子
print(str(k[j]),end='+ ') # 打印出所有的因子
print(k[n]) # 列印

# 方法2
l = [ ]
for n in range (1,10000):
for a in range (1,n):
if n%a ==0:
l.append(a)
if sum(l)==n:
print (l)
print (n)
l = []
————————————————

字串的排列組合

給你一個字串,比如‘abc’,請打印出該字串的所有排列組合:

以‘abc’為例,輸出的結果應該是:'abc', 'acb', 'bac', 'bca', 'cab', 'cba'

請用python程式碼編碼實現:

def fun1(s=''):
if len(s) <= 1:
return [s]
else:
sl = []
for i in range(len(s)):
for j in fun1(s[0:i] + s[i + 1:]):
sl.append(s[i] + j)
return sl

def main():
a = fun1('abc')
print(a)

二分法查詢

def bin_search_rec(data_set, value, low, high):
if low <= high:
mid = (low + high) // 2
if data_set[mid] == value:
return mid
elif data_set[mid] > value:
return bin_search_rec(data_set, value, low, mid - 1)
else:
return bin_search_rec(data_set, value, mid + 1, high)
else:return


2、遞迴實現
def search(list, key):
left = 0 # 左邊界
right = len(list) - 1 # 右邊界
while left <= right:
mid = (left + right) // 2 # 取得中間索引
if key > list[mid]:
left = mid + 1
elif key < list[mid]:
right = mid - 1
else:
return mid
else:
return -1

list = [2, 5, 13, 21, 26, 33, 37]
print(search(list, 5))
————————————————
原文連結:https://blog.csdn.net/weixin_42068613/java/article/details/83187817

3
def binary_search(list, item):
low = 0 # (以下2行)low和high用於跟蹤要在其中查詢的列表部分
high = len(list) - 1
n = 0
while low <= high: # 只要範圍沒有縮小到只包含一個元素
n += 1
mid_1 = (low + high)/2 # 就檢查中間的元素
mid = int(mid_1)
guess = list[mid]
if guess == item: # 找到了元素
return "要猜的數字在列表中的索引號為%d,共猜了%d次"%(mid,n)
if guess > item: # 猜的數字大了
high = mid -1
else: # 猜的數字小了
low = mid + 1
return "沒有這個數" # 沒有指定的元素


my_list = []
for i in range(1, 201):
my_list.append(i)
print(my_list)

print(binary_search(my_list, 100))
print(binary_search(my_list, 111))

#執行結果

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200]
要猜的數字在列表中的索引號為99,共猜了1次
要猜的數字在列表中的索引號為110,共猜了8次

Process finished with exit code 0

兩個陣列的交集 II

簡單地利用陣列操作,一次迴圈就能找出結果。

class Solution:
def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
res = []
for i, num in enumerate(nums1):
if num in nums2:
res.append(num)
nums2.pop(nums2.index(num))
return res

來源:力扣(LeetCode)

合併兩個有序的連結串列

將兩個升序連結串列合併為一個新的升序連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。

示例:

輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if not l1: return l2 # 終止條件,直到兩個連結串列都空
if not l2: return l1
if l1.val <= l2.val: # 遞迴呼叫
l1.next = self.mergeTwoLists(l1.next,l2)
return l1
else:
l2.next = self.mergeTwoLists(l1,l2.next)
return l2

移除元素

給你一個數組 nums 和一個值 val,你需要 原地 移除所有數值等於 val 的元素,並返回移除後陣列的新長度。

不要使用額外的陣列空間,你必須僅使用 O(1) 額外空間並 原地 修改輸入陣列。

元素的順序可以改變。你不需要考慮陣列中超出新長度後面的元素。

思路 有的同學可能說了,多餘的元素,刪掉不就得了。

要知道陣列的元素在記憶體地址中是連續的,不能單獨刪除陣列中的某個元素,只能覆蓋。

暴力解法 這個題目暴力的解法就是兩層for迴圈,一個for迴圈遍歷陣列元素 ,第二個for迴圈更新陣列。

刪除過程如下:

很明顯暴力解法的時間複雜度是O(n^2),這道題目暴力解法在leetcode上是可以過的。

作者:carlsun-2 連結:https://leetcode-cn.com/problems/remove-element/solution/dai-ma-sui-xiang-lu-27-yi-chu-yuan-su-ba-du7k/

class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
i,n = 0,len(nums)
for j in range(n):
if nums[j] != val:
nums[i] = nums[j]
i += 1
return i

作者:carlsun-2
連結:https://leetcode-cn.com/problems/remove-element/solution/dai-ma-sui-xiang-lu-27-yi-chu-yuan-su-ba-du7k/
來源:力扣(LeetCode)

搜尋插入位置

給定一個排序陣列和一個目標值,在陣列中找到目標值,並返回其索引。如果目標值不存在於陣列中,返回它將會被按順序插入的位置。

你可以假設陣列中無重複元素。

示例 1:

輸入: [1,3,5,6], 5
輸出: 2

示例 2:

輸入: [1,3,5,6], 2
輸出: 1

解題思路 思路: 1.二分法查詢 2.查完後nums[mid]肯定是和target最接近的,所以只需要比較它和target的大小來確定target的位置 注意: 返回座標那裡容易出錯,注意nums[mid]大於target時,nums[mid]後移,target佔據nums[mid]原來的位置,所以返回的應該是mid

作者:FvHk1D0CCe 連結:https://leetcode-cn.com/problems/search-insert-position/solution/python-er-fen-fa-by-fvhk1d0cce-paje/

class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
low,high = 0,len(nums)-1
while low <= high:
mid = (low + high) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
low = mid + 1
elif nums[mid] > target:
high = mid -1

#print(mid,nums[mid])

if nums[mid] > target: #注意,是target替換nums[mid]的位置
return mid

return mid + 1


作者:FvHk1D0CCe
連結:https://leetcode-cn.com/problems/search-insert-position/solution/python-er-fen-fa-by-fvhk1d0cce-paje/
來源:力扣(LeetCode)

最後一個單詞的長度

給你一個字串 s,由若干單片語成,單詞之間用空格隔開。返回字串中最後一個單詞的長度。如果不存在最後一個單詞,請返回 0 。

單詞 是指僅由字母組成、不包含任何空格字元的最大子字串。

來源:力扣(LeetCode) 連結:https://leetcode-cn.com/problems/length-of-last-word示例 1:

輸入:s = "Hello World"
輸出:5

示例 2:

輸入:s = " "
輸出:0
class Solution:
def lengthOfLastWord(self, s: str) -> int:
x = s.split(' ')
for i in x[::-1]:
if i != '':
return len(i)
return 0

刪除排序連結串列中的重複元素

存在一個按升序排列的連結串列,給你這個連結串列的頭位元組點head,請刪除所有重複的元素,使每個元素只出現一次。

返回同樣按升序排列的結果連結串列。

示例 1:

輸入:head = [1,1,2]
輸出:[1,2]

解題思路 題意:在一個有序連結串列中,連結串列中的值重複的節點僅保留一個。

重點:有序連結串列,所以,一個節點的值出現不止一次,那麼它們必相鄰。

下面使用兩種方法 :遞迴,迭代。其中迭代又分為兩種方法。

作者:fuxuemingzhu 連結:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/solution/fu-xue-ming-zhu-di-gui-die-dai-4-chong-d-t3bp/

class Solution(object):
def deleteDuplicates(self, head):
if not head: return None
prev, cur = head, head.next
while cur:
if cur.val == prev.val:
prev.next = cur.next
else:
prev = cur
cur = cur.next
return head


作者:fuxuemingzhu
連結:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/solution/fu-xue-ming-zhu-di-gui-die-dai-4-chong-d-t3bp/
  • 時間複雜度:O(N)O(N),對連結串列每個節點遍歷了一次;

  • 空間複雜度:O(1)O(1),只使用了常量的空間。

根據字元出現的頻率排序

給定一個字串,請將字串裡的字元按照出現的頻率降序排列

示例 1:

輸入: "tree"

輸出: "eert"

解釋: 'e'出現兩次,'r'和't'都只出現一次。 因此'e'必須出現在'r'和't'之前。此外,"eetr"也是一個有效的答案。

思路一:直接排序 首先遍歷字串,用雜湊表記錄每個字元出現的次數 然後獲取雜湊表中的鍵值對,根據value進行降序排列 遍歷排列後的結果,將字元根據其出現次數加到最終結果res中去

作者:edelweisskoko 連結:https://leetcode-cn.com/problems/sort-characters-by-frequency/solution/451-gen-ju-zi-fu-chu-xian-pin-lu-pai-xu-xup3z/ 來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

class Solution:
def frequencySort(self, s: str) -> str:
count = {}
for c in s:
count[c] = count.get(c, 0) + 1
items = [(-val, key) for key, val in count.items()]
res = ""
for val, key in sorted(items):
res += key * (-val)
return res

作者:edelweisskoko
連結:https://leetcode-cn.com/problems/sort-characters-by-frequency/solution/451-gen-ju-zi-fu-chu-xian-pin-lu-pai-xu-xup3z/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

劍指 Offer 58 - I. 翻轉單詞順序

輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字元的順序不變。為簡單起見,標點符號和普通字母一樣處理。例如輸入字串"I am a student. ",則輸出"student. a am I"。

例子:

示例 1:

輸入: "the sky is blue" 輸出: "blue is sky the" 示例 2:

輸入: " hello world! " 輸出: "world! hello" 解釋: 輸入字串可以在前面或者後面包含多餘的空格,但是反轉後的字元不能包括。

來源:力扣(LeetCode) 連結:https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof示例 1:

class Solution:
def reverseWords(self, s: str) -> str:
s = s.strip() # 刪除首尾空格
i = j = len(s) - 1
res = []
while i >= 0:
while i >= 0 and s[i] != ' ': i -= 1 # 搜尋首個空格
res.append(s[i + 1: j + 1]) # 新增單詞
while s[i] == ' ': i -= 1 # 跳過單詞間空格
j = i # j 指向下個單詞的尾字元
return ' '.join(res) # 拼接並返回

作者:jyd
連結:https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof/solution/mian-shi-ti-58-i-fan-zhuan-dan-ci-shun-xu-shuang-z/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

劍指 Offer 38. 字串的排列

輸入一個字串,打印出該字串中字元的所有排列。

你可以以任意順序返回這個字串陣列,但裡面不能有重複元素。

示例:

輸入:s = "abc" 輸出:["abc","acb","bac","bca","cab","cba"]

限制:

1 <= s 的長度 <= 8

來源:力扣(LeetCode) 連結:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof 著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。

class Solution:
def permutation(self, s: str) -> List[str]:
c, res = list(s), []
def dfs(x):
if x == len(c) - 1:
res.append(''.join(c)) # 新增排列方案
return
dic = set()
for i in range(x, len(c)):
if c[i] in dic: continue # 重複,因此剪枝
dic.add(c[i])
c[i], c[x] = c[x], c[i] # 交換,將 c[i] 固定在第 x 位
dfs(x + 1) # 開啟固定第 x + 1 位字元
c[i], c[x] = c[x], c[i] # 恢復交換
dfs(0)
return res

作者:jyd
連結:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/solution/mian-shi-ti-38-zi-fu-chuan-de-pai-lie-hui-su-fa-by/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。