63. 不同路径 II
64. 最小路径和
66. 加一
68. 文本左右对齐
69. x 的平方根
------------------------------分割线-----------------------------------
63. 不同路径 II
Difficulty: 中等
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1
和 0
来表示。
说明:m 和 n 的值均不超过 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;
}
}