1. 程式人生 > >leetCode解題報告5道題(十)

leetCode解題報告5道題(十)

ddl peek path sum ron 表示 bar largest ger 不能

題目一:Valid Number

Validate if a given string is numeric.

Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true

Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.


分析:

這道題目非常easy理解,可是主要要考慮到多種情況哈.

以下我們來分析下有哪些情況須要考慮到

1、空格不能出如今數字之間(即一開始我們要消除掉字符串前後的"空格",那麽之後假設再出現空格那就不滿足題意了)

2、小數點和e最多僅僅能出現一次("." 和"e" (或者"E")), 如:"..2"和"0e1e1"這種字符串都是不合法的.

3、字符e之前必須有數字。e之後也要有數字, 如: "e1"或者"0e"這種字符串也不合法

4、正負號要麽出如今數字的最前面,要麽出如今緊接著e後面("+"或者"-" 僅僅能在“去除空格之後的字符串”的首字母出現 或者 緊跟在"e"的後面出現) 如: " +123.1 " 或者 " -12 " 或者 " 0e+6 "或者" 10e-2 "這些都是合法的

5、"e"後面的數字不能是小數(即e之後不能出現小數點)


分析完這些全部的情況。那麽我們就能夠開始寫代碼了。看代碼理解吧~~~~


AC代碼:

public class Solution {
    public boolean isNumber(String s) {
        
        int start = 0;
        int len = s.length();
        int end = len-1;
        boolean flags = false;//直到處理到當前字符的時候是合法(true)還是非法(false)
        boolean exitsE = false;//是否已經存在“e”
        int doin = 0;   //小數點的個數
        //去除前面的空格 ‘ ‘
        while (start < len){
            if (s.charAt(start) == ‘ ‘){
                start++;
            }else{
                break;
            }
        }
        //去除後面的空格 ‘ ‘
        while (end >= 0){
            if (s.charAt(end) == ‘ ‘){
                end--;
            }else{
                break;
            }
        }
        //從第一個不是空格的位置開始。到最後一個不是空格的位置
        for (int index=start; index<=end; ++index){
            char c = s.charAt(index);
            //假設開頭是"+"或者"-", 那麽是能夠的。~~~ O(∩_∩)O
            if (index == start && (s.charAt(index) == ‘-‘ || s.charAt(index) == ‘+‘)){
                continue;
            }
            //假設"+"或者"-"緊跟在"e"或者“E”之後也是能夠的!

if ((s.charAt(index) == ‘-‘ || s.charAt(index) == ‘+‘) && (s.charAt(index-1) == ‘e‘ || s.charAt(index-1) == ‘E‘)){ flags = false; }else if(!((c >= ‘0‘ && c <= ‘9‘) || c == ‘.‘ || c == ‘e‘ || c == ‘E‘)){ //除了上面的"+"和"-"之外,假設字符不滿足在 0~9 或者 . 或者 e 或者 E中的一個的話,則不合法 return false; }else{ //假設遇到數字flags則設為合法 if ((c >= ‘0‘ && c <= ‘9‘)){ flags = true; }else if (c == ‘e‘ || c == ‘E‘){ //假設exitsE==true 表示之前的字符串已經出現過 e 或者 "E" 了,這樣就有兩個e了,不合法 if (exitsE){ return false; } exitsE = true; //假設flags == true,表示前面有出現過數字 if (flags){ flags = false;//在把flags設置為false, 用來推斷e之後是否還有出現數字 }else{ return false; } }else if (c == ‘.‘){ //e後面的數字必須是整數,則假設小數點在e之後的話,直接不合法 if (exitsE){ return false; } //假設小數點的個數大於1則不合法 doin++; if (doin > 1) return false; }else{ } } } return flags; } }



題目二:Jump Game

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Determine if you are able to reach the last index.

For example:
A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false.

分析:

這道題目的意思挺easy理解的,我們主要講下解法:

老規矩,我喜歡通過樣例來說明解法哈,假設 A=[2, 0, 2, 0, 1] len = A.length;

我們先從第一個位置A[0]開始,然後我們用一個pos來記錄如今第一個位置所能到達的最遠距離。

pos = A[0] = 2;

然後我們用一個index (index < len)來記錄當前的下標位置,第一個A[0]處理了之後 index++,

假設index > pos 則表示如今這個index的位置已經是 第一個元素所不能到達的地方了,這樣子的話就不可能走到最後一個元素,則返回false

假設index <= pos 則 假設 A[index] + i > pos (第一個元素能走到更遠的位置了),更新一下pos的值。


AC代碼:

public class Solution {
    public boolean canJump(int[] A) {
        int len = A.length;
        int index = 0;
        int pos = 0;//第一個元素能到的位置
        while (index < len){
            if (pos < index){
                //beyond
                return false;
            }else{
                //before or equals pos
                if (A[index] + index > pos){
                    pos = A[index] + index;
                }
            }
            index++;
        }
        return true;
    }
}


題目三:Jump Game II

Given an array of non-negative integers, you are initially positioned at the first index of the array.

Each element in the array represents your maximum jump length at that position.

Your goal is to reach the last index in the minimum number of jumps.

For example:
Given array A = [2,3,1,1,4]

The minimum number of jumps to reach the last index is 2. (Jump 1 step from index 0 to 1, then 3 steps to the last index.)

分析:

這題跟上面的那道題比較像。僅僅只是有點像貪心法,每一步都要走最遠的那種情況,所以每一次我們都須要把全部能走到的全部位置先走一遍,看哪個最遠。


AC代碼:

public class Solution {
    public int jump(int[] A) {
        int len = A.length;
        if (len == 1)
            return 0;
            
        int max = A[0];
        int index = 1;
        int pos = A[0];
        int n = 1;
        
        while (index < len){
            if (pos >= len-1){
                break;//假設pos已經能夠到最後一個位置的話,結束
            }
            //before or equals pos
            if (A[index] + index > max && index <= pos){
                max = A[index] + index;//記錄最大值
            }
            
            if (index == pos){
                if (max > pos){
                    pos = max;
                    n++;
                }
            }
            index++;
        }
        return n;
    }
}


題目四:Minimum Path Sum

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.

分析:

這道題目能夠看做是一個動態規劃的題目吧,我們舉個樣例

假設grid[][]=

1 2 3 4

7 8 1 3

2 5 6 10

我們從右下方的元素開始,往前推

當我們推斷到 grid[2][2] == 6 時。它到右下方結點的距離為 6 + 10 = 16。 存入grid[2][2]=16;

當我們推斷到 10 上方的那個元素 grid[1][3] == 3時,它到右下方結點的距離為 3 + 10 = 13, 存入grid[1][3]=13;

當推斷到 grid[1][2] == 1時。 它到右下方的距離,就是 grid[1][3] 和 grid[2][2]中比較小的那個值 再加上自身的值。即grid[1][2] += min{grid[1][3] (當前元素右邊的元素) , grid[2][2] (當前元素下邊的元素)};


AC代碼:

public class Solution {
    public int minPathSum(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        for (int row=m-1; row>=0; row--){
            for (int col=n-1; col>=0; col--){
                //右邊的列的下標
                int colRight = col + 1;
                //下邊的行的行標
                int rowDown = row + 1;
                //初始值
                int rowDownValue = Integer.MAX_VALUE;
                int colRightValue = Integer.MAX_VALUE;
                
                //存在行
                if (rowDown < m){
                    rowDownValue = grid[rowDown][col];
                }
                //存在列
                if (colRight < n){
                    colRightValue = grid[row][colRight];
                }
                //取最小
                int min = rowDownValue > colRightValue ? colRightValue : rowDownValue;
                //最小等於Integer.MAX_VALUE則表示沒有右邊也沒有下邊元素,即為右下方的那個目標元素
                if (min != Integer.MAX_VALUE){
                    grid[row][col] += min;
                }
            }
        }
        return grid[0][0];
    }
}



題目五: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.

技術分享

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.

For example,
Given height = [2,1,5,6,2,3],
return 10.

分析:

1、暴力法:

初看題目。非常easy給人想到的方法就是暴力法,也就是說對每一個 index < len 都找到從index 往左 和 往右,直到height[index] > height[left] 和 height[index] > height[right], 然後 把int temp = height[index] * (right - left + 1) 。 假設temp > max, 則更新max的值,可是這種話一下子就TLE超時了。

TLE代碼:

public class Solution {
    public int largestRectangleArea(int[] height) {
        int len = height.length;
        int max = Integer.MIN_VALUE;
        for (int i=0; i<len; ++i){
            int nowHeight = height[i];
            int left=i-1;
            while (left>=0){
                if (height[left] < nowHeight){
                    break;
                }
                --left;
            }
            int right=i+1;
            while (right<len){
                if (height[right] < nowHeight){
                    break;
                }
                ++right;
            }
            
            int allSize = (right-left+1) * nowHeight;
            if (allSize > max){
                max = allSize;
            }
        }
        return max;
    }
}



2、借助輔助棧:

竟然暴力法不行。那我們能夠知道它基本的時間消耗事實上是在尋找左邊的left, 和右邊的right上面,這種話有沒有什麽辦法把這塊時間節省下來,在我們遍歷的過程中確定好left, right的值呢?

我們採用輔助棧( 棧中存放矩形的下標 )來做這道題目能夠解決它哈。

算法描寫敘述:

1、定義一個空棧

2、遍歷數組 index < n

2.1、遍歷到index的時候,假設“棧為空”或者height[stack.peek()] <= height[index], 這時候把 index 壓入到stack中,並index++

2.2、假設不滿足2.1的情況,那麽證明棧頂元素p相應的height值比當前index相應的height值來得小。這種話彈出棧頂元素,並算出以棧頂元素為height所能得到的最大的矩形面積。這時候就是用輔助棧的關鍵地方了,針對這個情況,它的left位置就是它在棧中的下一個位置(假設沒有,則表示left是0,即左邊界從0開始),而它的右邊界right位置就是當前index的值。

看到這裏,肯定迷糊了吧,想想僅僅有當 “棧為空”或者height[stack.peek()] <= height[index] 的時候我們才會把index值壓入棧中。也就是說假設把棧從上往下看,必然上面的值相應的height會比以下的大或者相等,這樣以下的那個元素相應的值就必然是left的值,同理由於當 當前height[stack.peek()] > height[index] , 我們才進行計算面積的工作,這樣子的話這個index就是stack.peek()取到的這個位置相應height 的right右邊界咯.


AC代碼:

public class Solution {
    public int largestRectangleArea(int[] height) {
        int len = height.length;
        if (len == 0)
            return 0;
        int max = Integer.MIN_VALUE;
        Stack<Integer> stack = new Stack<Integer>();
        int index = 0;
        while (index < len){
            if (stack.empty() || height[(int)stack.peek()] <= height[index]){
                stack.push(index);
                index++;//這裏才有++哦!

}else{ //計算面積 int popIndex = (int)stack.pop(); int allWidth = stack.empty() ? index : index-((int)stack.peek())-1; int tempValue = height[popIndex] * allWidth; if (tempValue > max){ max = tempValue; } } } //right邊界都為len while (!stack.empty()){ int popIndex = (int)stack.pop(); int allWidth = stack.empty() ? len : len-((int)stack.peek())-1; int tempValue = height[popIndex] * allWidth; if (tempValue > max){ max = tempValue; } } return max; } }


leetCode解題報告5道題(十)