【CODE】二分查找 && 二維矩陣問題 && 螺旋矩陣 && 中位數

目錄

475. Heaters

441. Arranging Coins

363. Max Sum of Rectangle No Larger Than K

240. Search a 2D Matrix II

74. Search a 2D Matrix

54. Spiral Matrix

59. Spiral Matrix II

73. Set Matrix Zeroes

289. Game of Life

329. Longest Increasing Path in a Matrix

221. Maximal Square

84. Largest Rectangle in Histogram

85. Maximal Rectangle

4. Median of Two Sorted Arrays

295. Find Median from Data Stream


475. Heaters

Easy

619678Add to ListShare

Winter is coming! Your first job during the contest is to design a standard heater with fixed warm radius to warm all the houses.

Now, you are given positions of houses and heaters on a horizontal line, find out minimum radius of heaters so that all houses could be covered by those heaters.

So, your input will be the positions of houses and heaters seperately, and your expected output will be the minimum radius standard of heaters.

Note:

  1. Numbers of houses and heaters you are given are non-negative and will not exceed 25000.
  2. Positions of houses and heaters you are given are non-negative and will not exceed 10^9.
  3. As long as a house is in the heaters' warm radius range, it can be warmed.
  4. All the heaters follow your radius standard and the warm radius will the same.

Example 1:

Input: [1,2,3],[2]
Output: 1
Explanation: The only heater was placed in the position 2, and if we use the radius 1 standard, then all the houses can be warmed.

Example 2:

Input: [1,2,3,4],[1,4]
Output: 1
Explanation: The two heater was placed in the position 1 and 4. We need to use radius 1 standard, then all the houses can be warmed.
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
int findRadius(vector<int>& houses, vector<int>& heaters) {
	sort(houses.begin(), houses.end());
	sort(heaters.begin(), heaters.end());
	for (int i = 0; i < houses.size(); i++) cout << houses[i] << " ";
	cout << endl;
	for (int j = 0; j < heaters.size(); j++) cout << heaters[j] << " ";
	cout << endl;
	int max = 0;
	for (int i = 0; i < houses.size(); i++) {
		//找第一個大於等於houses[i]的heaters
		int dis = lower_bound(heaters.begin(), heaters.end(), houses[i])- heaters.begin();
		cout << dis << " ";
		if (dis >= heaters.size()) dis = heaters.size() - 1;
		if (dis == 0) max = max > abs(heaters[dis] - houses[i]) ? max : abs(heaters[dis] - houses[i]);
		else {
			int n1 = abs(heaters[dis] - houses[i]);
			int n2 = abs(heaters[dis - 1] - houses[i]);
			n1 = n1 < n2 ? n1 : n2;
			max = max > n1 ? max : n1;
		}
	}
	return max;
}
int main() {
	vector<int> houses = { 282475249,622650073,984943658,458777923 };
	vector<int> heaters = {823564440,115438165,16531729,823378840,143542612};
	cout << findRadius(houses, heaters);
	
	return 0;
} 
class Solution {
public:
    int findRadius(vector<int>& houses, vector<int>& heaters) {
        sort(houses.begin(),houses.end());
        sort(heaters.begin(),heaters.end());
        int i=0,j=0,max=0;
        for(i=0;i<houses.size();i++){
            while(j<heaters.size() && heaters[j]<houses[i]) j++;
            if(j>0 && j<heaters.size()){
                int n1=abs(houses[i]-heaters[j-1]);
                int n2=abs(heaters[j]-houses[i]);
                n1=n1<n2?n1:n2;
                max=max>n1?max:n1;
            }else if(j==0){
                int n1=abs(houses[i]-heaters[j]);
                max=max>n1?max:n1;
            }else if(j==heaters.size()){
                int n1=abs(houses[i]-heaters[j-1]);
                max=max>n1?max:n1;
            }
        }
        return max;
    }
};

441. Arranging Coins

Easy

265565Add to ListShare

You have a total of n coins that you want to form in a staircase shape, where every k-th row must have exactly k coins.

Given n, find the total number of full staircase rows that can be formed.

n is a non-negative integer and fits within the range of a 32-bit signed integer.

Example 1:

n = 5

The coins can form the following rows:
¤
¤ ¤
¤ ¤

Because the 3rd row is incomplete, we return 2.

Example 2:

n = 8

The coins can form the following rows:
¤
¤ ¤
¤ ¤ ¤
¤ ¤

Because the 4th row is incomplete, we return 3.
class Solution {
public:
    int arrangeCoins(int n) {
        /*Runtime: 4 ms, faster than 86.52% of C++ online submissions for Arranging Coins.
          Memory Usage: 7.4 MB, less than 100.00% of C++ online submissions for Arranging Coins.
        if(n==0) return 0;
        vector<int> arr;
        int now=1,i=1;
        long long next=1;
        for(i=2;i<=n;i++){
            next+=i;
            if(now<=n && next>n) return i-1;
        }
        return 1;*/
        /*二分查找,lgn
        Runtime: 4 ms, faster than 86.52% of C++ online submissions for Arranging Coins.
        Memory Usage: 7.2 MB, less than 100.00% of C++ online submissions for Arranging Coins.*/
        long long left=1,right=n;
        while(left<=right){
            long long mid=left+(right-left)/2;
            long long tmp;
            tmp=(mid+1)*mid/2;
            if(tmp>n) right=mid-1;
            else if(tmp==n) return mid;
            else left=mid+1;
        }
        return right;
        
    }
};

