diff --git a/Week 08/id_713/LeetCode_14_LongestCommonPrefix.java b/Week 08/id_713/LeetCode_14_LongestCommonPrefix.java new file mode 100644 index 000000000..72a9c183f --- /dev/null +++ b/Week 08/id_713/LeetCode_14_LongestCommonPrefix.java @@ -0,0 +1,49 @@ +package id_713; + +/** + * 14. 最长公共前缀 + */ +public class LeetCode_14_LongestCommonPrefix { + + + /* + 编写一个函数来查找字符串数组中的最长公共前缀。 + + 如果不存在公共前缀,返回空字符串 ""。 + + 示例 1: + + 输入: ["flower","flow","flight"] + 输出: "fl" + + 示例 2: + + 输入: ["dog","racecar","car"] + 输出: "" + 解释: 输入不存在公共前缀。 + + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/longest-common-prefix + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + */ + + + /* + 水平扫描法 + */ + public String longestCommonPrefix(String[] strs) { + if (strs == null || strs.length == 0) return ""; + + for (int i = 0; i < strs[0].length(); i++) { + char c = strs[0].charAt(i); + for (int j = 0; j < strs.length; j++) { + if (i == strs[j].length() || strs[j].charAt(j) != c) { + return strs[0].substring(0, i); + } + } + } + + return strs[0]; + } +} diff --git a/Week 08/id_713/LeetCode_14_ReverseString.java b/Week 08/id_713/LeetCode_14_ReverseString.java new file mode 100644 index 000000000..478760cc8 --- /dev/null +++ b/Week 08/id_713/LeetCode_14_ReverseString.java @@ -0,0 +1,48 @@ +package id_713; + +/** + * 344. 反转字符串 + */ +public class LeetCode_14_ReverseString { + + + /* + 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。 + + 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 + + 你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。 + + + + 示例 1: + + 输入:["h","e","l","l","o"] + 输出:["o","l","l","e","h"] + + 示例 2: + + 输入:["H","a","n","n","a","h"] + 输出:["h","a","n","n","a","H"] + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/reverse-string + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + */ + + + public void reverseString(char[] s) { + if (s == null || s.length == 0) return; + + int i = 0, j = s.length - 1; + + while (i < j) { + char tmp = s[i]; + s[i] = s[j]; + s[j] = tmp; + i++; + j--; + } + } + +} diff --git a/Week 08/id_713/LeetCode_151_ReverseWordsInAString.java b/Week 08/id_713/LeetCode_151_ReverseWordsInAString.java new file mode 100644 index 000000000..8ba93afb0 --- /dev/null +++ b/Week 08/id_713/LeetCode_151_ReverseWordsInAString.java @@ -0,0 +1,133 @@ +package id_713; + +import java.util.Arrays; +import java.util.Collections; + +/** + * 151. 翻转字符串里的单词 + */ +public class LeetCode_151_ReverseWordsInAString { + + /* + 给定一个字符串,逐个翻转字符串中的每个单词。 + + + + 示例 1: + + 输入: "the sky is blue" + 输出: "blue is sky the" + + 示例 2: + + 输入: " hello world! " + 输出: "world! hello" + 解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 + + 示例 3: + + 输入: "a good example" + 输出: "example good a" + 解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。 + + + + 说明: + + 无空格字符构成一个单词。 + 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。 + 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。 + + + + 进阶: + + 请选用 C 语言的用户尝试使用 O(1) 额外空间复杂度的原地解法。 + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/reverse-words-in-a-string + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + */ + + public String reverseWords(String s) { + if (s == null) return null; + + String[] words = s.trim().split(" +"); + Collections.reverse(Arrays.asList(words)); + return String.join(" ", words); + } + + + public String reverseWords2(String s) { + StringBuilder sb = new StringBuilder(); + int i = s.length() - 1; + + while (i >= 0) { + if (s.charAt(i) == ' ') { + i--; + continue; + } + + int start = s.lastIndexOf(' ', i); + sb.append(" "); + sb.append(s.substring(start + 1, i + 1)); + i = start - 1; + + + } + + if (sb.length() > 0) { + sb.deleteCharAt(0); + } + + return sb.toString(); + } + + + public String reverseWords3(String s) { + if (s == null) return null; + + char[] chars = s.toCharArray(); + int n = chars.length; + + reverse(chars, 0, n - 1); + reverseWord(chars, n); + return cleanSpaces(chars, n); + + } + + private void reverseWord(char[] chars, int n) { + int i = 0, j = 0; + + while (i < n) { + while (i < j || i < n && chars[i] == ' ') i++; + while (j < i || j < n && chars[j] == ' ') j++; + reverse(chars, i, j - 1); + } + } + + private void reverse(char[] chars, int i, int j) { + while (i < j) { + char tmp = chars[i]; + chars[i] = chars[j]; + chars[j] = tmp; + } + } + + + private String cleanSpaces(char[] chars, int n) { + int i = 0, j = 0; + while (j < n) { + while (j < n && chars[j] == ' ') j++; + while (j < n && chars[j] != ' ') chars[i++] = chars[j++]; + while (j < n && chars[j] == ' ') j++; + + if (j < n) { + chars[i++] = ' '; + } + } + + return new String(chars).substring(0, i); + } + +} diff --git a/Week 08/id_713/LeetCode_300_LongestIncreasingSubsequence.java b/Week 08/id_713/LeetCode_300_LongestIncreasingSubsequence.java new file mode 100644 index 000000000..77db783a3 --- /dev/null +++ b/Week 08/id_713/LeetCode_300_LongestIncreasingSubsequence.java @@ -0,0 +1,103 @@ +package id_713; + +/** + * 300. 最长上升子序列 + */ +public class LeetCode_300_LongestIncreasingSubsequence { + + /* + 给定一个无序的整数数组,找到其中最长上升子序列的长度。 + + 示例: + + 输入: [10,9,2,5,3,7,101,18] + 输出: 4 + 解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。 + + 说明: + + 可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。 + 你算法的时间复杂度应该为 O(n2) 。 + + 进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗? + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/longest-increasing-subsequence + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + */ + + + + /* + + + 参考: https://leetcode-cn.com/problems/longest-increasing-subsequence/solution/zui-chang-shang-sheng-zi-xu-lie-dong-tai-gui-hua-2/ + + 朴素动态规划: + 状态定义: + dp[i]的值表示 nums 前i个数字的最长子序列长度 + 转移方程 + 设 j 属于 [0, i), 考虑每轮计算新的dp[i]时, 遍历[0, i)列表区间, 做以下判断 + 1. 当 nums[i] > nums[j]时, nums[i]可以接在nums[j]之后, 此情况下最长上升子序列长度为 dp[j] + 1 + 2. 当 nums[i] <= nums[j]时, nums[i] 无法接在nums[i]之后, 此情况上升序列不成立, 跳过 + + 上述所有1情况下 计算出的 dp[j] + 1的最大值, 为直到i的上升子序列长度(dp[i]) + 实现方式为 遍历j时, 每轮执行 dp[i] = max(dp[i], dp[j] + 1) + + 转移方程: dp[i] = max(dp[i], dp[j] + 1) for j in [0, i) + 初始状态: dp[i]所有元素置1, 含义是: 每个元素都至少可以单独成为子序列, 长度为1 + 返回值: 返回dp数组中最大值, 即可得到全局最长上升子序列长度 + + 高级动态规划 + 1. 动态规划中, 通过线性遍历来计算dp的复杂度无法降低 + 2. 每轮计算中, 需要通过线性遍历 [0, k)区间元素来得到 dp[k]. 考虑, 是否可以通过重新设计状态定义, 使整个dp为一个排序列表 + 这样在计算每个dp[k]时, 就可以通过二分查找法遍历 [0, k)区间元素, 将此部分复杂度有 O(N) 降低至 O(logN) + + 新状态定义 + 维护一个列表 dp, 其中每个元素 dp[k]的值代表 长度为 k+1的子序列尾部元素值 + 如 [1,4,6]序列, 长度为1,2,3的子序列尾部元素值分别为 dp = [1,4,6] + + 状态转移设计 + 设常量数字N, 和随机数x, 可以推出: 当N越小时, N < x的纪律越大 + 如 N = 0 比 N = 1000更可能满足 N < x + + 在遍历计算每个 tails[k],不断更新长度为 [1,k]的子序列尾部元素值,始终保持每个尾部元素值最小 (例如 [1,5,3]], 遍历到元素 555 时,长度为 222 的子序列尾部元素值为 555;当遍历到元素 333 时,尾部元素值应更新至 333,因为 333 遇到比它大的数字的几率更大)。 + + + + + + [10 9 2 5 3 7 21 18] + + [0 0 0 0 0 0 0 0] + [10 0 0 0 0 0 0 0] + [9 0 0 0 0 0 0 0] + [2 0 0 0 0 0 0 0] + [2 5 0 0 0 0 0 0] + [2 3 0 0 0 0 0 0] + [2 3 7 0 0 0 0 0] + [2 3 7 21 0 0 0 0] + [2 3 7 18 0 0 0 0] + + 数组的长度, 即为最大上升子序列 + */ + + public int lengthOfLIS(int[] nums) { + + int[] tails = new int[nums.length]; + int res = 0; + + for (int num : nums) { + int i = 0, j = res; + while (i < j) { + int m = (i + j) / 2; + if (tails[m] < num) i = m + 1; + else j = m; + } + tails[i] = num; + if (res == j) res++; + } + + return res; + } +} diff --git a/Week 08/id_713/LeetCode_387_FirstUniqueCharacterInAString.java b/Week 08/id_713/LeetCode_387_FirstUniqueCharacterInAString.java new file mode 100644 index 000000000..b94d64c2b --- /dev/null +++ b/Week 08/id_713/LeetCode_387_FirstUniqueCharacterInAString.java @@ -0,0 +1,42 @@ +package id_713; + +import java.util.HashMap; + +/** + * 387. 字符串中的第一个唯一字符 + */ +public class LeetCode_387_FirstUniqueCharacterInAString { + + /* + 给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。 + + 案例: + + s = "leetcode" + 返回 0. + + s = "loveleetcode", + 返回 2. + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/first-unique-character-in-a-string + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + */ + + public int firstUniqChar(String s) { + HashMap map = new HashMap<>(); + + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + map.put(c, map.getOrDefault(c, 0) + 1); + } + + for (int i = 0; i < s.length(); i++) { + if (map.get(s.charAt(i)) == 1) { + return i; + } + } + + return -1; + } +} diff --git a/Week 08/id_713/LeetCode_8_StringToIntegerAtoi.java b/Week 08/id_713/LeetCode_8_StringToIntegerAtoi.java new file mode 100644 index 000000000..d1be1331c --- /dev/null +++ b/Week 08/id_713/LeetCode_8_StringToIntegerAtoi.java @@ -0,0 +1,95 @@ +package id_713; + +/** + * 8. 字符串转换整数 (atoi) + */ +public class LeetCode_8_StringToIntegerAtoi { + + /* + 请你来实现一个 atoi 函数,使其能将字符串转换成整数。 + + 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 + + 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。 + + 该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。 + + 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。 + + 在任何情况下,若函数不能进行有效的转换时,请返回 0。 + + 说明: + + 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。 + + 示例 1: + + 输入: "42" + 输出: 42 + + 示例 2: + + 输入: " -42" + 输出: -42 + 解释: 第一个非空白字符为 '-', 它是一个负号。 + 我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。 + + 示例 3: + + 输入: "4193 with words" + 输出: 4193 + 解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。 + + 示例 4: + + 输入: "words and 987" + 输出: 0 + 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。 + 因此无法执行有效的转换。 + + 示例 5: + + 输入: "-91283472332" + 输出: -2147483648 + 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 + 因此返回 INT_MIN (−231) 。 + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/string-to-integer-atoi + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + */ + + public int myAtoi(String str) { + int index = 0, sign = 1, total = 0; + + // 如果是空串 + if(str == null || str.length() == 0) return 0; + + // 去除空格, 如果使用trim的话, 会使用额外的空间, 原因: java的String是不可变的 + while (str.charAt(index) == ' ' && index < str.length()) + index++; + + // 处理符号 + if(str.charAt(index) == '+' || str.charAt(index) == '-'){ + sign = str.charAt(index) == '+' ? 1 : -1; + index++; + } + + + // 转换 + while (index < str.length()) { + int digit = str.charAt(index) - '0'; + if (digit < 0 || digit > 9) break; + + if (Integer.MAX_VALUE / 10 < total || Integer.MAX_VALUE / 10 == total && Integer.MAX_VALUE % 10 < digit) { + return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE; + } + + total = 10 * total + digit; + index++; + } + + return total * sign; + } + +} diff --git a/Week 08/id_713/LeetCode_91_DecodeWays.java b/Week 08/id_713/LeetCode_91_DecodeWays.java new file mode 100644 index 000000000..4fc047c54 --- /dev/null +++ b/Week 08/id_713/LeetCode_91_DecodeWays.java @@ -0,0 +1,130 @@ +package id_713; + +/** + * 91. 解码方法 + */ +public class LeetCode_91_DecodeWays { + + /* + 一条包含字母 A-Z 的消息通过以下方式进行了编码: + + 'A' -> 1 + 'B' -> 2 + ... + 'Z' -> 26 + + 给定一个只包含数字的非空字符串,请计算解码方法的总数。 + + 示例 1: + + 输入: "12" + 输出: 2 + 解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。 + + 示例 2: + + 输入: "226" + 输出: 3 + 解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。 + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/decode-ways + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + */ + + + /* + 分析: + + 以22067举例, 从后往前遍历 + + 1. 首先提取如果为7, 只有1种 -> G + 2. 其次为67, 也只有一种 -> FG + 3. 067 -> 0 + 4. 2067 -> (20 67) + (2 067) = (20 67) -> TFG + 5. 22067 -> (2 2067) + (22 067) + (2 2067) -> BTFG + + 得到规律: + 如果开始为0, 结果为0 + 如果开始的数加上第二个数 <= 26. 结果为 (start + 1) + (start + 2) + 如果开始的数加上第二个数 > 26. 结果为 (start + 1) + + 以上是递归的思路, 导致了大量重复的计算 + + 引入一个dp数组, 用来计算以某个字符为开始的解码数量, 动态规划是一个填表的过程 + 递推方程: + 如果 nums[i] = 0, dp[i] = 0 + 如果 nums[i] + nums[i + 1] <= 26 + dp[i] =dp[i + 1] + dp[i + 2] + 否则 + dp[i] = dp[i + 1] + + + 以2206为例, 假设此处 nums[]={2,2,0,6}, 新建一个数组 + int[] dp = new int[len + 1]; + 之所以长度为len+1, 因为这样不需要将最后一个6单独处理, 并将dp[len]=1 + + 0 1 2 3 4 + [0 0 0 0 1] // 将 dp[len]=1, 算上0, 此时长度为 len + 1, 所以索引是 len + [0 0 0 1 1] // 此时处理 dp[3], 按照递推式, 因为 nums[3] = 6,所以 dp[3] = 1 + [0 0 0 1 1] // 此时处理 dp[2], 按照递推式, 因为 nums[2] = 0,所以 dp[2] = 0 + [0 1 0 1 1] // 此时处理 dp[1], 按照递推式, 因为 nums[1]*10 + nums[2] = 20, 所以dp[1] = dp[2] + dp[3] = 1 + [1 1 0 1 1] // 此时处理 dp[0], 按照递推式, 因为 nums[0]*10 + nums[1] = 22, 所以dp[0] = dp[1] + dp[2] = 1 + + */ + + + public int numDecodings(String s) { + if (s == null || s.length() == 0) return 0; + + // 提取s的长度 + int n = s.length(); + + int[] dp = new int[n + 1]; + dp[n] = 1; + dp[n - 1] = (s.charAt(n - 1) == '0' ? 0 : 1); + + for (int i = n - 2; i >= 0; i--) { + if (s.charAt(i) == '0') { + dp[i] = 0; + continue; + } + + if ((s.charAt(i) - '0' * 10 + s.charAt(i + 1) - '0') <= 26) { + dp[i] = dp[i + 1] + dp[i + 2]; + } else { + dp[i] = dp[i + 1]; + } + } + + return dp[0]; + } + + public int numDecodingsPlus(String s) { + if (s == null || s.length() == 0) return 0; + + // 提取s的长度 + int len = s.length(); + + int help = 1; // 相当于 初始化 dp[len + 1[ = 1 的意思 + int res = (s.charAt(len - 1) != '0' ? 1 : 0); // 倒数第2个值, 也就是是 + + for (int i = len - 2; i >= 0; i--) { + if (s.charAt(i) == '0') { + help = res; + res = 0; + continue; + } + + if ((s.charAt(i - '0') * 10 + s.charAt(i + 1 - '0')) <= 26) { + res += help; + help = res - help; // help用于存储res之前的值 + } else { + help = res; + } + } + + return res; + } + +} diff --git a/Week 08/id_713/NOTE.md b/Week 08/id_713/NOTE.md old mode 100755 new mode 100644 index a6321d6e2..9e96a1bc3 --- a/Week 08/id_713/NOTE.md +++ b/Week 08/id_713/NOTE.md @@ -1,4 +1,146 @@ # NOTE - + + + + +# 高级动态规划 + +## 常见DP题目和状态转移方程 + +### 爬楼梯问题 + +* 转换成斐波那契数列 +* f(n) = f(n - 1) + f(n - 2), 其中 f(1) = 1, f(2) = 1 + +```python +# 朴素 +def f(n): + if n <= 1: return 1; + return f(n - 1) + f(n - 2) + +# 带缓存 +def f(n): + if n <= 1: return 1 + if n not in mem: + mem[n] = f(n - 1) + f(n - 2) + return mem[n] + +def f(n): + x, y = 1, 1 + for i in ranges (1, n): + y, x = x + y, y + return y +``` + + + +### 不同路径问题 + +* f(x, y) = f(x - 1, y) + f(x, y - 1) + +```python +def (x, y): + dp[[0] * (m + 1) for _ in range(n + 1)] + dp[1][1] = 1 + for i in range(1, y + 1): + for j in range(1, x + 1): + dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + return dp[y][x] +``` + + + +### 打家劫舍 + +* dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]) + +```python +dp[i][0] = max(dp[i - 1][0], dp[i - 1][1]) +dp[i][1] = dp[i - 1][0] + +``` + + + +### 最小路径和 + +* dp[i] [j]状态定义: minPath(A[1 -> i] [1 -> j]) +* dp[i] [j] = min(dp[i - 1] [j], dp[i] [j - 1]) +A[i] [j] + + + +### 股票买卖 + +```python +dp[i][k][0 or 1] 0 <= i <= n-1, 1 <= k <= K +# i为天数 +# k为最多交易次数 +# [0, 1]是否持有股票 +# 总状态数: n * K * 2种状态 + +for 0 <= i < n: + for i <= k <= K: + for s in [0, 1]: + dp[i][k][s] = max(buy, sell, rest) + +dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i]) +# 解释: 今天没有持有股票, 有2种可能 +# 1.昨天就没有持有, 然后今天选择rest +# 2.昨天持有了股票, 今天卖掉了 +dp[i][k][1] = max(dp[i-1[k][1]], dp[i-1][k-1][0] - prices[i]) +# 解释: 今天持有股票, 有2种可能 +# 1.昨天持有股票, 今天rest +# 2.昨天没有持有, 今天买入 +``` + + + +--- + +## 复杂度来源 + +* 拥有更多维度 +* dp方程复杂 + + + + + +### 爬楼梯变种 + +* 一次可以上 一级,二级,三级 + +```python +# 上一级, 上二级, 上三级 +# 状态转移方程 +a[i] = a[i - 1] + a[i - 2] + a[i -3] + +a[0] = 1 +a[1] = 2 +a[2] = 3 + +for (int i = 2; i < n; i++) { + a[i] = a[i - 1] + a[i - 2] + a[i - 3] +} + +return a[n - 1] +``` + + + +### 编辑距离 + +```python +# 如果word1[i]与word2[j]相同, 显然dp[i][j] = dp[i - 1][j - 1] + +# 如果word1[i]与word2[j], 不同那么dp[i][j]可以通过 +# 1.在dp[i - 1][j - 1]的基础上做replace操作达到目的 +# 2.在dp[i - 1][j]的基础上做insert操作达到目的 +# 3.在dp[i][j - 1]的基础上做delete操作达到目的 +# 取三者最小情况即可 + +``` + + diff --git a/Week 08/id_713/practise/LeetCode_58_LengthOfLastWord.java b/Week 08/id_713/practise/LeetCode_58_LengthOfLastWord.java new file mode 100644 index 000000000..d6f121579 --- /dev/null +++ b/Week 08/id_713/practise/LeetCode_58_LengthOfLastWord.java @@ -0,0 +1,46 @@ +package id_713.practise; + +/** + * 58. 最后一个单词的长度 + */ +public class LeetCode_58_LengthOfLastWord { + /* + 给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。 + + 如果不存在最后一个单词,请返回 0 。 + + 说明:一个单词是指由字母组成,但不包含任何空格的字符串。 + + 示例: + + 输入: "Hello World" + 输出: 5 + + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/length-of-last-word + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + + */ + + public int lengthOfLastWord(String s) { + if (s == null) return 0; + s = s.trim(); + if (s.length() == 0) return 0; + + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == ' ') + return s.length() - 1 - i; + } + + return s.length(); + } + + public int lengthOfLastWord2(String s) { + if (s == null || s.length() == 0) return 0; + s = s.trim(); + int lastSpace = s.lastIndexOf(" "); + return s.length() - 1 - lastSpace; + } + +} diff --git a/Week 08/id_713/practise/LeetCode_709_ToLowerCase.java b/Week 08/id_713/practise/LeetCode_709_ToLowerCase.java new file mode 100644 index 000000000..18ad20fbd --- /dev/null +++ b/Week 08/id_713/practise/LeetCode_709_ToLowerCase.java @@ -0,0 +1,47 @@ +package id_713.practise; + +/** + * 709. 转换成小写字母 + */ +public class LeetCode_709_ToLowerCase { + /* + 实现函数 ToLowerCase(),该函数接收一个字符串参数 str,并将该字符串中的大写字母转换成小写字母,之后返回新的字符串。 + + 示例 1: + + 输入: "Hello" + 输出: "hello" + + 示例 2: + + 输入: "here" + 输出: "here" + + 示例 3: + + 输入: "LOVELY" + 输出: "lovely" + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/to-lower-case + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + */ + + public String toLowerCase(String str) { + + char[] chars = new char[str.length()]; + + for (int i = 0; i < str.length(); i++) { + chars[i] = str.charAt(i) >= 65 && str.charAt(i) <= 90 + ? (char) (str.charAt(i) + 32) + : str.charAt(i); + } + + return new String(chars); + } + + public String toLowerCase2(String str) { + return str.toLowerCase(); + } + +} diff --git a/Week 08/id_713/practise/LeetCode_771_JewelsAndStones.java b/Week 08/id_713/practise/LeetCode_771_JewelsAndStones.java new file mode 100644 index 000000000..df0db4858 --- /dev/null +++ b/Week 08/id_713/practise/LeetCode_771_JewelsAndStones.java @@ -0,0 +1,57 @@ +package id_713.practise; + +import java.util.HashSet; +import java.util.Set; + +/** + * 771. 宝石与石头 + */ +public class LeetCode_771_JewelsAndStones { + /* + 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。 + + J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。 + + 示例 1: + + 输入: J = "aA", S = "aAAbbbb" + 输出: 3 + + 示例 2: + + 输入: J = "z", S = "ZZ" + 输出: 0 + + + 来源:力扣(LeetCode) + 链接:https://leetcode-cn.com/problems/jewels-and-stones + 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 + + */ + + public int numJewelsInStones(String J, String S) { + Set set = new HashSet<>(); + + for (char c : J.toCharArray()) { + set.add(c); + } + + int res = 0; + for (char c : S.toCharArray()) { + if (set.contains(c)) + res++; + } + return res; + } + + public int numJewelsInStones2(String J, String S) { + int res = 0; + for (char s : S.toCharArray()) { + if(J.indexOf(s) != -1) + res++; + } + + return res; + } + +}