刷题练习2021-12-15
数组拷贝:
int scores[] = new int[] { 57, 81, 68, 75, 91, 66, 75, 84 };
// 复制原数组的前5个元素到newScores数组中
int newScores[] = Arrays.copyOfRange(scores, 0, 5);
System.out.println(Arrays.toString(newScores));
数据结构:剑指 Offer 05. 替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = "We are happy."
输出:"We%20are%20happy."
限制:0 <= s 的长度 <= 10000
class Solution {
public String replaceSpace(String s) {
StringBuilder sb = new StringBuilder();
for(int i=0;i<s.length();i++) {
if(s.charAt(i)==' ') {
sb.append("%20");
} else {
sb.append(s.charAt(i));
}
}
return sb.toString();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
System.out.println(new Solution().replaceSpace(s));
}
}
动态规划:剑指 Offer 46. 把数字翻译成字符串
给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。
示例 1:
输入: 12258
输出: 5
解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"
提示:0 <= num < 231
递归:
class Solution {
public int translateNum(int num) {
return translateNum(String.valueOf(num));
}
public int translateNum(String s) {
if(s.length()<=1) return 1;
if(s.charAt(0)=='0') return translateNum(s.substring(1));
if(s.charAt(0)<'2'||(s.charAt(0)=='2'&&s.charAt(1)<='5')) return translateNum(s.substring(2))+translateNum(s.substring(1));
else return translateNum(s.substring(1));
}
}
包括路径的递归:
package cn.orzlinux.nettysource;
import java.util.*;
class Solution {
List<String> result = new LinkedList<>();
StringBuilder sb = new StringBuilder();
public List<String> translateNum(int num) {
translateNum(String.valueOf(num));
return result;
}
public void translateNum(String s) {
if(s.length()==0) {
result.add(sb.toString());
}
else if(s.length()==1||s.charAt(0)=='0') {
sb.append((char)(s.charAt(0)+'a'-'0'));
translateNum(s.substring(1));
sb.delete(sb.length()-1,sb.length());
}
else if(s.charAt(0)<'2'||(s.charAt(0)=='2'&&s.charAt(1)<='5')) {
sb.append((char)(Integer.parseInt(s.substring(0,2))+'a'));
translateNum(s.substring(2));
sb.delete(sb.length()-1,sb.length());
sb.append((char)(s.charAt(0)+'a'-'0'));
translateNum(s.substring(1));
sb.delete(sb.length()-1,sb.length());
}
else {
sb.append((char)(s.charAt(0)+'a'-'0'));
translateNum(s.substring(1));
sb.delete(sb.length()-1,sb.length());
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
System.out.println(new Solution().translateNum(num));
}
}
动态规划:
class Solution {
public int translateNum(int num) {
String s = String.valueOf(num);
int[] dp = new int[s.length()+2];
dp[0] = dp[1] = 1;
for(int i=1;i<s.length();i++) {
if(s.charAt(i-1)=='0') {
dp[i+1]+=dp[i];
}
else if(s.charAt(i-1)<'2'||(s.charAt(i-1)=='2'&&s.charAt(i)<='5')) {
dp[i+1] = dp[i]+dp[i-1];
} else {
dp[i+1]+=dp[i];
}
}
return dp[s.length()];
}
}
搜索与回溯:
1. 剑指 Offer 12. 矩阵中的路径
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true
示例 2:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true
示例 3:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false
提示:
m == board.length
n = board[i].length
1 <= m, n <= 6
1 <= word.length <= 15
board 和 word 仅由大小写英文字母组成
解答:
class Solution {
public boolean exist(char[][] board, String word) {
boolean[][] visited = new boolean[board.length][board[0].length];
for(int i=0;i<board.length;i++) {
for(int j=0;j<board[0].length;j++) {
if(exist0(board,visited,word,i,j)) {
return true;
}
}
}
return false;
}
private boolean exist0(char[][] board, boolean[][] visited,String word,int i,int j) {
if(word.length()==0) return true;
if(i<0||j<0||i>=board.length||j>=board[0].length||visited[i][j]||board[i][j]!=word.charAt(0)) return false;
visited[i][j] = true;
boolean result = exist0(board,visited,word.substring(1),i+1,j)||
exist0(board,visited,word.substring(1),i-1,j)||
exist0(board,visited,word.substring(1),i,j+1)||
exist0(board,visited,word.substring(1),i,j-1);
visited[i][j] = false;
return result;
}
}
2 剑指 Offer 13. 机器人的运动范围
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
示例 1:
输入:m = 2, n = 3, k = 1
输出:3
示例 2:
输入:m = 3, n = 1, k = 0
输出:1
提示:
1 <= n,m <= 100
0 <= k <= 20
解答:
class Solution {
private int count = 0;
public int movingCount(int m, int n, int k) {
movingCount0(m,n,k,new boolean[m][n],0,0);
return count;
}
private void movingCount0(int m,int n,int k,boolean[][] visited,int i,int j) {
if(i<0||j<0||i>=m||j>=n||visited[i][j]) return;
visited[i][j] = true;
if(sumOfEveryPos(i)+sumOfEveryPos(j)>k) return;
count+=1;
movingCount0(m,n,k,visited,i+1,j);
movingCount0(m,n,k,visited,i,j+1);
movingCount0(m,n,k,visited,i-1,j);
movingCount0(m,n,k,visited,i,j-1);
}
private int sumOfEveryPos(int n) {
int result = 0;
int tmp;
while(n!=0) {
tmp = n%10;
result+=tmp;
n = n/10;
}
return result;
}
}
分治:重建二叉树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
// Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
// Output: [3,9,20,null,null,15,7]
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return buildTree0(preorder,inorder,0,preorder.length-1,0,preorder.length-1);
}
private TreeNode buildTree0(int[] preorder,int[] inorder,int start,int end,int left,int right) {
if(start>end) return null;
if(start==end) return new TreeNode(inorder[start]);
int i;
for(i=start;i<=end;i++) {
if(inorder[i]==preorder[left]) break;
}
TreeNode node = new TreeNode(inorder[i]);
node.left = buildTree0(preorder,inorder,start,i-1,left+1,left+i-start);
node.right = buildTree0(preorder,inorder,i+1,end,left+i-start+1,right);
return node;
}
}