六十五、Leetcode數組系列(上篇)

@Author:Runsen

@Date:2020/6/5

作者介紹:Runsen目前大三下學期,專業化學工程與工藝,大學沉迷日語,Python, Java和一系列數據分析軟件。導致翹課嚴重,專業排名中下。.在大學60%的時間,都在CSDN。決定今天比昨天要更加努力。

從大一寫Python文章,到現在其都有上百篇,現在到了六十五,今日主要寫的是數據結構中的數組 Array

數組 Array

在平時使用最多的恐怕就是數組了吧,它是使用最廣泛的一種數據結構,它是相同數據類型(可以是基本類型也可以是自定義類型)的元素按一定順序排列的集合,它們在內存中按照這個先後順序連續存放在一起。有一維數組,二維數組,多維數組。 通俗的理解就是我們一般把一羣羊或者一羣牛放在一個圈裏面,這個圈就相當於數組容器,每一個羊相當於一個元素。

  • 查詢 Access: O(1)
  • 插入 Insert: 平均 O(n)
  • 刪除 Delete: 平均 O(n)

優點:

  1. 有序
  2. 可以進行下標操作,隨機訪問效率很高,時間複雜度可以達到O(1)
  3. 添加速度快
    缺點:
  4. 刪除,刪除第一個,刪除最後一個,選擇一個位置刪除這些都不方便操作
  5. 在數組起始位置處,插入數據和刪除數據效率低,時間複雜度平均 O(n)
  6. 內存空間要求高,必須有足夠的連續的內存空間

題目

這是爭哥的春節天天練,那時我太菜了。 沒搞。

三數之和

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]
#]
注意:答案中不可以包含重複的三元組。

三數之和就當兩數來幹,兩次遍歷,判斷第三個數在不在,就是時間複雜度O(n2)O(n^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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章