1. 程式人生 > >leetcode題解-初級演算法陣列篇(1-5題)

leetcode題解-初級演算法陣列篇(1-5題)

7月保研的夏令營已經告一段落了,面試中被問了很多演算法的問題,感覺自己演算法知識有些許薄弱(acm大神忽略),所以準備開始刷leetcode,順便也為面試準備,因為想把刷leet裡面的一些心得給記下來,便於之後複習,所以在這裡開博。之後會按裡面的篇章順序進行更新,喜歡的可以給文章點一個贊,如果文章有任何問題或者有更好的解法可以在評論中給出,下面開始題解,本篇章為初級演算法的陣列篇(1-5題):

第一題:從排序陣列中刪除重複項

題目要求:給定一個排序陣列,你需要在原地刪除重複出現的元素,使得每個元素只出現一次,返回移除後陣列的新長度。
不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 O(1) 額外空間的條件下完成。

演算法說明:這題是簡單題,題目中要求要用O(1)的空間複雜度,所以是不能額外建一個數組了,我的思路是建一個temp等於第一個數,再建一個res變數用於儲存不同的元素個數,因為陣列是排序的,所以對陣列進行掃描,若掃描的值和temp不一樣,則更新temp並且res++,把不一樣的元素移到對應的位置num[res-1]。
其程式碼如下:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int res=1;
        int curser;
        if
(nums.size()==0){ return 0; } int temp=nums[0]; for(int i=0;i<nums.size();i++){ if(nums[i]!=temp){ res++; temp=nums[i]; nums[res-1]=nums[i]; } else{ } } return
res; } };

第二題:買賣股票的最佳時機 II

題目說明:給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。設計一個演算法來計算你所能獲取的最大利潤。你可以儘可能地完成更多的交(多次買賣一支股票)。
注意:你不能同時參與多筆交易(你必須在再次購買前出售掉之前的股票)。

演算法:本題就是一題貪心,當後一天的價格比之前高就賣出,具體為什麼可以自己仔細想一想。

程式碼如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int sum=0;
        if(prices.size()==1||prices.size()==0){
        return 0;
        }
        for(int i=0;i<prices.size()-1;i++){
        if(prices[i+1]>prices[i]){
            sum=sum+prices[i+1]-prices[i];        }
        }
        return sum;
    }
};

第三題:旋轉陣列

給定一個數組,將陣列中的元素向右移動 k 個位置,其中 k 是非負數。
示例 1:
輸入: [1,2,3,4,5,6,7] 和 k = 3
輸出: [5,6,7,1,2,3,4]
解釋:
向右旋轉 1 步: [7,1,2,3,4,5,6]
向右旋轉 2 步: [6,7,1,2,3,4,5]
向右旋轉 3 步: [5,6,7,1,2,3,4]
儘可能想出更多的解決方案,至少有三種不同的方法可以解決這個問題。
要求使用空間複雜度為 O(1) 的原地演算法。
該題的解法有很多,這裡給出三種空間為O(1)的方法。
方法一:寫一個旋轉一次的函式,然後根據題目要求的k,旋轉k次,這樣空間複雜度為O(1),時間複雜度為O(N^K)。
方法二:和上個方法類似,不過移動的時候直接通過nums[i]與nums[(i+k)%nums.size()]這樣對應,從而減少操作次數。空間複雜度O(1),時間複雜度O(N)。
方法三:這是另一個比較好的方法,建立一個變數times=k%n。然後對於一個數組從times開始把整個陣列分為兩個部分。如[1,2,3,4,5,6,7] 和 k = 3,此時n=7。times=3。則把[1,2,3,4,5,6,7]分成兩個部分[1,2,3,4 | 5,6,7],然後把第一個部分翻轉[4,3,2,1 | 7,6,5],把第二部分也翻轉[4,3,2,1 | 7,6,5],最後把整個陣列翻轉得到最終答案[5,6,7,1,2,3,4],該方法時間複雜度O(n)。
該方法的程式碼如下:

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n=nums.size();
        int times=k%n;
        if(times==0)
            return;
        rotCore(nums,0,n-1-times);
        rotCore(nums,n-times,n-1);
        rotCore(nums,0,n-1);
    }
    void rotCore(vector<int>& nums,int b,int e){
        while(b<e){
            swap(nums[b],nums[e]);
            ++b;
            --e;
        }
        return;
    }
};

第四題 存在重複

題目描述:給定一個整數陣列,判斷是否存在重複元素。如果任何值在陣列中出現至少兩次,函式返回 true。如果陣列中每個元素都不相同,則返回 false。
演算法說明:這題和第一題的不同之處在於不是有序的陣列。方法1通過對每個元素判斷是否有重複,時間複雜度O(n^2)。所以這裡我採用了set容器,掃描的過程中把元素加入,如果有重複就返回true,因為set容器中的查詢為紅黑樹,所以該方法的時間複雜度為O(nlogn)。程式碼如下:

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        set<int> table;
        int i;
        for(i=0;i<nums.size();i++)    {
        if(table.count(nums[i])==1) return true;
         table.insert(nums[i]);
        }

        return false;

    }
};

第五題 只出現一次的數字

題目說明:給定一個非空整數陣列,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。
說明:你的演算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?

演算法說明:這道題目是面試中的原題了,有同學面試被問到過,難度在於線性時間複雜度和不使用額外空間,要滿足這兩個條件的本題的方法是使用異或。
首先我們知道異或對與一樣的兩個數他們的結果會是0,而且異或符合交換律,所以把陣列中所有的數異或一遍就得到了結果,而且符合了線性複雜度和0額外空間,其程式碼如下:

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int m=0;
        for(int i=0;i<nums.size();i++)
            m=m^nums[i];
        return m;
    }
};

6-11題的題解馬上也會更新