7月5日的五题leetcode

63. 不同路径 II

64. 最小路径和

66. 加一

68. 文本左右对齐

69. x 的平方根

------------------------------分割线-----------------------------------

63. 不同路径 II

Difficulty: 中等

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 10 来表示。

说明:mn 的值均不超过 100。

示例 1:

输入:
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1\. 向右 -> 向右 -> 向下 -> 向下
2\. 向下 -> 向下 -> 向右 -> 向右

Solution:动态规划

class Solution {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m, n;
        m = obstacleGrid.length;
        if(m == 0) return 0;
        n = obstacleGrid[0].length;
        if(n == 0) return 0;

        int[][] dp = new int[m][n];
        if(obstacleGrid[0][0] == 1) return 0;
        dp[0][0] = 1;

        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(obstacleGrid[i][j] == 1) dp[i][j] = 0;  //遇到障碍物,直接为0
                else if(i==0 && j==0) continue;
                else if(i==0){
                    dp[i][j] = dp[i][j-1];
                }
                else if(j == 0){
                    dp[i][j] = dp[i-1][j];
                }
                else{
                    dp[i][j] = dp[i-1][j] + dp[i][j-1];
                }
            }
        }
        return dp[m-1][n-1];
    }
}

64. 最小路径和

Difficulty: 中等

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

**说明:**每次只能向下或者向右移动一步。

示例:

输入:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

Solution:动态规划

class Solution {
    public int minPathSum(int[][] grid) {
        int m, n;
        m = grid.length;
        if(m<=0) return 0;
        n = grid[0].length;
        if(n<=0) return 0;

        int[][] dp = new int[m][n];
        dp[0][0] = grid[0][0];

        for(int i=0; i<m; i++){
            for(int j=0; j<n; j++){
                if(i==0 && j==0) continue;
                else if(i==0) dp[i][j] = grid[i][j]+dp[i][j-1];
                else if(j==0) dp[i][j] = grid[i][j]+dp[i-1][j];
                else{
                    dp[i][j] = grid[i][j] + Math.min(dp[i-1][j], dp[i][j-1]);
                }
            }
        }
        return dp[m-1][n-1];
    }
}

66. 加一

Difficulty: 简单

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。

示例 2:

输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。

Solution:看1这个数字,到底加在那个位置

//这个1到底应该加在哪里
class Solution {
    public int[] plusOne(int[] digits) {
        for(int i=digits.length-1; i>=0; i--){
            if(digits[i] != 9){         //不是9,直接加,然后返回
                digits[i] = digits[i]+1;
                return digits;  
            }
            else digits[i] = 0;
        }

        int[] res = new int[digits.length+1];
        res[0] = 1;
        for(int i=1; i<res.length; i++){
            res[i] = 0;
        }
        return res;
    }
}

68. 文本左右对齐

Difficulty: 困难

给定一个单词数组和一个长度 maxWidth,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。

你应该使用“贪心算法”来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。

要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。

文本的最后一行应为左对齐,且单词之间不插入额外的空格。

说明:

  • 单词是指由非空格字符组成的字符序列。
  • 每个单词的长度大于 0,小于等于 maxWidth
  • 输入单词数组 words 至少包含一个单词。

示例:

输入:
words = ["This", "is", "an", "example", "of", "text", "justification."]
maxWidth = 16
输出:
[
   "This    is    an",
   "example  of text",
   "justification.  "
]

示例 2:

输入:
words = ["What","must","be","acknowledgment","shall","be"]
maxWidth = 16
输出:
[
  "What   must   be",
  "acknowledgment  ",
  "shall be        "
]
解释: 注意最后一行的格式应为 "shall be    " 而不是 "shall     be",
     因为最后一行应为左对齐,而不是左右两端对齐。       
     第二行同样为左对齐,这是因为这行只包含一个单词。

示例 3:

输入:
words = ["Science","is","what","we","understand","well","enough","to","explain",
         "to","a","computer.","Art","is","everything","else","we","do"]
maxWidth = 20
输出:
[
  "Science  is  what we",
  "understand      well",
  "enough to explain to",
  "a  computer.  Art is",
  "everything  else  we",
  "do                  "
]

Solution:两个问题:1.每行需要放置多少的单词 2.每行的空格应该怎么放

import java.util.ArrayList;
import java.util.List;

//两个问题:1.每行需要放置多少的单词 2.每行的空格应该怎么放
class Solution {
    public List<String> fullJustify(String[] words, int maxWidth) {
        List<String> res = new ArrayList<>();
        List<String> temp = new ArrayList<>();
        StringBuilder str;
        int count = 0;
        for(int i=0; i<words.length; i++){
            //可以继续添加
            if(count+words[i].length() <= maxWidth){
                temp.add(words[i]);
                count += words[i].length();
                count++; //一个单词后面一个空格
            }
            //不能再添加
            else{
                int wordNum = count-temp.size();
                int blackNum = maxWidth-wordNum; //空格的个数
                str =  new StringBuilder();
                
                //只有一个元素,左对齐
                if(temp.size() == 1){
                    str.append(temp.get(0));
                    for(int j=0; j<maxWidth-temp.get(0).length(); j++){
                        str.append(" ");
                    }
                }
                //左右对齐
                else if(temp.size() > 1){
                    int x = blackNum/(temp.size()-1);
                    int y = blackNum%(temp.size()-1); //添加空格
                    for(int j=0; j<temp.size()-1; j++){
                        str.append(temp.get(j));
                        for(int p=0; p<x; p++){
                            str.append(" ");
                        }
                        if(y != 0){
                            str.append(" ");
                            y--;
                        }
                    }
                    str.append(temp.get(temp.size()-1)); //最后一个元素后面不加空格
                }

                //System.out.println("2str:"+str);
                res.add(str.toString());

                temp = new ArrayList<>();
                temp.add(words[i]);
                count = words[i].length() +1;
                //System.out.println("count:"+count);
            }
        }
        
        if(temp.size() > 0){   //最后一行
            str = new StringBuilder();
            for(int j=0; j<temp.size()-1; j++){
                str.append(temp.get(j)+" ");
            }
            str.append(temp.get(temp.size()-1));
            for(int j=0; j<maxWidth-count+1; j++){
                str.append(" ");
            }
            //System.out.println("3str:"+str);
            res.add(str.toString());
        }
        return res;
    }
}

69. x 的平方根

Difficulty: 简单

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:

输入: 4
输出: 2

示例 2:

输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 
     由于返回类型是整数,小数部分将被舍去。

Solution:二分法,注意越界

class Solution {
    public int mySqrt(int x) {
        if(x == 0 || x == 1) return x;
        int low = 0, high = x;
        while(low <= high){
            long mid = (high-low)/2 + low;   // mid容易越界
            if(mid*mid > x){
                if((mid-1)*(mid-1) < x) return (int)mid-1;
                else high = (int)mid-1;
            }
            else if(mid*mid == x){
                return (int)mid;
            }
            else{
                if((mid+1)*(mid+1) > x) return (int)mid;
                else low = (int)mid+1;
            }

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