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;
}
}