LeetCode刷題第三周【數組(簡單)】

2021-01-14 葉子昊的筆記

註:本文部分內容及所有題目源自於Leetcode網站[1],僅供本人自己學習與作為練習筆記使用。(所有引用都已標註原網址,見文章或附錄。若存在版權侵犯,請聯繫本人刪除侵權內容。)

日期Oct.28 - Nov.03 2020(每日一題)

Ps:本周我們接著上一周繼續刷數組,難度依舊是簡單,題目不再按順序,而是隨機挑選,下周開始會加深難度。隨著學校的開課,我會將平時上課的內容和筆記也整理成MK的格式上傳。這學期課程主要有圖形學(Computer Graphics)等等的專業課,具體的請看話題列表,每門課我將會開設一個專門的話題。內容會跟隨課程,逐步上傳,包括自學的一些額外筆記。

數組是目前Leetcode上題量最多的一個模塊了。刷題前我們來了解一下什麼是數組:數組是在程序設計中,為了處理方便, 把具有相同類型的若干元素按有序的形式組織起來的一種形式。首先,數組會利用 索引 來記錄每個元素在數組中的位置,且在大多數程式語言中,索引是從 0 算起的。我們可以根據數組中的索引,快速訪問數組中的元素。事實上,這裡的索引其實就是內存地址。其次,作為線性表的實現方式之一,數組中的元素在內存中是 連續 存儲的,且每個元素佔用相同大小的內存。例如對於一個數組 ['oranges', 'apples', 'bananas', 'pears', 'tomatoes'],為了方便起見,我們假設每個元素只佔用一個字節,它的索引與內存地址的關係如下圖所示。在具體的程式語言中,數組的實現方式具有一定差別。比如 C++ 和 Java 中,數組中的元素類型必須保持一致,而 Python 中則可以不同。相比之下,Python 中的數組(稱為 list)具有更多的高級功能。

以上文字描述均來自 LeetCode數組模塊[2]

1. 題目1539. 第 k 個缺失的正整數(難度:簡單)Oct.28

刷題請點擊或見附錄:1539. 第 k 個缺失的正整數[3]

題目要求:給你一個 嚴格升序排列 的正整數數組 arr 和一個整數 k 。

示例 1:

輸入:arr = [2,3,4,7,11], k = 5

輸出:9

解釋:缺失的正整數包括 [1,5,6,8,9,10,12,13,...] 。第 5 個缺失的正整數為 9 。

示例 2:

輸入:arr = [1,2,3,4], k = 2

輸出:6

解釋:缺失的正整數包括 [5,6,7,...] 。第 2 個缺失的正整數為 6 。

1.1 解題思路我們通過示例發現,數組的下標 i 與 arr[i] 的差值 distance 就是缺失的正整數個數。因此我們可以通過判斷 distance 和 k 的大小,來知道我們要找的數所在的區間。我們同樣也可以通過 distance 計算出,我們需要的值。1.2 代碼
class Solution:
    def findKthPositive(self, arr: List[int], k: int) -> int:
        for i in range(len(arr)):
            dis = arr[i] - i
            if k < dis:
                return arr[i] - (dis-k)   #找到區間,通過dis-k計算該值與相鄰較大值得距離
        return arr[-1]-dis+k+1     #若循環完了輸入數組還沒找到,則從數組的最後一個元素開始繼續加


class Solution {
public:
    int findKthPositive(vector<int>& arr, int k) {
        int res=0,dis=0;
        for(int i=0 ; i<arr.size();i++){
            dis = arr[i]-i;
            if(k<dis){
                res=arr[i]-(dis-k);
                return res;
            }
        }
        res=arr[arr.size()-1]-dis+k+1;
        return res;
    }
};

2. 題目747. 至少是其他數字兩倍的最大數(難度:簡單)Oct.29

刷題請點擊或見附錄:747. 至少是其他數字兩倍的最大數[4]

題目要求:在一個給定的數組nums中,總是存在一個最大元素 。

查找數組中的最大元素是否至少是數組中每個其他數字的兩倍。

示例 1:

輸入: nums = [3, 6, 1, 0]

輸出: 1

解釋: 6是最大的整數, 對於數組中的其他整數,6大於數組中其他元素的兩倍。6的索引是1, 所以我們返回1.

示例 2:

輸入: nums = [1, 2, 3, 4]

輸出: -1

解釋: 4沒有超過3的兩倍大, 所以我們返回 -1.