363. Max Sum of Rectangle No Larger Than K

Hard

62842Add to ListShare

Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix such that its sum is no larger than k.

Example:

Input: matrix = [[1,0,1],[0,-2,3]], k = 2
Output: 2 
Explanation: Because the sum of rectangle [[0, 1], [-2, 3]] is 2,and 2 is the max number no larger than k (k = 2).

Note:

  1. The rectangle inside the matrix must have an area > 0.
  2. What if the number of rows is much larger than the number of columns?
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
/*363. Max Sum of Rectangle No Larger Than K
1.計算每個矩陣的和
Runtime: 1060 ms, faster than 17.91% of C++ online submissions for Max Sum of Rectangle No Larger Than K.
Memory Usage: 9.9 MB, less than 100.00% of C++ online submissions for Max Sum of Rectangle No Larger Than K.*/
int maxSumSubmatrix1(vector<vector<int>>& matrix, int k) {
	int n = matrix.size(), m = matrix[0].size();
	int max = INT_MIN;
	vector<vector<int> > sum(n + 1, vector<int>(m + 1));
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + matrix[i - 1][j - 1];
			if (sum[i][j] <= k && max < sum[i][j]) max = sum[i][j];
			if (max == k) return max;
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			for (int q = 1; q <= i; q++) {
				for (int l = 1; l <= j; l++) {
					int tmp = sum[i][j] - sum[i][l - 1] - sum[q - 1][j] + sum[q - 1][l - 1];
					if (tmp <= k && max < tmp) max = tmp;
					if (max == k) return max;
				}
			}
		}
	}
	return max;
}
/*2.基於計算二維數組中最大子矩陣和算法
將二維數組按行或列拆分成多個一維數組,然後利用一維數組的累加和來找到符合要求的數字
使用lower_bound加快搜索速度,或者使用二分搜索代替
要先放一個0進去,這樣找lower_bound(curSum-k),當curSum=k時,就可以返回0了
Runtime: 412 ms, faster than 38.34% of C++ online submissions for Max Sum of Rectangle No Larger Than K.
Memory Usage: 99.8 MB, less than 58.82% of C++ online submissions for Max Sum of Rectangle No Larger Than K.*/
int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
	if (matrix.empty() || matrix[0].empty()) return 0;
	int m = matrix.size(), n = matrix[0].size(), res = INT_MIN;
	for (int i = 0; i < n; ++i) {//遍歷各列
		vector<int> sum(m);
		for (int j = i; j < n; ++j) {//對於第i到第n-1列
			for (int k = 0; k < m; ++k) {//累加各行
				sum[k] += matrix[k][j];
			}
			//sum[k]每輪表示:第i列,第i到i+1列,第i到i+2列,從第0到第k行的和
			//就是[0][i]->[k][i+x]的矩陣和
			int curSum = 0;
			set<int> st{ {0} };
			for(int k=0;k<m;k++){
				curSum += sum[k];//curSum累加,此時的sum[k]表示[0][i]->[k][j]的矩陣和
				auto it = st.lower_bound(curSum - k);
				//在set中找第一個≥curSum-k的數字,*it
				//*it≥curSum-k,curSum-*it≤k,*it是之前存入的比現在這個面積小的矩陣的和
				if (it != st.end()) res = max(res, curSum - *it);
				//如果*it是第一個≥curSum-k的數字,curSum-*it≤k,說明這個和是符合條件的,更新res
				st.insert(curSum);
				//將當前矩陣和加入set
			}
		}
	}
	return res;
}

240. Search a 2D Matrix II

Medium

244667Add to ListShare

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted in ascending from left to right.
  • Integers in each column are sorted in ascending from top to bottom.

Example:

Consider the following matrix:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]

Given target = 5, return true.

Given target = 20, return false.

#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
/*240. Search a 2D Matrix II
Runtime: 56 ms, faster than 98.18% of C++ online submissions for Search a 2D Matrix II.
Memory Usage: 12 MB, less than 100.00% of C++ online submissions for Search a 2D Matrix II.*/
bool searchMatrix(vector<vector<int>>& matrix, int target) {
	if (matrix.size() == 0) return false;
	int n = matrix.size(), m = matrix[0].size();
	int i = n - 1, j = 0;
	while (i >= 0 && j < m) {
		if (matrix[i][j] < target) j++;
		else if (matrix[i][j] > target) i--;
		else if (matrix[i][j] == target) return true;
	}
	return false;
}

https://blog.csdn.net/Li_Jiaqian/article/details/104497704#378.%C2%A0Kth%20Smallest%20Element%20in%20a%20Sorted%20Matrix

