@Author:Runsen
@Date:2020/6/5
作者介紹:Runsen目前大三下學期,專業化學工程與工藝,大學沉迷日語,Python, Java和一系列數據分析軟件。導致翹課嚴重,專業排名中下。.在大學60%的時間,都在CSDN。決定今天比昨天要更加努力。
從大一寫Python文章,到現在其都有上百篇,現在到了六十五,今日主要寫的是數據結構中的數組 Array
數組 Array
在平時使用最多的恐怕就是數組了吧,它是使用最廣泛的一種數據結構,它是相同數據類型(可以是基本類型也可以是自定義類型)的元素按一定順序排列的集合,它們在內存中按照這個先後順序連續存放在一起。有一維數組,二維數組,多維數組。 通俗的理解就是我們一般把一羣羊或者一羣牛放在一個圈裏面,這個圈就相當於數組容器,每一個羊相當於一個元素。
- 查詢 Access: O(1)
- 插入 Insert: 平均 O(n)
- 刪除 Delete: 平均 O(n)
優點:
- 有序
- 可以進行下標操作,隨機訪問效率很高,時間複雜度可以達到O(1)
- 添加速度快
缺點: - 刪除,刪除第一個,刪除最後一個,選擇一個位置刪除這些都不方便操作
- 在數組起始位置處,插入數據和刪除數據效率低,時間複雜度平均 O(n)
- 內存空間要求高,必須有足夠的連續的內存空間
題目
這是爭哥的春節天天練,那時我太菜了。 沒搞。
三數之和
leetcode 三數之和,這是Leecode的第十五道題目。
https://leetcode-cn.com/problems/3sum/Majority
#給你一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?請你找出所有滿足條件且不重複的三元組。
#
# 注意:答案中不可以包含重複的三元組。
# 示例:
#
# 給定數組 nums = [-1, 0, 1, 2, -1, -4],
#
#滿足要求的三元組集合爲:
#[
# [-1, 0, 1],
# [-1, -1, 2]
#]
注意:答案中不可以包含重複的三元組。
三數之和就當兩數來幹,兩次遍歷,判斷第三個數在不在,就是時間複雜度。
def threeSum(nums):
result = []
nums.sort()
a = len(nums)
for i in range(a - 1):
for j in range(i + 1, a):
if -(nums[i] + nums[j]) in nums[j + 1:]:
array = [nums[i], nums[j], -(nums[i] + nums[j])]
if array not in result:
result.append(array)
return result
nums = [-1, 0, 1, 2, -1, -4]
print(threeSum([-1, 0, 1, 2, -1, -4]))
但是會超出時間,其實三數之和用的不是這樣子的,做法是雙指針。
我們可以先把這個數組進行從小到大的排序,因爲排序的複雜度$O(NlogN) n^2$的,排序後,你會發現,由於三數之和是等於零,那麼如果當前這個元素是大於零的話,而且,這個數組是按照從小到大排序的話,那麼當前這個元素作爲起點的集合是爲空的,因爲後面的元素都是比這個元素大的元素,是不可相加等於零。
由此我們可以節省一些複雜度,當然,我們進行排序的時候,是要經歷一些複雜度的,但這遠遠小於n的平方,所以我們這個做法還是比較快的。
然後我們在確定起點之後,通過雙指針去遍歷其他兩個元素。
看不懂看下面的圖片
def threeSum(nums):
nums.sort()
# [-4, -1, -1, 0, 1, 2]
res_list = []
# 頭部循環查找
for i in range(len(nums)):
if i == 0 or nums[i] > nums[i - 1]:
# 最左端
l = i + 1
# 最右端
r = len(nums) - 1
while l < r: # 正在查找
three_sum = nums[i] + nums[l] + nums[r]
if three_sum == 0:
res_list.append([nums[i], nums[l], nums[r]])
l += 1 # 右移一位
r -= 1 # 左移一位
while l < r and nums[l] == nums[l - 1]:
# 從左往右,相同數值直接跳過
l += 1
while r > l and nums[r] == nums[r + 1]:
# 從右往左,相同數值直接跳過
r -= 1
elif three_sum > 0:
# 大於零,右邊數值大,左移
r -= 1
else:
# 小於零,左邊數值小,右移
l += 1
return res_list
求衆數
題目來源於 LeetCode 上第 169 號問題:求衆數(求數組中超過一半的數字)。題目難度爲 Easy
#給定一個大小爲 n 的數組,找到其中的多數元素。多數元素是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素。
#
# 你可以假設數組是非空的,並且給定的數組總是存在多數元素。
# 示例 1:
#
# 輸入: [3,2,3]
#輸出: 3
#
# 示例 2:
#
# 輸入: [2,2,1,1,1,2,2]
#輸出: 2
#
# Related Topics 位運算 數組 分治算法
方法:遍歷整個數組,出現次數比其他數字加起來出現次數還多的元素返回。
最簡單的方法就排序,取出 ⌊ n/2 ⌋ 的元素
def majorityElement(self, nums):
nums.sort()
return nums[int(len(nums) / 2)]
然後一種計數的方法,用字典來儲存起來。
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
num = {}
for i in nums:
if i in num:
num[i] += 1
else:
num[i] = 1
return max(num.items(),key = lambda x:x[1])[0]
還可以直接使用collections
import collections
def majorityElement(self, nums):
return collections.Counter(nums).most_common()[0][0]
求缺失的第一個正數
題目來源於 LeetCode 上第 41 號問題:求缺失的第一個正數
中文版:https://leetcode-cn.com/problems/first-missing-positive/
#給你一個未排序的整數數組,請你找出其中沒有出現的最小的正整數。
# 示例 1:
#
# 輸入: [1,2,0]
#輸出: 3
#
# 示例 2:
#
# 輸入: [3,4,-1,1]
#輸出: 2
#
# 示例 3:
#
# 輸入: [7,8,9,11,12]
#輸出: 1
# 提示:
#
# 你的算法的時間複雜度應爲O(n),並且只能使用常數級別的額外空間。
# Related Topics 數組
這道題的難度在於時間和空間的限制。
若沒有時間的限制,可以直接排序後遍歷查找。
若沒有空間的限制,可以創建輔助空間後記錄。
最簡單的做法就是出現就+1。
題目的要求是找到沒有出現過的最小正整數,最小的正整數是1,如果1沒出現過,那麼答案就是1,否則,自增1,繼續看2是否在列表中。
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
res = 1
while res in nums:
res += 1
return res
把數組裏 所有>=1的元素 放在它該放的位置!
哪裏是該放的位置? :放在值減一的位置
例如,數組[4 1 5 -1 2]。
4應該放在下標爲3(4-1)的位置,交換後
[-1 1 5 4 2]
1應該放在下標爲0(1-0)的位置,交換後
[1 -1 5 4 2]
以此類推
[1 -1 2 4 5]
[1 2 -1 4 5]
最後遍歷,第三個位置(下標爲2) 本來應放3,但此時是-1,所以返回3,答案就是3。
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
n=len(nums)
res_list=[-1] * n
# print(res_list)
for i in range(n):
# 要判斷這個數是否可以被交換
if nums[i] >=1 and nums[i]<=n:
res_list[nums[i]-1] =nums[i]
# print(res_list)
for i in range(n):
if res_list[i] != i+1:
return i+1
return n+1