2.1 解題思路此題目其實只是在尋找最大值輸出其下標(索引),這個問題上多了一個輸出判斷。這個判斷是最大值是否大於等於其它的值的兩倍。這裡C++可以通過冒泡排序先找到最大值及其對應的下標(索引)。而python則可以很方便的啊使用方法 max 與 index 分別取得最大值與下標。2.2 代碼
class Solution(object):
    def dominantIndex(self, nums):
        maxNum = max(nums)                      #取最大值
        if all(maxNum >= 2*num for num in nums if num != maxNum ):   #判斷除自身外,是否大於等於其它值的2倍
            return nums.index(maxNum)   #若大於等於 返回最大值索引
        return -1     #否則返回-1

class Solution {
public:
    int dominantIndex(vector<int>& nums) {
        int maxNum=0,index=0;
        for(int i = 0;i < nums.size();i++) // 冒泡排序尋最大值,並且記錄下標
            if(nums[i] > maxNum){
                maxNum = nums[i];
                index = i;
            }
        for(int i = 0;i < nums.size();i++)//判斷非自身的情況下,是否大於等於別的數的2倍
            if( nums[i]*2 > maxNum &&i != index && nums[i]!=0){ //這裡需要注意別忘了0這個特殊的值
                return -1;
            }
        return index;

    }
};

3. 題目88. 合併兩個有序數組(難度:簡單)Oct.30

刷題請點擊或見附錄:88. 合併兩個有序數組[5]

題目要求:給你兩個有序整數數組 nums1 和 nums2,請你將 nums2 合併到 nums1 中,使 nums1 成為一個有序數組。

初始化 nums1 和 nums2 的元素數量分別為 m 和 n 。你可以假設 nums1 有足夠的空間(空間大小大於或等於 m + n)來保存 nums2 中的元素。

示例 1:

輸入:

nums1 = [1,2,3,0,0,0], m = 3

nums2 = [2,5,6],       n = 3

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

3.1 解題思路

C++中我們可以使用雙指針,兩個指針 pos1 和 pos2 分別從數組 num1 與 num2 的末端開始往前走。比較2個指針值大小,將較大值存入數組 num1 的末端,同時存儲指針 save 往前挪一位,較大的數組指針也往前挪一位。註:指針要注意邊界問題!!

python的思路,我們使用循環直接在 num1 的 m 位開始,把 num2 拼接上去。然後做個快速排序即可。

Ps:C++中也可以使用python的方法,我會把對應的代碼也附上。

3.2 代碼
class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        for i in range (0,n):#從0開始所以不需要m+i-1!!!!
            nums1[m+i]=nums2[i] #拼接數組
        nums1.sort() #快速排序

//使用雙指針的思路
class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int pos1 = m - 1, pos2 = n - 1, save = m + n - 1;
        while(save >= 0){
            if(pos1 < 0){
                nums1[save] = nums2[pos2];
                pos2--;
            }
            else if(pos2 < 0){
                nums1[save] = nums1[pos1];
                pos1--;
            }//以上兩步處理指針邊界問題
            else if(nums1[pos1] <= nums2[pos2]){
                nums1[save] = nums2[pos2];
                pos2--;
            }
            else{
                nums1[save] = nums1[pos1];
                pos1--;
            }//判斷指針大小,插入save,並且前移
            save--;//存儲指針前移
        }
    }
};

-
//使用python相同的思路解題
class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        for(int i=0 ;i<n;i++){
            nums1[m+i]=nums2[i];
        }
        sort(nums1.begin(),nums1.end());
    }
};

4. 題目509. 斐波那契數(難度:簡單)Oct.31

題目要求:斐波那契數,通常用 F(n) 表示,形成的序列稱為斐波那契數列。該數列由 0 和 1 開始,後面的每一項數字都是前面兩項數字的和。也就是:

F(0) = 0,   F(1) = 1

F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

給定 N,計算 F(N)。

示例 1:

輸入:2

輸出:1

解釋:F(2) = F(1) + F(0) = 1 + 0 = 1.

示例 2:

輸入:3

輸出:2

解釋:F(3) = F(2)) + F(1)) = 1 + 1 = 2.

示例 3:

輸入:4

輸出:3

解釋:F(4) = F(3) + F(2) = 2 + 1 = 3.

4.1 解題思路圖中是一個F(5)計算的遞歸樹(圖片來自leetcode官方[7])。從底層開始往上計算 F(N)=F(N-1)+F(N-2)4.2 代碼
#注釋看C++
class Solution:
    def fib(self, N: int) -> int:
        sumF=0
        f1=1
        f0=0
        if N==0:
            sumF=f0
        if N==1:
            sumF=f1
        while N>=2:
            sumF=f1+f0
            f0=f1
            f1=sumF
            N=N-1
        return sumF