74. Search a 2D Matrix

Medium

1341141Add to ListShare

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

Example 1:

Input:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 3
Output: true

Example 2:

Input:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 13
Output: false
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
/*74. Search a 2D Matrix
在第一列中,找第一個大於等於目標值的,確定行數
在該行再用二分查找進行查找
Runtime: 8 ms, faster than 94.75% of C++ online submissions for Search a 2D Matrix.
Memory Usage: 8.8 MB, less than 100.00% of C++ online submissions for Search a 2D Matrix.*/
bool searchMatrix(vector<vector<int>>& matrix, int target) {
	if (matrix.size() == 0) return false;
	int n = matrix.size(), m = matrix[0].size();
	if (m == 0) return false;
	int up = 0, down = n - 1;
	while (up <= down) {
		int mid = up + (down - up) / 2;
		if (matrix[mid][0] < target) up = mid + 1;
		else if (matrix[mid][0] > target) down = mid - 1;
		else return true;
	}
	down = down < 0 ? 0 : down;
	int left = 0, right = m - 1;
	while (left <= right) {
		int mid = left + (right - left) / 2;
		if (matrix[down][mid] < target) left = mid + 1;
		else if (matrix[down][mid] > target) right = mid - 1;
		else return true;
	}
	return false;
}

54. Spiral Matrix

Medium

1798498Add to ListShare

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

Example 1:

Input:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]
Output: [1,2,3,6,9,8,7,4,5]

Example 2:

Input:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]
class Solution {
public:
    /*Runtime: 0 ms, faster than 100.00% of C++ online submissions for Spiral Matrix.
    Memory Usage: 8 MB, less than 100.00% of C++ online submissions for Spiral Matrix.*/
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> res;
        if(matrix.size()==0) return res;
        if(matrix[0].size()==0) return res;
        int n=matrix.size()-1,m=matrix[0].size()-1;
        int i=0,j=0,up=1,left=0;
        res.push_back(matrix[0][0]);
        while(res.size()!=matrix.size()*matrix[0].size()){
            while(j<m) res.push_back(matrix[i][++j]);
            if(res.size()==matrix.size()*matrix[0].size()) break;
            m--;
            while(i<n) res.push_back(matrix[++i][j]);
            if(res.size()==matrix.size()*matrix[0].size()) break;
            n--;
            while(j>left) res.push_back(matrix[i][--j]);
            if(res.size()==matrix.size()*matrix[0].size()) break;
            left++;
            while(i>up) res.push_back(matrix[--i][j]);
            if(res.size()==matrix.size()*matrix[0].size()) break;
            up++;
        }
        return res;
    }
};
class Solution {
public:
    /*Runtime: 0 ms, faster than 100.00% of C++ online submissions for Spiral Matrix.
    Memory Usage: 7.7 MB, less than 100.00% of C++ online submissions for Spiral Matrix.*/
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> res;
        if(matrix.size()==0) return res;
        if(matrix[0].size()==0) return res;
        int n=matrix.size(),m=matrix[0].size();
        int left=0,right=m-1,up=0,down=n-1;
        while(true){
            for(int i=left;i<=right;i++) res.push_back(matrix[up][i]);
            if(++up>down) break;
            for(int i=up;i<=down;i++) res.push_back(matrix[i][right]);
            if(--right<left) break;
            for(int i=right;i>=left;i--) res.push_back(matrix[down][i]);
            if(--down<up) break;
            for(int i=down;i>=up;i--) res.push_back(matrix[i][left]);
            if(++left>right) break;
        }
        return res;
    }
};
  • 第二種方法,設置4個上下限座標會好看一些

59. Spiral Matrix II

Medium

778101Add to ListShare

Given a positive integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.

Example:

Input: 3
Output:
[
 [ 1, 2, 3 ],
 [ 8, 9, 4 ],
 [ 7, 6, 5 ]
]
class Solution {
public:
    /*Runtime: 4 ms, faster than 74.26% of C++ online submissions for Spiral Matrix II.
    Memory Usage: 7.9 MB, less than 100.00% of C++ online submissions for Spiral Matrix II.*/
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int> > res(n,vector<int>(n));
        int num=1;
        int left=0,right=n-1,up=0,down=n-1;
        while(true){
            for(int j=left;j<=right;j++) res[up][j]=num++;
            if(++up>down) break;
            for(int i=up;i<=down;i++) res[i][right]=num++;
            if(--right<left) break;
            for(int j=right;j>=left;j--) res[down][j]=num++;
            if(--down<up) break;
            for(int i=down;i>=up;i--) res[i][left]=num++;
            if(++left>right) break;
        }
        return res;
    }
};

73. Set Matrix Zeroes

Medium

1616271Add to ListShare

Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place.

Example 1:

Input: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
Output: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

Example 2:

Input: 
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
Output: 
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

Follow up:

  • A straight forward solution using O(mn) space is probably a bad idea.
  • A simple improvement uses O(m + n) space, but still not the best solution.
  • Could you devise a constant space solution?
