LeetCode--數組

 數組:java

一、給定一個數組和一個值,刪除該值的全部實例並返回新的長度。 元素的順序能夠改變。 你留下的新長度並不重要git

這道題很坑爹,是牛客網裏的一道題,也不知道是個人理解能力差,仍是它的英文寫的有問題,它的測試案例很偏,不得不像下面這麼作。算法

class Solution {
public:
    int removeElement(int A[], int n, int elem) {
        if (n == 0) return n;
        for (int i = 0; i < n; ++i){
            if (A[i] == elem)
            {
                while (n>i && A[--n] == elem);
                A[i] = A[n];
            }
        }
        return n;
    }
};

二、給定排序數組,刪除重複項,使每一個元素只出現一次並返回新長度。
不要爲另外一個數組分配額外的空間,必須使用常量內存來執行此操做。
例如,
給定輸入數組A = [1,1,2],
你的函數應該返回length = 2,A如今是[1,2]數組

class Solution {
public:
    int removeDuplicates(int A[], int n) {
        if(n==0) return n;
        int i=0; // 慢指針
        for(int j=1;j<n;j++) //快指針
        {
            if(A[i]!=A[j]) //若是快慢兩指針指向地址內的值相同,則跳過
            {              //若不相同,則將快指針指向的值放在慢指針的後面
                A[++i] = A[j];
            }
        }
        return ++i; // 數組的長度
    }
};

三、您將得到表示圖像的n x n 2D矩陣。函數

將圖像旋轉90度(順時針)。
跟進:
你能這樣作嗎?測試

思路:其實這道題就是將數組順時針旋轉90°spa

按照圖像須要作兩部翻轉,第一步是對角線翻轉,第二部是上下翻轉設計

class Solution {
public:
    void rotate(vector<vector<int> > &matrix) {
        int row = (int)matrix.size();
        int col = (int)matrix[0].size();
        int a = row - 1;
        int b = col - 1;
        int target = matrix[row-1][0];
        //對角線翻轉
        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col-i;j++)
            {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[b-j][a-i];
                matrix[b-j][a-i] = temp;
            }
        }
        //從中間翻轉
        for(int i=0;i<row/2;i++)
        {
            for(int j=0;j<col;j++)
            {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[a-i][j];
                matrix[a-i][j] = temp;
            }
        }    
    }
};

四、給定未排序的整數數組,找到第一個缺乏的正整數。
例如,
鑑於[1,2,0] return3,
和[3,4,-1,1] RETURN2。
您的算法應該在O(n)時間運行並使用恆定空間。指針

思路:code