class Solution {
public:
    int fib(int N) {
        int sum = 0, f1 = 1, f0 = 0;//初始化f0 f1的值
        if(N == 0){
             sum=f0;
             }
        if(N == 1){
             sum=f1; 
        }
        while(N >= 2)//當N>2時開始從下往上計算,每計算一次N--
        {
            sum = f1 + f0;
            f0 = f1;
            f1 = sum;
            N --;
        }
        return sum;
    }
};

5. 題目118. 楊輝三角(難度:簡單)Nov.01

題目要求:給定一個非負整數 numRows,生成楊輝三角的前 numRows 行。在楊輝三角中,每個數是它左上方和右上方的數的和。

註:有圖片解釋題意 leetcode官網[9]

示例 1:

輸入: 5

輸出:

[

[1],

[1,1],

[1,2,1],

[1,3,3,1],

[1,4,6,4,1]

]

5.1 解題思路這題的解法比斐波那契稍微複雜一點,要用到二維數組來計算和存儲這個數字三角。主要是用到了這個動態方程 res[i][j]=res[i-1][j-1]+res[i-1][j] 來計算。初始化斐波那契數列的時候,我們初始化了前2個數為0和1,然後從第三個數開始計算。在這裡我們需要在初始化的時候讓第一二兩行值都為1,從第三行開始計算。5.2 代碼
#注釋看C++
class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        res = [[1]*i for i in range(1,numRows+1)]
        for i in range(2,numRows) :
            for j in range(1,i) :
                res[i][j] = res[i-1][j-1]+res[i-1][j]
        return res

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int> > res;
        for(int i=1; i<=numRows; ++i) 
            // 初始化楊輝三角形,值均為1
            res.push_back(vector<int> (i, 1));
        for(int i=2; i<numRows; ++i)
        {//從第3行開始計算
            for(int j=1; j<i; ++j)
            {//每行從第二個元素開始到倒數第二個元素為止,因為第一個元素和最後一個元素我們已經初始化為1了
                res[i][j] = res[i-1][j-1] + res[i-1][j];
            }
        }
        return res;
    }
};

6. 題目1331. 數組序號轉換(難度:簡單)Nov.02

刷題請點擊或見附錄:1331. 數組序號轉換[10]

題目要求:給你一個整數數組 arr ,請你將數組中的每個元素替換為它們排序後的序號。

一個元素越大,那麼序號越大。如果兩個元素相等,那麼它們的序號相同。

示例 1:

輸入:arr = [40,10,20,30]

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

解釋:40 是最大的元素。10 是最小的元素。20 是第二小的數字。30 是第三小的數字。

示例 2:

輸入:arr = [100,100,100]

輸出:[1,1,1]

解釋:所有元素有相同的序號。

示例 3:

輸入:arr = [37,12,28,9,100,56,80,5,12]

輸出:[5,3,4,2,8,6,7,1,3]

6.1 解題思路第三步 拿原來的數組 arr 與去重後的數組做一個匹配。輸出匹配結果。這裡需要2個空間,所以我們要重新定義一個容器,內容與 arr 數組相同。6.2 代碼
class Solution:
    def arrayRankTransform(self, arr: List[int]) -> List[int]:
        dic={}#創建空字典
        L=sorted(list(set(arr)))#set去重,然後對list排序
        for i,element in enumerate(L):
            dic[element]=i+1 #元素對應序號
        return [dic[i] for i in arr]#對arr元素做匹配

class Solution {
public:
    vector<int> arrayRankTransform(vector<int>& arr) {
        vector<int> res = arr;//在定義一個數組
        sort(arr.begin(), arr.end());//對原數組排序
        int len = unique(arr.begin(), arr.end()) - arr.begin();//獲取去重後數組的長度 unique返回的是去重排序後 最後一位的地址
        for(int& index : res)   //做匹配 類似於 python的字典
            index = lower_bound(arr.begin(), arr.begin() + len, index) - arr.begin() + 1;//函數lower_bound()在first和last中的前閉後開區間進行二分查找,返回大於或等於val的第一個元素位置。如果所有元素都小於val,則返回last的位置.
        return res;
    }
};


7. 題目53. 最大子序和(難度:簡單)Nov.03 題目要求:給定一個整數數組 nums ,找到一個具有最大和的連續子數組(子數組最少包含一個元素),返回其最大和。

示例 1:

輸入: [-2,1,-3,4,-1,2,1,-5,4]

輸出: 6