class Solution {
public:
    /*使用set記錄含有0的行數和列數
    Runtime: 40 ms, faster than 99.05% of C++ online submissions for Set Matrix Zeroes.
    Memory Usage: 10.6 MB, less than 100.00% of C++ online submissions for Set Matrix Zeroes.*/
    void setZeroes(vector<vector<int>>& matrix) {
        int n=matrix.size();
        if(n==0) return;
        int m=matrix[0].size();
        if(m==0) return;
        set<int> hang,lie;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(matrix[i][j]==0){
                    hang.insert(i);
                    lie.insert(j);
                }
            }
        }
        for(auto &a:hang){
            for(int j=0;j<m;j++){
                matrix[a][j]=0;
            }
        }
        for(auto &a:lie){
            for(int i=0;i<n;i++){
                matrix[i][a]=0;
            }
        }
        return;
    }
};
class Solution {
public:
    /*O(1)
    Runtime: 44 ms, faster than 92.86% of C++ online submissions for Set Matrix Zeroes.
    Memory Usage: 10.3 MB, less than 100.00% of C++ online submissions for Set Matrix Zeroes.*/
    void setZeroes(vector<vector<int>>& matrix) {
        int n=matrix.size();
        if(n==0) return;
        int m=matrix[0].size();
        if(m==0) return;
        bool hang=false,lie=false;
        for(int j=0;j<m;j++){
            if(matrix[0][j]==0){
                hang=true;
                break;
            }
        }//觀察第1行有沒有0
        for(int i=0;i<n;i++){
            if(matrix[i][0]==0){
                lie=true;
                break;
            }
        }//觀察第1列有沒有0
        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                if(matrix[i][j]==0){
                    matrix[0][j]=0;
                    matrix[i][0]=0;
                }
            }
        }//除去第一行和第一列的其他元素中有沒有0,有的話,將(0,j)和(i,0)設置爲0
        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                if(matrix[i][0]==0 || matrix[0][j]==0) matrix[i][j]=0;
            }
        }
        if(hang){
            for(int j=0;j<m;j++) matrix[0][j]=0;
        }//如果原本第一行就有0,將第一行設爲0
        if(lie){
            for(int i=0;i<n;i++) matrix[i][0]=0;
        }//如果原本第一列就有0,將第一列設爲0
        return;
    }
};

289. Game of Life

Medium

1443245Add to ListShare

According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970."

Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):

  1. Any live cell with fewer than two live neighbors dies, as if caused by under-population.
  2. Any live cell with two or three live neighbors lives on to the next generation.
  3. Any live cell with more than three live neighbors dies, as if by over-population..
  4. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.

Write a function to compute the next state (after one update) of the board given its current state. The next state is created by applying the above rules simultaneously to every cell in the current state, where births and deaths occur simultaneously.

Example:

Input: 
[
  [0,1,0],
  [0,0,1],
  [1,1,1],
  [0,0,0]
]
Output: 
[
  [0,0,0],
  [1,0,1],
  [0,1,1],
  [0,1,0]
]

Follow up:

  1. Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.
  2. In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?
  • 康威生命遊戲, 一種細胞自動機,每一個位置有兩種狀態,1爲活細胞,0爲死細胞,對於每個位置都滿足如下的條件:

  • 1. 如果活細胞周圍八個位置的活細胞數少於兩個,則該位置活細胞死亡

  • 2. 如果活細胞周圍八個位置有兩個或三個活細胞,則該位置活細胞仍然存活

  • 3. 如果活細胞周圍八個位置有超過三個活細胞,則該位置活細胞死亡

  • 4. 如果死細胞周圍正好有三個活細胞,則該位置死細胞復活

  • 當一個位置更新了,這個位置成爲其他位置的 neighbor 時,怎麼知道其未更新的狀態呢?可以使用狀態機轉換:

  • 狀態轉換:

  • 狀態0:死->死,狀態1:活->活,狀態2:活->死,狀態3:死->活

  • 最後狀態更新完後,統一 mod 2

  • 判斷的是鄰居轉換前的狀態:0、3是死,1、2是活

  • 自己是活的 && 2/3個鄰居是活的 -> 下一代是活的,否則是死的

  • 自己是死的 && 3個鄰居是活的 -> 下一代是活的,否則是死的

  • 最後對所有狀態對2取餘,則狀態0和2就變成死細胞,狀態1和3就是活細胞,達成目的。先對原數組進行逐個掃描,對於每一個位置,掃描其周圍八個位置,如果遇到狀態1或2,就計數器累加1,掃完8個鄰居,如果少於兩個活細胞或者大於三個活細胞,而且當前位置是活細胞的話,標記狀態2,如果正好有三個活細胞且當前是死細胞的話,標記狀態3。完成一遍掃描後再對數據掃描一遍,對2取餘變成我們想要的結果。

