數組: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。
你能想出一個只使用恆定空間的一次經過算法嗎?
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]
]
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; } };
思路:
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)複雜度運行。
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; } };