解釋: 連續子數組 [4,-1,2,1] 的和最大,為 6。

7.1 解題思路使用動態規劃的辦法,若前一位大於0,則累加到當前位。然後對動態規劃後的新數組排序,取出最大值。7.2 代碼
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        size=len(nums) #獲取數組長度
        for i in range (1,size): #從第二個數開始做判斷,若前一位大於0,則累加到當前位
            if nums[i-1]>=0:
                nums[i] += nums[i-1]
        return max(nums)#取出新數組的最大值

//注釋看python
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        for(int i=1;i<nums.size();i++){
            if (nums[i-1]>=0){
                nums[i] += nums[i-1];
            }
        }
        sort(nums.begin(),nums.end());
        return nums[nums.size()-1];
    }
};

Ps:後面難度上去可能會變成2天一題,最近開學了,開始忙了。要整理的文檔也開始多起來了!加油吧!

參考資料[1]

Leetcode網站: https://leetcode-cn.com/

[2]

以上文字描述均來自 LeetCode數組模塊: https://leetcode-cn.com/tag/array/

[3]

刷題請點擊或見附錄:1539. 第 k 個缺失的正整數: https://leetcode-cn.com/problems/kth-missing-positive-number/

[4]

刷題請點擊或見附錄:747. 至少是其他數字兩倍的最大數: https://leetcode-cn.com/problems/largest-number-at-least-twice-of-others/

[5]

刷題請點擊或見附錄:88. 合併兩個有序數組: https://leetcode-cn.com/problems/merge-sorted-array/

[6]

刷題請點擊或見附錄:509. 斐波那契數: https://leetcode-cn.com/problems/fibonacci-number/

[7]

leetcode官方: https://leetcode-cn.com/problems/fibonacci-number/solution/fei-bo-na-qi-shu-by-leetcode/

[8]

刷題請點擊或見附錄:118. 楊輝三角: https://leetcode-cn.com/problems/pascals-triangle/

[9]

leetcode官網: https://leetcode-cn.com/problems/pascals-triangle/

[10]

刷題請點擊或見附錄:1331. 數組序號轉換: https://leetcode-cn.com/problems/rank-transform-of-an-array/

[11]

刷題請點擊或見附錄:53. 最大子序和: https://leetcode-cn.com/problems/maximum-subarray/

- END -