class Solution {
public:
    /*狀態轉換:
    狀態0:死->死,狀態1:活->活,狀態2:活->死,狀態3:死->活
    最後狀態更新完後,統一 mod 2
    判斷的是鄰居轉換前的狀態:0、3是死,1、2是活
    自己是活的 && 2/3個鄰居是活的 -> 下一代是活的,否則是死的
    自己是死的 && 3個鄰居是活的 -> 下一代是活的,否則是死的
    Runtime: 0 ms, faster than 100.00% of C++ online submissions for Game of Life.
    Memory Usage: 7.8 MB, less than 100.00% of C++ online submissions for Game of Life.*/
    void gameOfLife(vector<vector<int>>& board) {
        int n=board.size();
        if(n==0) return ;
        int m=board[0].size();
        if(m==0) return;
        int dx[8]={-1,-1,-1,0,0,1,1,1};
        int dy[8]={-1,0,1,-1,1,-1,0,1};
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                //分析每個點的八個鄰居
                int huo=0;
                for(int k=0;k<8;k++){
                    int x=i+dx[k],y=j+dy[k];
                    if(x>=0 && x<n && y>=0 && y<m){
                        if(board[x][y]==1 || board[x][y]==2) huo++;
                    }
                    if(huo>3){//已經超過3個活鄰居了
                        break;
                    }
                }
                if(board[i][j]==1){
                    if(huo==2 || huo==3) board[i][j]=1;//狀態1:活->活
                    else board[i][j]=2;//狀態2:活->死
                }
                else if(board[i][j]==0){
                    if(huo==3) board[i][j]=3;//狀態3:死->活
                    else board[i][j]=0;//狀態0:死->死,
                }
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                board[i][j]%=2;
            }
        }
        return;
    }
};

329. Longest Increasing Path in a Matrix

Hard
151928Add to ListShare

Given an integer matrix, find the length of the longest increasing path.

From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).

Example 1:

Input: nums = 
[
  [9,9,4],
  [6,6,8],
  [2,1,1]
] 
Output: 4 
Explanation: The longest increasing path is [1, 2, 6, 9].

Example 2:

Input: nums = 
[
  [3,4,5],
  [3,2,6],
  [2,2,1]
] 
Output: 4 
Explanation: The longest increasing path is [3, 4, 5, 6]
. Moving diagonally is not allowed.

#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>
#include<string>
using namespace std;
/*329. Longest Increasing Path in a Matrix
1.DFS,超時*/
void DFS1(vector<vector<int>>& matrix,int x,int y,vector<vector<int> > &vis,int &max,int len,int last) {
	if (x < 0 || y < 0 || x >= matrix.size() || y >= matrix[0].size() || vis[x][y]==1) return;
	if (last < matrix[x][y]) {
		len++;
		max = max > len ? max : len;
		vis[x][y] = 1;
		DFS1(matrix, x - 1, y, vis, max, len, matrix[x][y]);
		DFS1(matrix, x, y - 1, vis, max, len, matrix[x][y]);
		DFS1(matrix, x + 1, y, vis, max, len, matrix[x][y]);
		DFS1(matrix, x, y + 1, vis, max, len, matrix[x][y]);
		vis[x][y] = 0;
	}
	return;
}
int longestIncreasingPath1(vector<vector<int>>& matrix) {
	if (matrix.size() == 0) return 0;
	if (matrix[0].size() == 0) return 0;
	vector<vector<int> > vis(matrix.size(), vector<int>(matrix[0].size()));
	int max = 0;
	for (int i = 0; i < matrix.size(); i++) {
		for (int j = 0; j < matrix[0].size(); j++) {
			DFS1(matrix, i, j, vis, max, 0, INT_MIN);
		}
	}
	return max;
}
/*2.dp,dp[i][j]表示從(i,j)出發,最長距離
Runtime: 36 ms, faster than 92.93% of C++ online submissions for Longest Increasing Path in a Matrix.
Memory Usage: 11.8 MB, less than 100.00% of C++ online submissions for Longest Increasing Path in a Matrix.*/
int dir[4][2] = { {0,-1},{-1,0},{0,1},{1,0} };
int DFS2(vector<vector<int> > &matrix, vector<vector<int> > &dp, int i, int j) {
	if (dp[i][j]) return dp[i][j];
	int mx = 1, m = matrix.size(), n = matrix[0].size();
	for (auto a : dir) {
		int x = i + a[0], y = j + a[1];
		if (x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] >= matrix[i][j]) continue;
		int len = 1 + DFS2(matrix, dp, x, y);
		mx = max(mx, len);
	}
	dp[i][j] = mx;
	return mx;
}
int longestIncreasingPath(vector<vector<int>>& matrix) {
	if (matrix.size() == 0) return 0;
	if (matrix[0].size() == 0) return 0;
	vector<vector<int> > dp(matrix.size(), vector<int>(matrix[0].size()));
	int maxx = 0;
	for (int i = 0; i < matrix.size(); i++) {
		for (int j = 0; j < matrix[0].size(); j++) {
			maxx = max(maxx,DFS2(matrix, dp, i, j));
		}
	}
	return maxx;
}
int main() {
	vector<vector<int> > matrix = { {9,9,4},{6,6,8},{2,1,1} };
	cout << longestIncreasingPath(matrix);
	return 0;
} 

