Kotlin 朱涛 实战 刷题 LeetCode
目录
目录
春节刷题计划 | Kotlin + LeetCode
移除字符
移除字符串中的所有元音字母 a、e、i、o、u。
public String removeVowels(String s) {
return s.replaceAll("[aeiou]", "");
}
val String.removeVowels: String get() = replace("[aeiou]".toRegex(), "")
val String.removeVowels2: String get() = filter { it !in setOf('a', 'e', 'i', 'o', 'u') }
冒泡排序
public static int[] bubbleSort(int[] array) {
int size = array.length;
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size - i - 1; ++j) {
if (array[j] > array[j + 1]) {
int tmp = array[j];
array[j] = array[j + 1];
array[j + 1] = tmp;
}
}
}
return array;
}
fun sort(array: IntArray): IntArray {
for (i in array.indices) {
for (j in 0 until array.size - i - 1) {
if (array[j] > array[j + 1]) {
val tem = array[j]
array[j] = array[j + 1]
array[j + 1] = tem
}
}
}
return array
}
最常见的单词
LeetCode-819:给定一个段落 (paragraph) 和一个禁用单词列表 (banned)。返回出现次数最多,同时不在禁用列表中的单词。
题目保证至少有一个词不在禁用列表中,而且答案唯一。禁用列表中的单词用
小写
字母表示,不含标点符号。段落中的单词不区分大小写
。答案都是小写
字母。
Java
public static String mostCommonWord(String paragraph, String[] banned) {
HashMap<String, Integer> map = new HashMap<>();
String[] strings = paragraph.toLowerCase().replaceAll("[^A-Za-z]", " ").split(" ");
for (String s : banned) {
map.put(s, Integer.MIN_VALUE);
}
map.put("", Integer.MIN_VALUE);
for (String s : strings) {
Integer count = map.get(s);
map.put(s, count == null ? 1 : count + 1);
}
String text = null;
int max = 0;
for (String next : map.keySet()) {
Integer count = map.get(next);
if (count != null && count > max) {
text = next;
max = count;
}
}
return text;
}
Kotlin
fun mostCommonWord(paragraph: String, banned: Array<String>): String = paragraph
.lowercase(Locale.getDefault()) // Returns a copy of this string converted to lower case
.replace(Regex("[^A-Za-z]"), " ")
.split(" ")
.asSequence() // Call chain on a collection could be converted into 'Sequence' to improve performance
.filter { it !in banned }
.groupBy { it } // Groups elements of the original sequence
.map { Pair(it.key, it.value.size) } // 转换为 List
.maxBy { it.second } // Returns the first element yielding the largest value of the given function
.first
比较版本号
LeetCode-165:比较版本号
- 版本号仅包含数字和
.
- 1.0 小于 1.1
- 2.0 大于 1.5.6
- 1.1 等于 1.001 等于 1.1.0
Java
public class Test {
public static void main(String[] args)
{
System.out.println(compareVersion("3.10.0101.0", "3.10.0102."));
}
public static int compareVersion(String version1, String version2)
{
int[] v1 = getVersions (version1);
int[] v2 = getVersions (version2);
boolean isV1LengthLong = v1 . length > v2 . length;
int minLength = isV1LengthLong ? v2 . length : v1 . length;
for (int i = 0; i < minLength; i++) {
if (v1[i] != v2[i]) {
return v1[i] > v2[i] ? 1 :-1;
}
}
int maxLength = isV1LengthLong ? v1 . length : v2 . length;
int[] maxLengthVersion = isV1LengthLong ? v1 : v2;
for (int i = minLength; i < maxLength; i++) {
if (maxLengthVersion[i] != 0) {
return isV1LengthLong ? 1 :-1;
}
}
return 0;
}
private static int[] getVersions(String version)
{
String[] strings = version . split ("\\.");
int[] versions = new int[strings.length];
for (int i = 0; i < strings.length; i++) {
String newString = strings [i];
while (newString.length() > 1 && newString.startsWith("0")) {
newString = newString.substring(1);
}
versions[i] = Integer.parseInt(newString);
}
return versions;
}
}
Kotlin - 1
fun compareVersion(version1: String, version2: String): Int {
val list1 = version1.split(".")
val list2 = version2.split(".")
var i = 0
while (i < list1.size || i < list2.size) { // 只要有一个没遍历完,就要继续遍历
val v1 = list1.getOrNull(i)?.toInt() ?: 0 // 类型转换,当数组越界时,转换为 0
val v2 = list2.getOrNull(i)?.toInt() ?: 0
if (v1 != v2) {
return v1.compareTo(v2) // Int.compareTo() 的返回值,刚好符合题目的要求
}
i++
}
return 0
}
核心代码:
val v1 = list1.getOrNull(i)?.toInt() ?: 0
// 等价于以下三步
val versionStr: String? = list1.getOrNull(i) // 当数组越界时,返回 null
val versionInt: Int? = versionStr?.toInt() // 当变量不为空时,才调用
val v1: Int = versionInt ?: 0 // 当变量为空时,才赋值
Kotlin - 2
前面的思路,我们是使用的 Kotlin 的库函数 split()
进行分割,然后对列表进行遍历
来判断的版本号。其实,我们可以自己遍历字符串,来模拟 split 的过程,并在遍历时把比对的工作也一起做完。
fun compareVersion(version1: String, version2: String): Int {
val v1 = Version(0, 0, version1)
val v2 = Version(0, 0, version2)
while (v1.index < version1.length || v2.index < version2.length) {
v1.dealSubVersionValue()
v2.dealSubVersionValue()
if (v1.subValue != v2.subValue) {
return v1.subValue.compareTo(v2.subValue)
}
}
return 0
}
data class Version(var index: Int, var subValue: Int, val versionStr: String) {
val baseValue = '0'.toInt()
fun dealSubVersionValue() {
subValue = 0
while (index < versionStr.length && versionStr[index] != '.') {
subValue = subValue * 10 + versionStr[index].toInt() - baseValue
index++
}
index++
}
}
求解一元一次方程
LeetCode-640:输入一个方程,以 x=value
的形式返回该方程的解
- 方程仅包含
+-=
符号、变量 x 和其对应系数 - 如果方程没有解,请返回
No solution
- 如果方程有无限解,请返回
Infinite solutions
- 如果方程中只有一个解,要保证返回值是一个整数
输入: "x+5-3+x=6+x-2"
输出: "x=2"
输入: "x=x"
输出: "Infinite solutions"
输入: "x=x+1"
输出: "No solution"
Java
public static String solveEquation(String equation) { // x+5-3+2x=6+x-2
int xCount = 0; // 移到左边的 x 系数之和
int addValue = 0; // 移到右边的数字之和
int equalIndex = equation.indexOf('='); // 等号的位置
for (int i = 0; i < equation.length(); i++) {
int fromIndex = i;
if (i == 0) {
i++;
}
for (int j = i; j < equation.length(); j++) {
char c = equation.charAt(j);
if (c == '+' || c == '-' || c == '=') {
break;
}
i++;
}
String subString = equation.substring(fromIndex == 0 ? fromIndex : fromIndex - 1, i);
subString = subString.startsWith("=") ? subString.substring(1) : subString;
// System.out.println("值为:" + subString);
if (subString.endsWith("x")) {
subString = subString.substring(0, subString.length() - 1);
int tempCount;
if (subString.length() == 0) { // x
tempCount = 1;
} else {
if (subString.length() == 1 && (subString.startsWith("+") || subString.startsWith("-"))) { // +x 或 -x
tempCount = subString.charAt(0) == '+' ? 1 : -1;
} else { // +5x 或 5x 或 53x 或 -2x
tempCount = Integer.parseInt(subString);
}
}
xCount = i > equalIndex ? xCount - tempCount : xCount + tempCount; // 左正右负
} else if (subString.length() > 0) { // 过滤掉 = 产生的一个空字符串
int tempValue = Integer.parseInt(subString);
addValue = i > equalIndex ? addValue + tempValue : addValue - tempValue; // 左负右正
}
// System.out.println("结果:" + xCount + "x = " + addValue);
if (xCount == 0) {
return addValue == 0 ? "Infinite solutions" : "No solution";
} else {
return "x=" + (addValue / xCount);
}
}
Kotlin
fun solveEquation(equation: String): String { // x+5-3+2x=6+x-2
var xCount = 0 // 移到左边的 x 系数之和
var addValue = 0 // 移到右边的数字之和
val equalIndex = equation.indexOf('=') // 等号的位置
var i = 0
while (i < equation.length) {
val fromIndex = i
if (i == 0) {
i++
}
for (j in i until equation.length) {
val c: Char = equation[j]
if (c == '+' || c == '-' || c == '=') {
break
}
i++
}
var subString = equation.substring(if (fromIndex == 0) fromIndex else fromIndex - 1, i)
subString = if (subString.startsWith("=")) subString.substring(1) else subString
println("值为:$subString")
if (subString.endsWith("x")) {
subString = subString.substring(0, subString.length - 1)
val tempCount = if (subString.isEmpty()) 1 // x
else {
if (subString.length == 1 && (subString.startsWith("+") || subString.startsWith("-"))) { // +x 或 -x
if (subString[0] == '+') 1 else -1
} else subString.toInt() // +5x 或 5x 或 53x 或 -2x
}
xCount = if (i > equalIndex) xCount - tempCount else xCount + tempCount // 左正右负
} else if (subString.isNotEmpty()) { // 过滤掉 = 产生的一个空字符串
val tempValue = subString.toInt()
addValue = if (i > equalIndex) addValue + tempValue else addValue - tempValue // 左负右正
}
i++
}
println("结果:${xCount}x = $addValue")
return if (xCount == 0) if (addValue == 0) "Infinite solutions" else "No solution"
else "x=" + addValue / xCount
}
分数加减运算
题目描述
给定一个表示分数加减运算的字符串,返回计算结果。
- 输入、输出字符串只包含
0-9
的数字,以及/+-
符号(不会有空格) - 输入、输出分数格式均为
(-)分子/分母
,正数前面的+
会被省略 - 输入只包含合法的最简分数,分子、分母的范围是
[1,10]
(整数也会用分数来表示) - 输入分数的个数不超过 10 个,最终结果的分子与分母不超过 32 位整数(不会溢出)
- 输出的分数需要是最简分数形式(整数也需要用分数来表示)
题目分析
主要步骤:
- 分割、解析分数
- 计算分母的最小公倍数
- 将分数进行通分
- 计算分子加减运算的结果
- 将计算结果约分
求最小公倍数 & 最大公约数
最大公约数计算公式如下
20 36 -- 16
16 20 -- 4
4 16 -- 0 --> 最大公约数是 4
3 8 -- 5
3 5 -- 2
2 3 -- 1
1 2 -- 0 --> 最大公约数是 1
22 36 -- 14
14 22 -- 8
8 14 -- 6
6 8 -- 2
2 6 -- 0 --> 最大公约数是 2
最小公倍数 = a * b /最大公约数
// 求两个数的最大公约数,Greatest Common Divisor
private fun gcd(a: Int, b: Int): Int {
var (big, small) = if (a > b) a to b else b to a
while (small != 0) {
val temp = small
small = big % small
big = temp
}
return big
}
// 求两个数的最小公倍数,Least Common Multiple
private fun lcm(a: Int, b: Int) = a * b / gcd(a, b)
完整代码
fun fractionAddition(expression: String): String {
val pairs = expression
.replace("-", "+-")
.split("+") // 拆分每个分数
.filter { it.isNotBlank() } // 过滤非法数据
.map { it.split("/") } // 拆分分子分母
.map { Pair(it[0].toInt(), it[1].toInt()) }
val lcm = pairs
.map { it.second } // 分母的集合
.reduce { acc, i -> lcm(acc, i) } // 所有分母的最小公倍数
val sum = pairs
.map { it.first * lcm / it.second } // 分子通分
.reduce { acc, i -> acc + i } // 所有分子相加
val gcd = gcd(kotlin.math.abs(sum), lcm) // 分子和分母的最大公约数
val result = "${sum / gcd}/${lcm / gcd}" // 简化分数
println("lcm: $lcm, sum: $sum, gcd: $gcd, result: $result")
return result
}
private val List<Int>.lcm: Int get() = reduce { acc, i -> lcm(acc, i) }
// 求两个数的最大公约数,Greatest Common Divisor
private fun gcd(a: Int, b: Int): Int {
var (big, small) = if (a > b) a to b else b to a
while (small != 0) {
val temp = small
small = big % small
big = temp
}
return big
}
// 求两个数的最小公倍数,Least Common Multiple
private fun lcm(a: Int, b: Int) = a * b / gcd(a, b)
2017-10-20
本文来自博客园,作者:白乾涛,转载请注明原文链接:https://www.cnblogs.com/baiqiantao/p/7698657.html