相關焦點

  • LeetCode數組類知識點&題型總結
    leetcode第一題就是two-sum,對於這類題目,首先看題目要求的時間複雜度和空間複雜度是什麼,其次看有沒有限制條件,如要求不能有重複的子數組或者要求按照升序/降序排列等。1.按start排序2.在前一個區間的end和後一個區間的start找交集例題:252 meeting room[easy](https://leetcode.com/problems/meeting-rooms/)題目理解:給定一個數組,包含每個會議的開始時間和結束時間[[s1,e1],[s2,e2],...]
  • [LeetCode] 912. Sort an Array 數組排序
    Output: [1,2,3,5]Example 2:Input: [5,1,1,2,0,0]Output: [0,0,1,1,2,5]Note:1<=A.length<=10000-50000<=A[i]<=50000這道題讓我們給數組排序
  • LeetCode刷題指南(數組和矩陣)
    人在江湖不迷路作者:CYC2018文章連結:https://github.com/CyC2018/CS-Notes/blob/master/docs/notes/Leetcode%20%E9%A2%98%E8%A7%A3.mdLeetCode題解是CYC2018的力作,我也是通過他的題解來完成算法刷題的
  • leetcode刷對了麼
    今天,逆行君就帶你從世界觀和方法論兩方面走進「leetcode」 簡單來說,leetcode是一個美國的在線編程網站,它收集了各大公司的經典算法面試題,用戶可以選擇不同的語言進行代碼的在線編寫、編譯和調試。
  • 通關LeetCode刷題完整攻略,省時又高效
    最簡單的方式是這樣的:middle = (start + end) / 2。但這種計算方式有不小的概率會出現整數越界。這種模式定義了一種簡單方式來理解拓撲排序這種技術。這種模式是這樣奏效的:初始化a) 藉助於HashMap將圖保存成鄰接表形式。
  • LeetCode145|數組中數字出現的次數II
    一,數組中數字出現的次數II1,問題描述在一個數組 nums 中除一個數字只出現一次之外,其他數字都出現了三次
  • 刷了幾千道算法題,我私藏的刷題網站都在這裡了
    1、leetcode英文網址:https://leetcode.com/中文網址:https://leetcode-cn.com/估計 leetcode(力扣)大家都很熟悉了,都被推薦爛了,很多國內外的程式設計師在上面刷題
  • [LeetCode] 996. Number of Squareful Arrays 平方數組的個數
    Example 2:Input: [2,2,2]Output: 1Note:1<=A.length<=120<=A[i]<=1e9這道題給了一個非負整數組成的數組A,定義了一種平方數組,即任意兩個相鄰的數字之和是個完全平方數,現在讓找出有多少個A
  • 小張刷題計劃
    原題為了提高自己的代碼能力,小張制定了 LeetCode 刷題計劃,他選中了 LeetCode 題庫中的 n 道題,編號從 0 到 n-1,並計劃在 m 天內按照題目編號順序刷完所有的題目(注意,小張不能用多天完成同一題)。在小張刷題計劃中,小張需要用 time[i] 的時間完成編號 i 的題目。
  • [LeetCode] 918. Maximum Sum Circular Subarray 環形子數組的最大和
    >Example 5:Input: [-2,-3,-1]Output: -1 Explanation: Subarray [-1] has maximum sum -1Note:-30000<=A[i]<=300001<=A.length<=30000這道題讓求環形子數組的最大和
  • ​LeetCode刷題實戰53:最大子序和
    所以,為了提高大家的算法能力,這個公眾號後續每天帶大家做一道算法題,題目就從LeetCode上面選 !今天和大家聊的問題叫做 最大子序和,我們先來看題面:https://leetcode-cn.com/problems/maximum-subarray/Given an integer array nums, find the contiguous subarray (containing at least one number
  • ​LeetCode刷題實戰15題: 三數之和
    所以,為了提高大家的算法能力,這個公眾號後續每天帶大家做一道算法題,題目就從LeetCode上面選 !今天和大家聊的問題叫做三數之和 ,我們先來看題面:https://leetcode.com/problems/3sum/描述給定一個整數的數組,要求尋找當中所有的a,b,c三個數的組合,使得三個數的和為0.注意,
  • ​LeetCode刷題實戰137:只出現一次的數字 II
    所以,為了提高大家的算法能力,這個公眾號後續每天帶大家做一道算法題,題目就從LeetCode上面選 !今天和大家聊的問題叫做只出現一次的數字 II,我們先來看題面:https://leetcode-cn.com/problems/single-number-ii/Given an integer array nums where every element appears three times except for one, which appears exactly
  • Go 刷 leetcode|一道簡單難度卻讓我陷入沉思的題目
    今天為大家講解 LeetCode 第 53
  • 旋轉數組的最小數字
    原題把一個數組最開始的若干個元素搬到數組的末尾,我們稱之為數組的旋轉。輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。例如,數組 [3,4,5,1,2] 為 [1,2,3,4,5] 的一個旋轉,該數組的最小值為 1。
  • 每天一道算法題(第三十二期)
    這周的題是隨機抽取,沒有特定的主題。算法題解沒有特定的思路,可能一人有一個思路,例如有的題既可以使用動規,又可以使用分治。殊途同歸,算法的目的就是提升效率。連續數列給定一個整數數組,找出總和最大的連續數列,並返回總和。
  • Leetcode刷題No.234
    今天的題目就是一道套路題。https://leetcode-cn.com/problems/palindrome-linked-list
  • [LeetCode] 976. Largest Perimeter Triangle 最大周長的三角形
    Example 3:Input: [3,2,3,4]Output: 10Example 4:Input: [3,6,2,3]Output: 8Note:3<=A.length<=100001<=A[i]<=10^6這道題給了個正整數數組
  • LeetCode 題解 | 238. 除自身以外數組的乘積
    輸入: [1,2,3,4]輸出: [24,12,8,6]說明: 請 不要使用除法,且在 O(n) 時間複雜度內完成此題。進階:你可以在常數空間複雜度內完成這個題目嗎?( 出於對空間複雜度分析的目的,輸出數組 不被視為 額外空間。)解決方案概述這似乎是一個簡單的問題,可以在線性時間和空間內解決。可以先計算給定數組所有元素的乘積,然後對數組中的每個元素 x ,將乘積除以 x 來求得除自身值的以外的數組乘積。
  • [LeetCode] 923. 3Sum With Multiplicity 三數之和的多種情況
    Note:3<=A.length<=30000<=A[i]<=1000<=target<=300這道題是之前那道 3Sum 的拓展,之前那道題是說沒有重複數字,而這道題卻有大量的重複數字,所以每個組合可能會大量重複出現,讓我們統計出所有組合的總出現次數,並對一個超大數取餘。