221. Maximal Square

Medium
216654Add to ListShare

Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area.

Example:

Input: 

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0

Output: 4
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>
#include<string>
using namespace std;
/*221. Maximal Square
1.遍歷每個點,以每個點爲左上角,找正方形
Runtime: 16 ms, faster than 95.92% of C++ online submissions for Maximal Square.
Memory Usage: 9.8 MB, less than 100.00% of C++ online submissions for Maximal Square.*/
void DFS(vector<vector<char>>& matrix, int i, int j, int &maxx) {
	int lenmax = min(matrix.size() - i, matrix[0].size() - j);//正方形最大邊長
	if (lenmax < maxx) return;//最大邊長小於當前最大值,直接跳出
	int flag = 0, tmpmax = 0;
	for (int l = 2; l <= lenmax && flag == 0; l++) {//邊長l,從1遍歷到lenmax
		//每次新增的正方形,在前一個的基礎上,只需要遍歷最外面的兩個邊就可以了
		for (int a = i; a < i + l && flag == 0; a++) {//新增列:j+l-1,遍歷新增列
			if (matrix[a][j + l - 1] == '0') flag = 1;
		}
		for (int b = j; b < j + l && flag == 0; b++) {//新增行:i+l-1,遍歷新增行
			if (matrix[i + l - 1][b] == '0') flag = 1;
		}
		if (flag == 0) tmpmax = l;
	}
	if (tmpmax > maxx) maxx = tmpmax;
	return;
}
int maximalSquare1(vector<vector<char>>& matrix) {
	int maxx = 1, one = 0;
	for (int i = 0; i < matrix.size(); i++) {
		for (int j = 0; j < matrix[0].size(); j++) {
			if (matrix[i][j] != '0') {
				one++;
				DFS(matrix, i, j, maxx);
			}
		}
	}
	if (one == 0) return 0;
	return maxx * maxx;
}
/*2.累計和數組,建立好累加和數組後,遍歷二維數組的每個位置,
對於任意(i,j),從該位置往(0,0)遍歷所有正方形,正方形個數爲min(i,j)+1
由於有了累加和數組,可以快速得到所有子正方形的和,比較和與邊長平方是否相等,
相等則說明正方形中的數字都是1,更新maxx
Runtime: 64 ms, faster than 6.30% of C++ online submissions for Maximal Square.
Memory Usage: 10.5 MB, less than 92.59% of C++ online submissions for Maximal Square.*/
int maximalSquare2(vector<vector<char>>& matrix) {
	if (matrix.size() == 0 || matrix[0].size() == 0) return 0;
	vector<vector<int> > sum(matrix.size(), vector<int>(matrix[0].size()));
	int maxx = 0;
	for (int i = 0; i < matrix.size(); i++) {
		for (int j = 0; j < matrix[0].size(); j++) {
			if (matrix[i][j] == '1') maxx = 1;
			if (i == 0 && j == 0) sum[i][j] = matrix[i][j] - '0';
			else if (i == 0) sum[i][j] = sum[i][j - 1] + (matrix[i][j] - '0');
			else if (j == 0) sum[i][j] = sum[i - 1][j] + (matrix[i][j] - '0');
			else sum[i][j] = sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1]+(matrix[i][j]-'0');
		}
	}
	
	for (int i = 1; i < matrix.size(); i++) {
		for (int j = 1; j < matrix[0].size(); j++) {
			if (matrix[i][j] == '1') {
				int num = min(i, j)+1 ;//正方形個數
				for (int k = 1; k <= num; k++) {
					if (i - k < 0 && j - k >= 0 && sum[i][j] - sum[i][j - k] == k * k) maxx = max(maxx, k);
					else if (i - k >= 0 && j - k < 0 && sum[i][j] - sum[i - k][j] == k * k) maxx = max(maxx, k);
					else if (i-k>=0 && j-k>=0 && sum[i][j] - sum[i - k][j] - sum[i][j - k] + sum[i - k][j - k] == k * k) {
						//說明是一個正方形
						maxx = max(maxx, k);
					}
					else if (i - k < 0 && j - k < 0 && sum[i][j] == k * k) maxx = max(maxx, k);
				}
			}
		}
	}
	return maxx * maxx;
}
int main() {
	vector<vector<char> > matrix = { {'1','1'},{'1','1'}};
	int res=maximalSquare2(matrix);
	cout << res << endl;
	return 0;
} 

84. Largest Rectangle in Histogram

Hard

287770Add to ListShare

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.


Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].


The largest rectangle is shown in the shaded area, which has area = 10 unit.

Example:

Input: [2,1,5,6,2,3]
Output: 10
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
/*84. Largest Rectangle in Histogram
1.dp[i][j]存儲從i到j最小數值,內存不夠了*/
int largestRectangleArea1(vector<int>& heights) {
	if (heights.size() == 0) return 0;
	vector<vector<int> > dp(heights.size(), vector<int>(heights.size()));
	int max = 0;
	for (int i = 0; i < heights.size(); i++) {
		dp[i][i] = heights[i];
		if (max < dp[i][i]) max = dp[i][i];
	}
	for (int i = 0; i < heights.size(); i++) {
		for (int j = i + 1; j < heights.size(); j++) {
			if (heights[j] < dp[i][j - 1]) dp[i][j] = heights[j];
			else dp[i][j] = dp[i][j - 1];
			if (max < dp[i][j] * (j - i + 1)) max = dp[i][j] * (j - i + 1);
		}

	}
	return max;
}
/*2.遍歷數組,每找到一個數字大於後面的數字(局部峯值),
就向前遍歷所有值,算出共同矩形面積。
爲何從局部峯值處理:例如在[2,1,5,6,2,3]中,
局部峯值是2,6,3,非局部峯值的情況,局部峯值都可以包括,
例如1和5能組成的,到6都能組成,再加上6還能形成更大的。
Runtime: 12 ms, faster than 86.03% of C++ online submissions for Largest Rectangle in Histogram.
Memory Usage: 9.4 MB, less than 100.00% of C++ online submissions for Largest Rectangle in Histogram.*/
int largestRectangleArea2(vector<int>& heights) {
	int n = heights.size();
	if (n == 0) return 0;
	heights.push_back(0);
	int maxx = 0;
	for (int i = 0; i < n; i++) {
		if (heights[i] > heights[i + 1]) {
			int minn = heights[i];
			maxx = max(maxx, minn);
			for (int j = i-1; j >= 0; j--) {
				minn = min(heights[j], minn);
				maxx = max(maxx, minn*(i-j + 1));
			}
		}
	}
	return maxx;
}
/*3.維護一個棧,用來保存遞增序列,相當於第二種方法中找局部峯值。
遞增棧:維護遞增順序,遇到小於棧頂的就要處理
遞減棧:維護遞減順序,遇到大於棧頂的開始處理
所以應當維護遞增棧,當遇到小於棧頂的元素,就要開始計算舉行面積了
由於棧頂是矩形高度,那麼下面需要求寬度,所以單調棧中不能放高度,而是需要座標,
從而可以直接計算出寬度
Runtime: 8 ms, faster than 98.53% of C++ online submissions for Largest Rectangle in Histogram.
Memory Usage: 9.6 MB, less than 100.00% of C++ online submissions for Largest Rectangle in Histogram.*/
int largestRectangleArea(vector<int>& heights) {
	heights.push_back(0);
	int n = heights.size();
	if (n == 1) return 0;
	stack<int> s;
	int maxx = 0;
	for (int i = 0; i < n; ++i) {
		if (s.empty() || heights[i] > heights[s.top()]) s.push(i);
		else {
			int top = s.top();s.pop();
			if (s.empty()) maxx = max(maxx, heights[top] * i);
			else  maxx = max(maxx, heights[top] * (i - s.top() - 1));	
			--i;
		}
	}
	return maxx;
}
int main() {
	vector<int> nums = { 1,1 };

	cout << largestRectangleArea(nums)<< endl;
	return 0;
} 

85. Maximal Rectangle

Hard

215357Add to ListShare

Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.

Example:

Input:
[
  ["1","0","1","0","0"],
  ["1","0","1","1","1"],
  ["1","1","1","1","1"],
  ["1","0","0","1","0"]
]
Output: 6
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
/*85. Maximal Rectangle
每個層向上可以是一個直方圖,計算每一層直方圖的最大面積
Runtime: 44 ms, faster than 16.66% of C++ online submissions for Maximal Rectangle.
Memory Usage: 10.6 MB, less than 100.00% of C++ online submissions for Maximal Rectangle.*/
int maximalRectangle(vector<vector<char>>& matrix) {
	if (matrix.size() == 0 || matrix[0].size() == 0) return 0;
	int n = matrix.size(), m = matrix[0].size();
	vector<int> dp(m+1);//記錄上一層的直方圖數組
	int res = 0;
	for (int i = 0; i < n; i++) {
		//對每一層構建例如84題的那種一位數組,從而構建每一層的直方圖,求出每一層的最大面積
		for (int j = 0; j < m; j++) {
			if (matrix[i][j] == '0') dp[j] = 0;
			else dp[j] += 1;
		}
		int maxx = 0;
		stack<int> s;
		for (int j = 0; j <=m; j++) {
			if (s.empty() || dp[j] > dp[s.top()]) s.push(j);
			else {
				int top = s.top(); s.pop();
				if (s.empty()) maxx = max(maxx, dp[top] * j);
				else maxx = max(maxx, dp[top] * (j - s.top() - 1));
				j--;
			}
		}
		res = max(maxx, res);
	}
	return res;
}
int main() {
	vector<vector<char> > matrix = { {'1','0','1','0','0'},{'1','0','1','1','1'},
									{'1', '1','1','1','1'} ,{'1','0','0','1','0'} };
	int res = maximalRectangle(matrix);
	cout << res;
	return 0;
} 

4. Median of Two Sorted Arrays