class Solution {
public:
    int firstMissingPositive(int A[], int n) {
        if(n==0) return 1;
        for(int i=0;i<n;i++){
            //A[i] - 1 < A.length超出範圍不交換,A[i] != A[A[i] - 1] 相等不交換
            while(A[i]>0 && A[i]!=i+1 && A[i]-1<n && A[i]!=A[A[i]-1]){
                change(A,i,A[i]-1);
            }
        }
        for (int i = 0; i < n; i++) {
            if (A[i] != i + 1) {
                return i + 1;  // 第一個不相等就返回
            }
        }
        return A[n-1]+1;  // 數組交換後是有序正數,就返回最大 + 1
    }
    void change(int A[],int i,int j)
    {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
};

五、實現下一個排列,它將數字從新排列到字典上的下一個更大的數字排列。
若是這種安排不可能,則必須將其從新排列爲儘量低的順序(即按升序排序)。
替換必須就地,不要分配額外的內存。
這裏有些例子。 輸入位於左側列中,其相應的輸出位於右側列中。
1,2,3→1,3,2
3,2,1→1,2,3
1,1,5-→1,5,1

思路:從後往前先找到不知足遞增排序的點,swap這個點與後面大於此的數,而後對後面升序排列

class Solution {
public:
    void nextPermutation(vector<int> &num) {
        int n = num.size();
        int i = n-1;
        if(n==0) return;
        //先找到數組後面數比前面數大的下標
        while(i>0 && num[i-1]>=num[i]) --i;
        //若下標爲0,則表明該數組是降序排列,改成升序排列
        if(i==0){
            reverse(num.begin(),num.end());
        }
        //若下標不爲0。則表明存在一個數大於前面的數
        else{
            //找到數組最後的數
            int j=n-1;
            //若是該數小於數組最後的數
            while(num[j]<=num[i-1]) --j;
            swap(num[j],num[i-1]);
            reverse(num.begin()+i,num.end());
        }
    }
};

六、給定一個數字表示爲數字數組,加上一個數字。

思路:這題是什麼意思呢?例若有個數字爲10010,將這個數字放在數組裏,該數組爲{1,0,0,1,0},而後再這個數組上加1,的到最後的數組,但上面的狀況是很是好的狀況,若是是向下面這樣的數組{1,0,0,9,9},這就涉及進位了。因此該題最好是從數組的右面向左進行運算,求出它每一個位的餘數。

class Solution {
public:
    vector<int> plusOne(vector<int> &digits) {
        int carry = 1;
        int n = digits.size();
        for(int i=n-1;i>=0;--i){
            int cur_sum = digits[i] + carry; // 當前數字 + 進位
            digits[i] = cur_sum%10; 
            carry = cur_sum/10; // 進位
        }
        if(carry>0) digits.insert(digits.begin(),carry);
        return digits;
    }
};

七、給定整數n,以螺旋順序生成填充有1到n 2的元素的方陣。

例如,
給定n = 3,
你應該返回如下矩陣:
[
  [1,2,3],
  [8,9,4],
  [7,6,5]
]

思路:先從外圈開始,在轉到內圈,直到最後一個數

class Solution {
    public:
    vector<vector<int> > generateMatrix(int n) {
        vector<vector<int> > res;
        if (n < 1)
            return res;
        int index = 1, rowStart = 0, rowEnd = n - 1, colStart = 0, colEnd = n - 1;
        while (index <= n * n) {
            for (int i = colStart; i <= colEnd; i++) 
                res[rowStart][i] = index++;
            for (int i = rowStart + 1; i <= rowEnd; i++) 
                res[i][colEnd] = index++;
            for (int i = colEnd - 1; i >= colStart; i--) 
                res[rowEnd][i] = index++;
            for (int i = rowEnd - 1; i > rowStart; i--) 
                res[i][colStart] = index++;

            rowStart += 1;
            rowEnd -= 1;
            colStart += 1;
            colEnd -= 1;
        }
        return res;
    }
};

八、給定m×n個元素的矩陣(m行,n列),以螺旋順序返回矩陣的全部元素。

例如,
給出如下矩陣:

[
  [1,2,3],
  [4,5,6],
  [7,8,9]
]
你應該返回[1,2,3,6,9,8,7,4,5]。 

思路:該題思路和上題同樣,就是否是往裏面填數而是取數。

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int> > &matrix) {
        if(matrix.empty()) return vector<int>();
        int col = matrix.size();
        int row = matrix[0].size();
        int left = 0,right = row-1;
        int top = 0,bottom = col-1;
        vector<int> num;
        while(1)
        {
            for(int i=left;i<=right;i++)
                num.push_back(matrix[top][i]);
            if(++top > bottom) break;
            
            for(int j=top;j<=bottom;j++)
                num.push_back(matrix[j][right]);
            if(--right < left) break;
            
            for(int i=right;i>=left;i--)
                num.push_back(matrix[bottom][i]);
            if(--bottom < top) break;
            
            for(int j=bottom;j>=top;j--)
                num.push_back(matrix[j][left]);
            if(++left > right) break;
        }
        return num;
    }
};

九、跟進「刪除重複項」:
若是重複最多容許兩次怎麼辦?

例如,
給定排序數組A = [1,1,1,2,2,3],

你的函數應該返回length = 5,A如今是[1,1,2,2,3]。

class Solution {
public:
    int removeDuplicates(int A[], int n) {
        if(n<2) return n;
        int index = 2;
        for(int i=2;i<n;i++){
            if(A[i]!=A[index-2]) //不等則計數,相等則跳過不計數
                A[index++]=A[i];
        }
        return index;
    }
};

十、給定一個具備紅色,白色或藍色的n個對象的數組,對它們進行排序,使相同顏色的對象相鄰,顏色順序爲紅色,白色和藍色。
這裏,咱們將使用整數0,1和2分別表示紅色,白色和藍色。
注意:
您不該該使用庫的排序功能來解決此問題。
點擊顯示跟進。
跟進:
一個至關直接的解決方案是使用計數排序的兩遍算法。
首先,迭代0,1,和2的數組計數,而後覆蓋總數爲0的數組,而後是1,而後是2。
你能想出一個只使用恆定空間的一次經過算法嗎?

思路:
設置3個變量,分別表明數組前部zeroindex,當前遍歷的位置 i,數組後部 twoindex
①當A[i] = 0時,必然屬於數組前部,則交換A[i] 和 A[zeroindex] ,接着i++ , zeroindex++
②當A[i] = 1時,只需i++就好,由於只有排好了0和2,1天然就只能在中間了,故不做處理
③當A[i] = 2時,否則屬於數組後部,則交換A[i]和A[twoindex],接着twoindex--,不過此時就不能i++了由於,交換過去的A[i]有多是0或者2,因此須要在下一個循環裏判斷,這樣它的位置纔可以正確
class Solution {
public:
    void sortColors(int A[], int n) {
        int left = 0;
        int right = n-1;
        int i=0;
        while(i < right+1)
        {
            if(A[i]==0) {
                swap(A[i],A[left]);
                left++;
                i++;
            }else if(A[i]==2){
                swap(A[i],A[right]);
                right--;
            }else{
                i++;
            }
        }
    }
}; 

