Java练习——day3
文章目录
- 练习1
- 练习2
- 练习3
练习1
题目:输入一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
例如,121 是回文,而 123 不是。
示例代码:
package com.study;class Solution {public boolean isPalindrome(int x) {if (x < 0 || (x % 10 == 0 && x != 0)) {return false;}int revertedNumber = 0;while (x > revertedNumber) {revertedNumber = revertedNumber * 10 + x % 10;x /= 10;}return x == revertedNumber || x == revertedNumber / 10;}public static void main(String[] args) {Solution solution = new Solution();// 测试System.out.println(solution.isPalindrome(121)); // 输出: trueSystem.out.println(solution.isPalindrome(-121)); // 输出: falseSystem.out.println(solution.isPalindrome(10)); // 输出: false}
}
练习2
题目:
七个不同的符号代表罗马数字,其值如下:
符号 | 值 |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:
如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)。
只有 10 的次方(I, X, C, M)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式。
给定一个整数,将其转换为罗马数字。
- 示例 1:
输入:num = 3749
输出: “MMMDCCXLIX”
解释:
3000 = MMM 由于 1000 (M) + 1000 (M) + 1000 (M)
700 = DCC 由于 500 (D) + 100 © + 100 ©
40 = XL 由于 50 (L) 减 10 (X)
9 = IX 由于 10 (X) 减 1 (I)
-
注意:49 不是 50 (L) 减 1 (I) 因为转换是基于小数位
-
示例代码
package com.study;class Solution {public String intToRoman(int num) {// 罗马数字的符号与对应的值int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};String[] symbols = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};StringBuilder result = new StringBuilder();// 从最大的值开始,依次判断for (int i = 0; i < values.length; i++) {// 计算当前值能在 num 中出现多少次while (num >= values[i]) {result.append(symbols[i]); // 添加对应的罗马数字符号num -= values[i]; // 减去对应的值}}return result.toString();}public static void main(String[] args) {Solution solution = new Solution();System.out.println(solution.intToRoman(3749)); // 输出: "MMMDCCXLIX"System.out.println(solution.intToRoman(58)); // 输出: "LVIII"System.out.println(solution.intToRoman(1994)); // 输出: "MCMXCIV"}
}
练习3
-
题目:
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。
s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。
例如,如果 words = [“ab”,“cd”,“ef”], 那么 “abcdef”, “abefcd”,“cdabef”, “cdefab”,“efabcd”, 和 “efcdab” 都是串联子串。 “acdbef” 不是串联子串,因为他不是任何 words 排列的连接。
返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。 -
示例 1:
输入:s = “barfoothefoobarman”, words = [“foo”,“bar”]
输出:[0,9]
解释:因为 words.length =2 同时 words[i].length = 3,连接的子字符串的长度必须为 6。
子串 “barfoo” 开始位置是 0。它是 words 中以 [“bar”,“foo”] 顺序排列的连接。
子串 “foobar” 开始位置是 9。它是 words 中以 [“foo”,“bar”] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。 -
示例代码:
import java.util.*;class Solution {public List<Integer> findSubstring(String s, String[] words) {List<Integer> result = new ArrayList<>();if (s == null || words == null || words.length == 0 || s.length() == 0) {return result;}// 单词长度和串联子串的总长度int wordLength = words[0].length();int totalLength = wordLength * words.length;// 用哈希表记录单词的出现次数Map<String, Integer> wordCount = new HashMap<>();for (String word : words) {wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);}// 滑动窗口检查每个可能的起始位置for (int i = 0; i < wordLength; i++) { // 每次从不同的起始位置滑动int left = i;int right = i;int count = 0;Map<String, Integer> currentCount = new HashMap<>();while (right + wordLength <= s.length()) {// 获取当前窗口的单词String word = s.substring(right, right + wordLength);right += wordLength;// 如果当前单词在 words 中if (wordCount.containsKey(word)) {// 记录当前单词出现次数currentCount.put(word, currentCount.getOrDefault(word, 0) + 1);// 如果当前单词的出现次数超过了在 words 中的次数,调整窗口while (currentCount.get(word) > wordCount.get(word)) {String leftWord = s.substring(left, left + wordLength);currentCount.put(leftWord, currentCount.get(leftWord) - 1);left += wordLength;count--;}count++;// 如果窗口内的单词数与 words 数组的长度相等,则找到一个串联子串if (count == words.length) {result.add(left);// 移动左边界,继续寻找下一个子串String leftWord = s.substring(left, left + wordLength);currentCount.put(leftWord, currentCount.get(leftWord) - 1);left += wordLength;count--;}} else {// 如果当前单词不在 words 中,重置窗口currentCount.clear();left = right;count = 0;}}}return result;}
}
- 编写 main 方法来测试
public class Main {public static void main(String[] args) {Solution solution = new Solution();System.out.println(solution.findSubstring("barfoothefoobarman", new String[]{"foo", "bar"})); // 输出: [0, 9]System.out.println(solution.findSubstring("wordgoodgoodgoodbestword", new String[]{"word", "good", "best", "word"})); // 输出: []System.out.println(solution.findSubstring("barfoofoobarthefoobarman", new String[]{"bar", "foo", "the"})); // 输出: [6, 9, 12]}
}
复杂度分析:
- 时间复杂度:O(N * M),其中 N 是字符串 s 的长度,M 是 words 数组的长度。对于每个起始位置,我们会遍历一次字符串。
- 空间复杂度:O(M),我们使用了哈希表来存储单词的出现次数,最多需要存储 words.length 个单词。