Hard

6037918Add to ListShare

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

You may assume nums1 and nums2 cannot be both empty.

Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0

Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5
#include"pch.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
/*4. Median of Two Sorted Arrays
兩個有序數組的中位數,時間複雜度爲 O(log (m+n)),二分法
如果有序數組長度是奇數,中位數就是中間那個,如果是偶數,就是中間兩個數的平均值
設兩個有序數組長度爲n和m,長度之和爲n+m,
分別找第 (m+n+1) / 2 個,和 (m+n+2) / 2 個,然後求其平均值即可,這對奇偶數均適用。
若 m+n 爲奇數的話,那麼其實 (m+n+1) / 2 和 (m+n+2) / 2 的值相等,
相當於兩個相同的數字相加再除以2,還是其本身。
如何在兩個有序數組中找到第K個元素:對K二分,分別在兩個數組中找第K/2個元素,
需要檢查一下,是否有第K/2個元素,如果有,就取出來,如果沒有,就賦整型最大值,
比如 nums1 = {3},nums2 = {2, 4, 5, 6, 7},K=4,要找兩個數組中的第4個數字,
首先先在nums1和nums2中找第2個數字,而nums1中只有1個數字,沒有第2個數字,所以nums2中的前2個數字可以直接跳過,
因爲要求在兩個數組中找第4個數字,不管nums1中的數字有多大,第4個數字都不會在nums2的前兩個數字中
Runtime: 20 ms, faster than 71.56% of C++ online submissions for Median of Two Sorted Arrays.
Memory Usage: 8.9 MB, less than 100.00% of C++ online submissions for Median of Two Sorted Arrays.
https://www.cnblogs.com/grandyang/p/4465932.html*/
int findKth(vector<int>&nums1, int i, vector<int>&nums2, int j, int K) {
	if (i >= nums1.size()) return nums2[K + j - 1];
	if (j >= nums2.size()) return nums1[K + i - 1];
	if (K == 1) return min(nums1[i], nums2[j]);
	int midVal1, midVal2;
	if (i + K / 2 - 1 >= nums1.size()) midVal1 = INT_MAX;
	else midVal1 = nums1[i + K / 2 - 1];
	if (j + K / 2 - 1 >= nums2.size()) midVal2 = INT_MAX;
	else midVal2 = nums2[j + K / 2 - 1];
	if (midVal1 < midVal2) return findKth(nums1, i + K / 2, nums2, j, K - K / 2);
	else return findKth(nums1, i, nums2, j + K / 2, K - K / 2);
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
	int m = nums1.size(), n = nums2.size(), left = (m + n + 1) / 2, right = (m + n + 2) / 2;
	return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
}
int main() {
	vector<int> nums1 = { 1,3 };
	vector<int> nums2 = { 2 };
	cout << findMedianSortedArrays(nums1, nums2);
	return 0;
} 

295. Find Median from Data Stream

Hard

198338Add to ListShare

Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.

For example,

[2,3,4], the median is 3

[2,3], the median is (2 + 3) / 2 = 2.5

Design a data structure that supports the following two operations:

  • void addNum(int num) - Add a integer number from the data stream to the data structure.
  • double findMedian() - Return the median of all elements so far.

Example:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3) 
findMedian() -> 2

Follow up:

  1. If all integer numbers from the stream are between 0 and 100, how would you optimize it?
  2. If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it?
class MedianFinder {
public:
    /** initialize your data structure here. 
    數據流中的中位數,先使其有序,使用大小堆(都是大頂堆),大堆保存右半部分較大的數字,
    小堆保存左半部分較小的數字,這樣數組就被一分爲二,當大、小堆元素數量相同時,
    去首元素平均值,當小堆元素較多時,取小堆堆首。
    從大堆和小堆取出的數字都是從大到小,因爲都是默認的大頂堆,
    每新來一個數字,先插入小堆,此時小堆堆首就是偏小的那半部分的數字中最大的,
    將小堆堆首(存入相反數)插入大堆(這樣,大堆存放的都是相反數,
    大堆堆頂是相反數中最大的,就是原數字中最小的),並且將小堆堆首出堆,
    此時,比較兩個堆的大小,如果小堆size小於大堆,則將大堆中的最小的移動到小堆中。
    使用priority_queue和multiset能實現相同功能。
    Runtime: 184 ms, faster than 26.48% of C++ online submissions for Find Median from Data Stream.
    Memory Usage: 41.8 MB, less than 100.00% of C++ online submissions for Find Median from Data Stream.*/
    MedianFinder() {
        
    }
    
    void addNum(int num) {
        small.push(num);
        large.push(-small.top());
        small.pop();
        if(small.size()<large.size()){
            small.push(-large.top());
            large.pop();
        }
    }
    
    double findMedian() {
        if(small.size()>large.size()) return small.top();
        else return 0.5*(small.top()-large.top());
    }
private:
    priority_queue<long> small,large;
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder* obj = new MedianFinder();
 * obj->addNum(num);
 * double param_2 = obj->findMedian();
 */

 

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