十一、編寫一個有效的算法,搜索m×n矩陣中的值。 該矩陣具備如下屬性:
每行中的整數從左到右排序。
每行的第一個整數大於前一行的最後一個整數。
例如,
考慮如下矩陣:
[
   [1,3,5,7],
   [10,11,16,20],
   [23,30,34,50]
]

思路:個人思路多是最笨的了,時間複雜度較大
首先將數組裏的數所有放入到新建的容器num裏
而後從容器num裏判斷是否存在該數
class Solution {
public:
    bool searchMatrix(vector<vector<int> > &matrix, int target) {
        int row = matrix.size(); 
        int col = matrix[0].size();
        vector<int> num;
        bool result=false;
        //將matrix數組裏的樹所有放入到容器num裏
        for(int i=0;i<row;i++)
            for(int j=0;j<col;j++)
                num.push_back(matrix[i][j]);
        int n = num.size();
        //判斷容器num裏是否存在該數
        for(int i=0;i<n;i++)
            if(num[i]==target) result = true;

        return result;
    }
};

十二、給定包含'X'和'O'的2D板,捕獲由'X'包圍的全部區域。
經過將全部'O'翻轉到該周圍區域中的'X'來捕獲區域。
例如,
X X X X.
X O O X.
X X O X.
X O X X.
運行功能後,主板應該是:
X X X X.
X X X X.
X X X X.
X O X X.

思路:
全部與四條邊相連的O都保留,其餘O都變爲X
遍歷四條邊上的O,並深度遍歷與其相連的O,將這些O都轉爲*
將剩餘的O變爲X
將剩餘的*變爲O
class Solution {
    public:
    int rowNum = 0;
    int colNum = 0;
    void solve(vector<vector<char> > &board) {
        rowNum = board.size();
        colNum = board[0].size();
        for(int i = 0; i < colNum; i++){
            dfs(board, 0, i);
            dfs(board, rowNum-1, i);
        }
        for(int i = 0; i < rowNum; i++){
            dfs(board, i, 0);
            dfs(board, i, colNum-1);
        }
        for(int i = 0; i < rowNum; i++){
            for(int j = 0; j < colNum; j++){
                if(board[i][j] == 'O'){
                    board[i][j] = 'X';
                }
            }
        }
        for(int i = 0; i < rowNum; i++){
            for(int j = 0; j < colNum; j++){
                if(board[i][j] == '*'){
                    board[i][j] = 'O';
                }
            }
        }
    }
    void dfs(vector<vector<char> > &board, int row, int col) {
        // TODO Auto-generated method stub
        if(board[row][col] == 'O'){
            board[row][col] = '*';
            if(row > 1){
                dfs(board, row-1, col);
            }
            if(col > 1){
                dfs(board, row, col-1);
            }
            if(row < rowNum-1){
                dfs(board, row+1, col);
            }
            if(col < colNum-1){
                dfs(board, row, col+1);
            }
        }
    }
};

1三、給定兩個排序的整數數組A和B,將B合併爲A做爲一個排序的數組。
注意:
您能夠假設A有足夠的空間來容納B中的其餘元素.A和B中初始化的元素數分別爲m和n。

思路以下:
i從A的末尾,j從B末尾開始,兩兩比較,大的放在末端。
好比A[4,5,7] B[1,2,6],。
7比6大,A[5]處放置7,而後i前移。
再次比較5 和6,6放在A[4]處。
如此類推若是A窮盡,把B元素依次放進A的前幾個位置,若是B窮盡,正好結束。
class Solution {
public:
    void merge(int A[], int m, int B[], int n) {
        int aindex = m-1;
        int bindex = n-1;
        int counts = m+n-1;
        while(aindex>=0 && bindex>=0)
            A[counts--] = A[aindex] > B[bindex] ? A[aindex--] : B[bindex--];
        
        while(bindex>=0)
            A[counts--] = B[bindex--];
    }
};

1四、假設您有一個數組,其中第i個元素是第i天給定股票的價格。
設計算法以找到最大利潤。 您最多能夠完成兩筆交易。
注意:
您不得同時進行多筆交易(即,您必須在再次購買以前賣出股票)。

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int buy1 = INT_MIN, sell1 = 0, buy2 = INT_MIN, sell2 = 0;
        for(auto u:prices) { //每次循環表示進入新的一天
            buy1 = max(buy1,-u);   //記錄以前全部天最便宜的股價
            sell1 = max(sell1,buy1 + u);  //記錄以前全部天只進行1次買賣的最大利益
            buy2 = max(buy2,sell1 - u);   //記錄以前天先進行1次交易得到最大利益後,
            //再買到那次交易後最便宜股價時剩餘的淨利潤
            sell2 = max(sell2,buy2 + u); //記錄以前天進行2次完整交易的最大利潤
        }
        return sell2;
    }
};

