leetcode-Container With Most Water

来源:互联网 发布:广州淘宝二手汽车网 编辑:程序博客网 时间:2024/06/05 08:51

题目
Given n non-negative integers a1, a2, …, an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container.

一开始的代码

nt maxArea(int* height, int heightSize) {    int max = 0;    if(heightSize == 0 || heightSize == 1){        return 0;    }    for(int i = 0; i < heightSize; i++){        for(int j = i + 1; j < heightSize; j++){            int row = j - i;            int col = height[j] < height[i] ? height[j] : height[i];            int area = row * col;            max = max > area ? max : area;        }    }    return max;}

复杂度为O(N2)超时了

2.0版本,还是超时,不过不是之前的超时用例了

int maxArea(int* height, int heightSize) {    int max = 0;    if(heightSize == 0 || heightSize == 1){        return 0;    }    for(int i = 0; i < heightSize; i++){        if(i <= heightSize / 2){//距离右端远            int j = heightSize - 1;            while(j > i){//从右开始,找到高度大于i的第一个也是最远的j                if(height[j] >= height[i]){                    //printf("%d * %d | ", height[i], j -i);                    max = max > (height[i] * (j - i)) ? max : height[i] * (j - i);                    break;                }                else{                    j--;                }            }            if(j - i < i){//右端的距离小于左端最远的距离,则左端可能存在大于目前面积的列,检查左端                int k = 0;                while(k < i && i - k > j - i){                    if(height[k] >= height[i]){                        //printf("%d * %d | ", height[i], i-k);                        max = max > (height[i] * (i - k)) ? max : height[i] * (i - k);                        break;                    }                    else{                        k++;                    }                }            }        }        else{//距离左端远,同上            int j = 0;            while(j < i){                if(height[j] >= height[i]){                    //printf("%d * %d | ", height[i], i-j);                    max = max > (height[i] * (i - j)) ? max : height[i] * (i - j);                    break;                }                else{                    j++;                }            }            if(i - j < heightSize - i - 1){                int k = heightSize - 1;                while(k > i && k - i > i - j){                    if(height[k] >= height[i]){                        //printf("%d * %d | ", height[i], k -i);                        max = max > (height[i] * (k - i)) ? max : height[i] * (k - i);                        break;                    }                    else{                        k--;                    }                }            }        }    }    return max;}

3.0版,想到在上个版本上更进一步的简便方法,循环时多加个判断条件,可以少判断几次

int maxArea(int* height, int heightSize) {    int max = 0;    if(heightSize == 0 || heightSize == 1){        return 0;    }    for(int i = 0; i < heightSize; i++){        if(height[i] == 0){            continue;        }        if(i <= (heightSize - 1) / 2){//距离右端远            int j = heightSize - 1;            while(j > i && ((j - i) > max / height[i])){//从右开始,找到高度大于i的第一个也是最远的j                if(height[j] >= height[i]){                    //printf("%d * %d | ", height[i], j -i);                    max = max > (height[i] * (j - i)) ? max : height[i] * (j - i);                    break;                }                else{                    j--;                }            }            if(j - i < i){//右端的距离小于左端最远的距离,则左端可能存在大于目前面积的列,检查左端                int k = 0;                while(k < i && i - k > j - i){                    if(height[k] >= height[i]){                        //printf("%d * %d | ", height[i], i-k);                        max = max > (height[i] * (i - k)) ? max : height[i] * (i - k);                        break;                    }                    else{                        k++;                    }                }            }        }        else{//距离左端远,同上            int j = 0;            while(j < i && ((i - j) > max / height[i])){                if(height[j] >= height[i]){                    //printf("%d * %d | ", height[i], i-j);                    max = max > (height[i] * (i - j)) ? max : height[i] * (i - j);                    break;                }                else{                    j++;                }            }            if(i - j < heightSize - i - 1){                int k = heightSize - 1;                while(k > i && k - i > i - j){                    if(height[k] >= height[i]){                        //printf("%d * %d | ", height[i], k -i);                        max = max > (height[i] * (k - i)) ? max : height[i] * (k - i);                        break;                    }                    else{                        k--;                    }                }            }        }    }    return max;}

还是未通过,当测试用例为倒序时,遍历的次数还是会较多,因此改下算法,先算下用例大概为升序还是降序,若为升序则从左向右开始遍历,若为降序,则从右开始向左遍历。
改完了,还是未过…只好根据测试用例,采用暴力破解了

int maxArea(int* height, int heightSize) {    int max = 0;    if(heightSize == 0 || heightSize == 1){        return 0;    }    int asc = 1;    for(int i = 1; i < heightSize; i++){        if(height[i] < height[i - 1]){            asc = 0;            break;        }    }    if(asc == 1){//升序数列        for(int i = 0; i < heightSize; i++){            max = max > (heightSize - i - 1) * height[i] ? max : (heightSize - i - 1) * height[i];        }        return max;    }    int desc = 1;    for(int i = 0; i < heightSize; i++){        if(i == heightSize - 1){            if(height[i] > height[i - 1]){                desc = 0;                break;            }        }        else{            if(height[i] < height[i + 1]){                desc = 0;                break;            }        }    }    if(desc == 1){        for(int i = heightSize - 1; i >= 0; i--){            max = max > i * height[i] ? max : i * height[i];        }        return max;    }    if(asc >= 0){        for(int i = 0; i < heightSize; i++){            if(height[i] == 0){                continue;            }            if(i <= (heightSize - 1) / 2){//距离右端远                int j = heightSize - 1;                while(j > i && ((j - i) > max / height[i])){//从右开始,找到高度大于i的第一个也是最远的j                    if(height[j] >= height[i]){                        //printf("%d * %d | ", height[i], j -i);                        max = max > (height[i] * (j - i)) ? max : height[i] * (j - i);                        break;                    }                    else{                        j--;                    }                }                if(j - i < i){//右端的距离小于左端最远的距离,则左端可能存在大于目前面积的列,检查左端                    int k = 0;                    while(k < i && i - k > j - i){                        if(height[k] >= height[i]){                            //printf("%d * %d | ", height[i], i-k);                            max = max > (height[i] * (i - k)) ? max : height[i] * (i - k);                            break;                        }                        else{                            k++;                        }                    }                }            }            else{//距离左端远,同上                int j = 0;                while(j < i && ((i - j) > max / height[i])){                    if(height[j] >= height[i]){                        //printf("%d * %d | ", height[i], i-j);                        max = max > (height[i] * (i - j)) ? max : height[i] * (i - j);                        break;                    }                    else{                        j++;                    }                }                if(i - j < heightSize - i - 1){                    int k = heightSize - 1;                    while(k > i && k - i > i - j){                        if(height[k] >= height[i]){                            //printf("%d * %d | ", height[i], k -i);                            max = max > (height[i] * (k - i)) ? max : height[i] * (k - i);                            break;                        }                        else{                            k--;                        }                    }                }            }        }    }    else{printf("new algo");        for(int i = heightSize - 1; i >= 0 ; i--){            if(height[i] == 0){                continue;            }            if(i >= (heightSize - 1) / 2){                int j = 0;                while(j < i && (i - j) > max / height[i]){                    if(height[j] >= height[i]){                        max = max > (height[i] * (i - j)) ? max : height[i] * (i - j);                        break;                    }                    else{                        j++;                    }                }                if(i - j < heightSize - i - 1){                    int k = heightSize - 1;                    while(k > i && k - i > i - j){                        if(height[k] >= height[i]){                            max = max > (height[i] * (k - i)) ? max : height[i] * (k - i);                            break;                        }                        else{                            k--;                        }                    }                }            }            else{                int j = heightSize - 1;                while(j > i && ((j - i) > max / height[i])){//从右开始,找到高度大于i的第一个也是最远的j                    if(height[j] >= height[i]){                        //printf("%d * %d | ", height[i], j -i);                        max = max > (height[i] * (j - i)) ? max : height[i] * (j - i);                        break;                    }                    else{                        j--;                    }                }                if(j - i < i){//右端的距离小于左端最远的距离,则左端可能存在大于目前面积的列,检查左端                    int k = 0;                    while(k < i && i - k > j - i){                        if(height[k] >= height[i]){                            //printf("%d * %d | ", height[i], i-k);                            max = max > (height[i] * (i - k)) ? max : height[i] * (i - k);                            break;                        }                        else{                            k++;                        }                    }                }            }        }    }    return max;}

观察测试用例,发现超时的用例要么是升序,要么是降序,因此,在最开始判断用例是升序还是降序,然后相应的遍历一次解决…
嗯,这是个投机取巧的方法,纯粹只是为了通过题目而已..
不过根据原来的算法,其实也才300ms左右,也算过了吧~哈哈
代码中我觉的有大量冗余的地方,但是懒得改了,就放在那里了

0 0
原创粉丝点击