几何问题的解法也没什么固定模式
题目一:Max Points on a Line http://oj.leetcode.com/problems/max-points-on-a-line/
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
思路:统计每个点到其他所有点的泄漏,统计相同斜率的个数最大值。斜率有两种情况:非无穷大和无穷大。分两种情况讨论。另外可能存在坐标相同的点。其次一个重要的观察是在同一条直线上的任意两个点之间的斜率相同。
/**
* Definition for a point.
* struct Point {
* int x;
* int y;
* Point() : x(0), y(0) {}
* Point(int a, int b) : x(a), y(b) {}
* };
*/
class Solution {
public:
int countEqualNum(vector<double>& slope){
int maxNum=0;
int num=1;
if(slope.size()==0) return maxNum;
sort(slope.begin(), slope.end());
for(int i=1;i<slope.size();i++){
if(slope[i]==slope[i-1]) num++;
else{
if(num>maxNum) maxNum=num;
num=1;
}
}
if(num>maxNum) maxNum=num; //****
return maxNum+1;
}
int maxPoints(vector<Point> &points) {
if(points.size()==0 || points.size()==1) return points.size();
vector<int> x;
int maxNum=0;
vector<double> slope;
for(int i=0;i<points.size();i++){
int num=1;
int num2=0;
for(int j=i+1;j<points.size();j++){
if(points[j].x!=points[i].x){
double tmp=(points[j].y-points[i].y)*1.0/(points[j].x-points[i].x);
slope.push_back(tmp);
}
else{
if(points[j].y==points[i].y) num2++;
num++;
}
}
int localmax=countEqualNum(slope)+num2;
localmax=max(localmax, num);
if(localmax>maxNum) maxNum=localmax;
slope.clear();
}
return maxNum;
}
};
题目二:Triangle http://oj.leetcode.com/problems/triangle/
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
思路:利用DP的思想,用数组保存当前行中每个位置的path sum的最小值。
class Solution {
public:
int minimumTotal(vector<vector<int> > &triangle) {
int res=1<<8;
vector<int> sum(triangle.size(), 1<<12);
vector<int> num(triangle.size(), 1<<12);
num[0]=sum[0]=triangle[0][0];
for(int i=1;i<triangle.size();i++){
for(int j=0;j<triangle[i].size();j++){
if(j==0) sum[j]=num[j]+triangle[i][j];
else if(j==triangle[i].size()-1) sum[j]=num[j-1]+triangle[i][j];
else sum[j]=triangle[i][j]+min(num[j-1], num[j]);
}
for(int j=0;j<triangle[i].size();j++)
num[j]=sum[j];
}
for(int i=0;i<triangle.size();i++){
if(res>num[i]) res=num[i];
}
return res;
}
};
上面两道题都还算比较简单,现在来上两道有意思的题。
题目三:Largest Rectangle in Histogram http://oj.leetcode.com/problems/largest-rectangle-in-histogram/
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.
思路:我想了一许久都没想到很好的方法,最后求助了discussion。版主给了一个非常有意思的解法。把每个柱子都当做最低去求面积。每当出现一个比自己低的柱子,就计算之前柱子形成的最大面积,否则让当前柱子编号入栈(编号入栈比高度入栈好,为什么呢?),因为求面积要求柱子是连续的,保留开始与结束柱子的编号即可!有两种写法
//写法一:利用额外添加的高度为0的柱子
class Solution {
public:
int largestRectangleArea(vector<int> &height) {
int n=height.size();
if(n==0) return 0;
int maxArea=0;
int curArea=0;
stack<int> hg;
height.push_back(0); //额外添加0,保证最后一个柱子的面积也能算到
int i=0;
while(i<=n){
if(hg.empty() || height[hg.top()] <= height[i])
hg.push(i++);
else{
while(!hg.empty()&&height[hg.top()]>height[i]){
int top_min=hg.top();
hg.pop();
curArea=height[top_min]*(hg.empty()?i:i-hg.top()-1);
if(curArea>maxArea) maxArea=curArea;
}
hg.push(i); //将hg.top()] <= height[i]条件的柱子入栈
}
}
return maxArea;
}
};
//解法二,额外处理最后的柱子
class Solution {
public:
int largestRectangleArea(vector<int> &height) {
int n=height.size();
if(n==0) return 0;
int maxArea=0;
int curArea=0;
stack<int> hg;
int i=0;
while(i<n){
if(hg.empty() || height[hg.top()] <= height[i])
hg.push(i++);
else{
int top_min=hg.top();
hg.pop();
curArea=height[top_min]*(hg.empty()?i:i-hg.top()-1);
if(curArea>maxArea)
maxArea=curArea;
}
}
while(!hg.empty()){
int top_min=hg.top();
hg.pop();
curArea=height[top_min]*(hg.empty()?i:i-hg.top()-1);
if(curArea>maxArea)
maxArea=curArea;
}
return maxArea;
}
};
题目四:Maximal Rectangle http://oj.leetcode.com/problems/maximal-rectangle/
Given a 2D bianry matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area
思路:我毫无思路。求助于discussion。一位机智的小伙伴利用上面求maximal histogram area的方法求这道题。把每列当做是一个水柱,如果为'1',则柱子高度加上1,如果为'0',则柱子高度清零(柱子断开了,当然得为零)。
class Solution {
public:
int maximalRectangle(vector<vector<char> > &matrix) {
const int m=matrix.size();
if(m==0) return 0;
const int n=matrix[0].size();
int maxarea=0;
int height[n+1];
memset(height,0,sizeof(height));
for(int i=0; i<m; i++){
stack<int> pstack; //该方法中最重要的数据结构,可以得到当前值附近的值
for(int j=0; j<=n; j++){
if(j<n){ //统计当前行中每一列的高度
if(matrix[i][j]=='1')
height[j]+=1;
else height[j]=0;
} //计算面积
if(pstack.empty() || height[pstack.top()]<=height[j]){
pstack.push(j);
}
else{
while(!pstack.empty()&&height[pstack.top()]>height[j]){
int top=pstack.top();
pstack.pop();
int area=height[top]*(pstack.empty()?j:(j-pstack.top()-1));
if(area>maxarea) maxarea=area;
}
pstack.push(j);
}
}
}
return maxarea;
}
};
说明:这道题无法像上面那道题那样有两种解法,只能遇到一个比当前栈顶小的高度,利用while循环求出以当前栈中所有元素为最低值的面积,然后再进行到下一列。
题目五:Trapping Rain Water http://oj.leetcode.com/problems/trapping-rain-water/
Given n non-negative integers representing an elevating map where the width of each bar is 1, compute how much water it is able to trap after rainning.
思路一:之前想偏了,想了一个繁琐但是直接的方法,就是顺序扫描数字,找到valley点,求积水。和前面利用stack求面积一样。暂时没实现。。
思路二:利用求反的思想,把总的面积减去block的面积,得到积水的面积。具体是两个指针往中间走,如果当前的两者最低值小于current water level(初始值为0),则求积水面积。否则移动左边或者右边的index,并计算block数。
class Solution {
public:
int trap(int A[], int n) {
int block=0, cur=0, l=0, r=n-1, vol=0;
if(n==0) return 0;
while(l<=r){
int minVal=min(A[l],A[r]);
if(minVal>cur){
vol=vol+(minVal-cur)*(r-l+1);
cur=minVal;
}
if(A[l]<A[r]) block+=A[l++];
else block+=A[r--];
}
return vol-block;
}
};