思路:

數組下標爲i的元素存儲股票i天時的價格,要求進行2次交易,求出最大利益,而且買第2支股票前必須先拋售第一支股票
假如只進行1次交易的話會更簡單一些:用sell1表示初始時身上的淨利潤爲0,buy1以後用於存放最便宜股價的價格。一個循環表示時間一每天推移,第一天時buy1記錄下第一天買入股票身上淨利潤,以後每進入新的一天(今天),就用buy1表示前些天最便宜的股價,sell1保存了前些天買入最便宜股票以後再在股價最高時賣出股票的最大利潤。新的一天到來,再用buy1繼續記錄最低股價,再計算出在今天拋售那個最低價股票後的利潤,若是這個利潤比以前保存的sell1高,那就更新sell1,不然,sell1不變。
如此循環下去,到最後一天結束,sell1就記錄了一次交易的最大利潤。
進行2次交易的道理是能夠類推的。
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int buy1 = INT_MIN, sell1 = 0, buy2 = INT_MIN, sell2 = 0;
        for(auto u:prices) { //每次循環表示進入新的一天
            buy1 = max(buy1,-u);   //記錄以前全部天最便宜的股價
            sell1 = max(sell1,buy1 + u);  //記錄以前全部天只進行1次買賣的最大利益
            buy2 = max(buy2,sell1 - u);   //記錄以前天先進行1次交易得到最大利益後,
            //再買到那次交易後最便宜股價時剩餘的淨利潤
            sell2 = max(sell2,buy2 + u); //記錄以前天進行2次完整交易的最大利潤
        }
        return sell2;
    }
};

1五、假設您有一個數組,其中第i個元素是第i天給定股票的價格。
設計算法以找到最大利潤。 您能夠根據須要完成儘量多的交易(即,屢次買入並賣出一股股票)。 可是,您可能不會同時進行多筆交易(即,您必須在再次購買以前賣出股票)。

思路以下:

本題因爲容許屢次交易(每次必須先賣出再買進),因此很差用爆搜

分析可知,要想利益最大化,就應該每次在波谷買進,波峯賣出,這樣利益最大,操做次數最少

應該是使用動態規劃來作可能比較簡潔,我的以爲。

class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int len = prices.size();
        vector<int> num(len,0);
        int maxpro=0;
        for(int i=1;i<len;i++){
            //記錄全部長和跌的狀況
            num[i] = prices[i]-prices[i-1];
            //累加全部長幅,即爲最大收益
            if(num[i]>0) maxpro+=num[i]; 
        }
        return maxpro;
    }
};

1六、假設您有一個數組,其中第i個元素是第i天給定股票的價格。

若是您只被容許完成最多一筆交易(即買入並賣出一股股票),請設計一個算法來查找最大利潤。

思路:
從左往右遍歷向量,遇到當前最小值,則保存,
若是不是最小值,則計算它到最小值的距離,保存爲最大利潤
class Solution {
public:
    int maxProfit(vector<int> &prices) {
        int n = prices.size();
        int max_price=0;
        int min_price=prices[0];
        for(int i=0;i<n;i++){
            if(prices[i]<min_price) min_price = prices[i];
            if((prices[i]-min_price)>max_price) max_price = prices[i]-min_price;
        }
        return max_price;
    }
};

1七、給定未排序的整數數組,找到最長連續元素序列的長度。

例如,
鑑於[100,4,2,1,3,2],
最長的連續元素序列是[1,2,3,4]。 返回長度:4。
您的算法應該以O(n)複雜度運行。

思路:從數組頭部開始遍歷每個數,建立兩個int型的變量result和cnt,並將cnt置爲1,result爲0,若遇到第i個數加1不等於第i+1個數,
則計算此時數組連續數的大小,若相等則cnt加1
class Solution {
public:
    int longestConsecutive(vector<int> &num) {
        sort(num.begin(),num.end());
        int n = num.size();
        if(n==0 || n== 1) return n;
        unique(num.begin(),num.end());
        int result=0,cnt=1;
        for(int i=0;i<n-1;i++){
            if(num[i]+1!=num[i+1]){
                result = result>cnt ? result : cnt;
                cnt=0;
            }
            cnt++;
        }
        return result = result>cnt ? result : cnt;
    }
};
相關文章
相關標籤/搜索