1、有效的字母异位词
问题:
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package LeetCode.test8_zifuchuan; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 public class ques_242_有效的字母异位词 { 7 public boolean isAnagram(String s, String t) { 8 Map<Character, Integer> map_s = new HashMap<>(); 9 Map<Character, Integer> map_t = new HashMap<>(); 10 return getMap(map_s, s).equals(getMap(map_t, t)); 11 } 12 13 public boolean isAnagram2(String s, String t) { 14 if (s.length() != t.length()) { 15 return false; 16 } 17 Map<Character, Integer> map = new HashMap<>(); 18 for (int i = 0; i < s.length(); i++) { 19 if (map.containsKey(s.charAt(i))) { 20 map.put(s.charAt(i), map.get(s.charAt(i)) + 1); 21 } else { 22 map.put(s.charAt(i), 1); 23 } 24 } 25 for (int i = 0; i < t.length(); i++) { 26 if (map.containsKey(t.charAt(i))) { 27 map.put(t.charAt(i), map.get(t.charAt(i)) - 1); 28 if (map.get(t.charAt(i)) == 0) { 29 map.remove(t.charAt(i)); 30 } 31 } 32 } 33 return map.size() == 0; 34 } 35 36 private Map<Character, Integer> getMap(Map<Character, Integer> map, String str) { 37 for (int i = 0; i < str.length(); i++) { 38 if (map.containsKey(str.charAt(i))) { 39 map.put(str.charAt(i), map.get(str.charAt(i)) + 1); 40 } else { 41 map.put(str.charAt(i), 1); 42 } 43 } 44 return map; 45 } 46 } 47 48 class Test_242 { 49 public static void main(String[] args) { 50 // String s = "anagram"; 51 // String t = "nagaram"; 52 String s = "rat"; 53 String t = "car"; 54 ques_242_有效的字母异位词 p = new ques_242_有效的字母异位词(); 55 System.out.println(p.isAnagram(s, t)); 56 System.out.println(p.isAnagram2(s, t)); 57 } 58 }
2、同构字符串
问题:
给定两个字符串 s 和 t ,判断它们是否是同构的。
如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。
每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
示例 1:
输入:s = "egg", t = "add"
输出:true
示例 2:
输入:s = "foo", t = "bar"
输出:false
示例 3:
输入:s = "paper", t = "title"
输出:true
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package LeetCode.test8_zifuchuan; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 /** 7 * 思路:从s到t和t到s两个方向进行map操作。 8 */ 9 public class ques_205_同构字符串 { 10 public boolean isIsomorphic(String s, String t) { 11 int m = s.length(); 12 int n = t.length(); 13 if (m != n) { 14 return false; 15 } 16 char[] char_s = s.toCharArray(); 17 char[] char_t = t.toCharArray(); 18 return judge(char_s, char_t) && judge(char_t, char_s); 19 } 20 21 private boolean judge(char[] s, char[] t) { 22 Map<Character, Character> map = new HashMap<>(); 23 for (int i = 0; i < s.length; i++) { 24 map.put(s[i], t[i]); 25 } 26 for (int i = 0; i < s.length; i++) { 27 if (t[i] != map.get(s[i])) { // map只能判断,不能修改! 28 return false; 29 } 30 } 31 return true; 32 } 33 } 34 35 class Test_205 { 36 public static void main(String[] args) { 37 String s = "egg"; 38 String t = "add"; 39 // String s = "foo"; 40 // String t = "bar"; 41 // String s = "badc"; 42 // String t = "baba"; 43 ques_205_同构字符串 p = new ques_205_同构字符串(); 44 System.out.println(p.isIsomorphic(s, t)); 45 } 46 }
3、回文子串
问题:
给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
回文字符串 是正着读和倒过来读一样的字符串。
子字符串 是字符串中的由连续字符组成的一个序列。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
输入:s = "abc"
输出:3
解释:三个回文子串: "a", "b", "c"
示例 2:
输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package LeetCode.test8_zifuchuan; 2 3 public class ques_647_回文子串 { 4 public int countSubstrings(String s) { 5 int num = 0; 6 for (int i = 0; i < s.length(); i++) { 7 for (int j = i; j < s.length(); j++) { 8 if (isPalindrome(s.substring(i, j + 1))) { 9 num++; 10 } 11 } 12 } 13 return num; 14 } 15 16 private boolean isPalindrome(String str) { 17 int len = str.length(); 18 for (int i = 0; i < len / 2; i++) { 19 if (str.charAt(i) != str.charAt(len - i - 1)) { 20 return false; 21 } 22 } 23 return true; 24 } 25 } 26 27 class Test_647 { 28 public static void main(String[] args) { 29 String s = "aaa"; 30 ques_647_回文子串 p = new ques_647_回文子串(); 31 System.out.println(p.countSubstrings(s)); 32 } 33 }
4、计数二进制子串
问题:
给定一个字符串 s,统计并返回具有相同数量 0 和 1 的非空(连续)子字符串的数量,并且这些子字符串中的所有 0 和所有 1 都是成组连续的。
重复出现(不同位置)的子串也要统计它们出现的次数。
示例 1:
输入:s = "00110011"
输出:6
解释:6 个子串满足具有相同数量的连续 1 和 0 :"0011"、"01"、"1100"、"10"、"0011" 和 "01" 。
注意,一些重复出现的子串(不同位置)要统计它们出现的次数。
另外,"00110011" 不是有效的子串,因为所有的 0(还有 1 )没有组合在一起。
示例 2:
输入:s = "10101"
输出:4
解释:有 4 个子串:"10"、"01"、"10"、"01" ,具有相同数量的连续 1 和 0 。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package LeetCode.test8_zifuchuan; 2 3 4 /** 5 * 思路:从左往右遍历数组,记录和当前位置数字相同且连续的长度,以及其之前连续的不同数字的长度。 6 * 若不同数字的连续长度大于等于当前数字的连续长度,则说明存在一个且只存在一个以当前数字结尾的满足条件的子字符串。 7 * eg:000111100(pre>=cur) 8 * 0001 pre=3 cur=1 count = 1 9 * 00011 pre=3 cur=2 count = 2 10 * 000111 pre=3 cur=3 count = 3 11 * 0001111 pre=3 cur=4 count = 3 12 * 000(11110) pre=4 cur=1 count = 4 13 * 000(111100) pre=4 cur=2 count = 5 14 */ 15 public class ques_696_计数二进制子串 { 16 public int countBinarySubstrings(String s) { 17 int pre = 0; 18 int cur = 1; 19 int count = 0; 20 for (int i = 1; i < s.length(); i++) { 21 if (s.charAt(i) == s.charAt(i - 1)) { 22 cur++; 23 } else { 24 pre = cur; 25 cur = 1; 26 } 27 if (pre >= cur) { 28 count++; 29 } 30 } 31 return count; 32 } 33 } 34 35 class Test_696 { 36 public static void main(String[] args) { 37 String s = "000111100"; 38 ques_696_计数二进制子串 p = new ques_696_计数二进制子串(); 39 System.out.println(p.countBinarySubstrings(s)); 40 } 41 }
5、基本计算器II
基础知识:
1 eg: 2 中缀:9*8+(14-8/2)*3 3 前缀:+ * 9 8 * - 14 / 8 2 3 4 后缀:9 8 * 14 8 2 / - 3 * + 5 1、中缀表达式转前缀表达式 6 ①初始化两个栈S1,S2,从右往左扫描中缀式。 7 ②遇到操作数:将其压入S2栈。 8 ③遇到括号时: 9 若是右括号‘)’,将其压入S1栈; 10 若是左括号‘(’,则依次弹出S1栈的元素,并将其压入S2栈,直至S1栈栈顶元素为右括号‘)’,弹出这个右括号。 11 ④遇到运算符时: 12 若S1栈为空或者其栈顶元素为右括号‘)’,将其压入S1。 13 否则,比较运算符和S1栈顶运算符(一定是运算符)的优先级: 14 若其优先级≥S1栈顶运算符,则将其压入S1; 15 若小于,则将S1栈顶运算符弹出并压入S2,重新进行步骤④。 16 ⑤重复②③④直到到达中缀式最左边,将S1剩余元素压入S2。最后依次取出S2元素即为前缀表达式。 17 2、求前缀表达式的值 18 ①初始化一个栈S,从右往左扫描前缀式。 19 ②遇到操作数时,则将其压入栈S。 20 ③遇到运算符时,取出栈S的栈顶元素和次顶元素,运行运算。栈顶元素 运算符 次顶元素 = 结果。将结果压入栈S。 21 ④重复②③直到到达前缀式最左边,此时栈S栈顶元素即为计算结果。 22 3、中缀表达式转后缀表达式 23 ①初始化两个栈S1,S2,从右往左扫描中缀式。 24 ②遇到操作数:将其压入S2栈。 25 ③遇到括号时: 26 若是左括号‘(’,将其压入S1栈; 27 若是右括号‘)’,则依次弹出S1栈的元素,并将其压入S2栈,直至S1栈栈顶元素为左括号‘(’,弹出这个左括号。 28 ④遇到运算符时: 29 若S1栈为空或者其栈顶元素为左括号‘(’,将其压入S1。 30 否则,比较运算符和S1栈顶运算符(一定是运算符)的优先级: 31 若其优先级>S1栈顶运算符,则将其压入S1; 32 若其优先级≤S1栈顶运算符,则将S1栈顶运算符弹出并压入S2,重新进行步骤④。 33 ⑤重复②③④直到到达中缀式最右边。将S1剩余元素压入S2。最后依次取出S2元素进行倒序即为后缀表达式。 34 注意: 35 (1)开始: s1[* +] s2[9 8] 36 (2)遇左括号: s1[+ ( - /] s2[9 8 * 14 8 2] 37 (3)遇右括号: s1[+] s2[9 8 * 14 8 2 / - C],其中(弹出 38 (4)接着: s1[+ *] s2[9 8 * 14 8 2 / - 3] 39 (5)最后: s1[] s2[9 8 * 14 8 2 / - 3 * +] 40 4、求后缀表达式的值 41 ①初始化一个栈S,扫描后缀式。 42 ②遇到操作数时,则将其压入栈S。 43 ③遇到运算符时,取出栈S的栈顶元素和次顶元素,运行运算。次顶元素 运算符 栈顶元素 = 结果。将结果压入栈S。 44 ④重复②③直到到达前缀式最右边,此时栈S栈顶元素即为计算结果。 45 注意: 46 (1)s[9 8] 9*8=72 47 (2)s[72 14 8 2] 8/2=4 48 (3)s[72 14 4] 14-4=10 49 (4)s[72 10 3] 10*3=30 50 (5)s[72 30] 72+30=102 51 (6)s[102]
问题:
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。
示例 1:
输入:s = "3+2*2"
输出:7
示例 2:
输入:s = " 3/2 "
输出:1
示例 3:
输入:s = " 3+5 / 2 "
输出:5
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package LeetCode.test8_zifuchuan; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 import java.util.Stack; 6 7 /** 8 * 注意:此题通过772.Basic Calculator III (Hard)进行了拓展,通用!!! 9 */ 10 public class ques_227_基本计算器II { 11 Stack<String> s1; 12 Stack<String> s2; 13 Map<String, Integer> map; 14 15 public int calculate(String s) { 16 char[] chars = s.toCharArray(); 17 StringBuilder sb = new StringBuilder(); 18 for (char c : chars) { 19 if (c != ' ') { 20 sb.append(c); 21 } 22 } 23 String newS = sb.toString(); 24 s1 = new Stack<>(); 25 s2 = new Stack<>(); 26 map = new HashMap<>(); 27 map.put("+", 1); 28 map.put("-", 1); 29 map.put("*", 2); 30 map.put("/", 2); 31 // 计算后缀表达式 32 Stack<String> stack = getChange(newS); 33 return cal(stack); 34 } 35 36 private Stack<String> getChange(String newS) { // "9*8+(14-8/2)*3" 37 for (int i = 0; i < newS.length(); ) { 38 if (newS.charAt(i) >= '0' && newS.charAt(i) <= '9') { // 注意多位数的处理 39 int num = newS.charAt(i) - '0'; 40 i++; 41 while (i < newS.length() && newS.charAt(i) >= '0' && newS.charAt(i) <= '9') { 42 num = num * 10 + (newS.charAt(i) - '0'); 43 i++; 44 } 45 s2.push(String.valueOf(num)); 46 // 这里做处理 47 48 } else if (newS.charAt(i) == '(') { 49 s1.push(String.valueOf(newS.charAt(i))); 50 i++; 51 } else if (newS.charAt(i) == ')') { 52 while (!s1.empty()) { 53 String top = s1.pop(); 54 if (top.equals("(")) { 55 break; 56 } 57 s2.push(top); 58 } 59 i++; 60 } else { 61 if (s1.empty() || s1.peek().equals("(")) { 62 s1.push(String.valueOf(newS.charAt(i))); 63 i++; 64 } else { 65 if (map.get(String.valueOf(newS.charAt(i))) > map.get(s1.peek())) { 66 s1.push(String.valueOf(newS.charAt(i))); 67 i++; 68 } else { 69 String top = s1.pop(); 70 s2.push(top); // 依旧是当前的i重新判断 71 } 72 } 73 } 74 } 75 while (!s1.empty()) { 76 String top = s1.pop(); 77 s2.push(top); 78 } 79 Stack<String> stack = new Stack<>(); //倒序 80 while (!s2.empty()) { 81 stack.push(s2.pop()); 82 } 83 return stack; 84 } 85 86 private int cal(Stack<String> stack) { 87 Stack<Integer> newStack = new Stack<>(); 88 while (!stack.empty()) { 89 String pop = stack.pop(); 90 if (pop.equals("+") || pop.equals("-") || pop.equals("*") || pop.equals("/")) { 91 int temp1 = newStack.pop(); 92 int temp2 = newStack.pop(); 93 int temp; 94 if (pop.equals("+")) { 95 temp = temp2 + temp1; 96 } else if (pop.equals("-")) { 97 temp = temp2 - temp1; 98 } else if (pop.equals("*")) { 99 temp = temp2 * temp1; 100 } else { 101 temp = temp2 / temp1; 102 } 103 newStack.push(temp); 104 } else { 105 newStack.push(Integer.valueOf(pop)); 106 } 107 } 108 return newStack.pop(); 109 } 110 } 111 112 class Test_227 { 113 public static void main(String[] args) { 114 String s = "9*8+(14-8/2)*3"; 115 ques_227_基本计算器II p = new ques_227_基本计算器II(); 116 System.out.println(p.calculate(s)); 117 } 118 }
6、实现strStr
问题:
实现 strStr() 函数。
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。
说明:
当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。
示例 1:
输入:haystack = "hello", needle = "ll"
输出:2
示例 2:
输入:haystack = "aaaaa", needle = "bba"
输出:-1
示例 3:
输入:haystack = "", needle = ""
输出:0
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package LeetCode.test8_zifuchuan; 2 3 /** 4 * 思路:KMP算法(https://www.xdull.cn/kmp.html) 5 * 不太好理解,直接记住就完事了!!! 6 */ 7 public class ques_28_实现strStr { 8 public int strStr(String haystack, String needle) { 9 int[] next = getNext(needle); 10 int m = haystack.length(); 11 int n = needle.length(); 12 if (n == 0) { 13 return 0; 14 } 15 int i = 0, j = 0; 16 while (i < m) { 17 if (haystack.charAt(i) == needle.charAt(j)) { 18 i++; 19 j++; 20 } else { 21 if (j > 0) { 22 j = next[j - 1]; 23 } else { 24 i++; 25 } 26 } 27 if (j == n) { 28 return i - n; 29 } 30 } 31 return -1; 32 } 33 34 private int[] getNext(String needle) { //ababc 35 int j = 0; 36 int i = 1; 37 int len = needle.length(); 38 int[] next = new int[len]; 39 while (i < len) { 40 if (needle.charAt(i) == needle.charAt(j)) { 41 next[i] = j + 1; 42 i++; 43 j++; 44 } else { 45 if (j > 0) { 46 j = next[j - 1]; 47 } else { 48 next[i] = 0; 49 i++; 50 } 51 } 52 } 53 return next; 54 } 55 } 56 57 class Test_28 { 58 public static void main(String[] args) { 59 String haystack = "hello"; 60 String needle = "ll"; 61 ques_28_实现strStr s = new ques_28_实现strStr(); 62 System.out.println(s.strStr(haystack, needle)); 63 } 64 }
7、最长回文串
问题:
给定一个包含大写字母和小写字母的字符串 s ,返回 通过这些字母构造成的 最长的回文串 。
在构造过程中,请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串。
示例 1:
输入:s = "abccccdd"
输出:7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
示例 2:
输入:s = "a"
输入:1
示例 3:
输入:s = "bb"
输入: 2
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package LeetCode.test8_zifuchuan; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 public class ques_409_最长回文串 { 7 public int longestPalindrome(String s) { 8 Map<Character, Integer> map = new HashMap<>(); 9 for (int i = 0; i < s.length(); i++) { 10 if (!map.containsKey(s.charAt(i))) { 11 map.put(s.charAt(i), 1); 12 } else { 13 map.put(s.charAt(i), map.get(s.charAt(i)) + 1); 14 } 15 } 16 System.out.println(map); 17 int num = 0; 18 for (Character c : map.keySet()) { 19 if (map.get(c) % 2 == 0) { 20 num += map.get(c); 21 } else { 22 num += (map.get(c) - 1); 23 map.put(c, 1); 24 } 25 } 26 if (map.containsValue(1)){ 27 num++; 28 } 29 return num; 30 } 31 } 32 33 class Test_409 { 34 public static void main(String[] args) { 35 // String s = "ccc"; 36 // String s = "abccccdd"; 37 String s = "ababababa"; 38 ques_409_最长回文串 p = new ques_409_最长回文串(); 39 System.out.println(p.longestPalindrome(s)); 40 } 41 }
8、无重复字符的最长子串
问题:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package LeetCode.test8_zifuchuan; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 /** 7 * 思路:滑动窗口 abcabcbb 8 * 进入这个窗口为abc,满足题目要求,当再进入a时,队列变成了abca,这时候不满足要求,要把队列的左边的元素移出。 9 */ 10 public class ques_3_无重复字符的最长子串 { 11 public int lengthOfLongestSubstring(String s) { 12 if (s.length() == 0) { 13 return 0; 14 } 15 Map<Character, Integer> map = new HashMap<>(); 16 int max = 0; 17 int left = 0; 18 for (int i = 0; i < s.length(); i++) { 19 if (map.containsKey(s.charAt(i))) { 20 left = Math.max(left, map.get(s.charAt(i)) + 1); 21 // eg:abba 没有max的时候(i=2,left=2) (i=3,left=1) 22 } 23 map.put(s.charAt(i), i); 24 max = Math.max(max, i - left + 1); 25 } 26 return max; 27 } 28 } 29 30 class Test_3 { 31 public static void main(String[] args) { 32 // String s = "pwwkew"; 33 String s = "abba"; 34 ques_3_无重复字符的最长子串 p = new ques_3_无重复字符的最长子串(); 35 System.out.println(p.lengthOfLongestSubstring(s)); 36 } 37 }
9、最长回文子串
问题:
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package LeetCode.test8_zifuchuan; 2 3 /** 4 * 思路:对于字符串“ababa”,如果已经知道“bab”是回文串,那么“ababa” 一定是回文串,这是因为它的首尾两个字母都是“a”。 5 * P(i,j)=P(i+1,j−1)∧(S[i]=S[j])(子串长度大于2) 6 * 对于长度为1的子串,它显然是个回文串;对于长度为2的子串,只要它的两个字母相同,它就是一个回文串。 7 */ 8 public class ques_5_最长回文子串 { 9 public String longestPalindrome(String s) { 10 int len = s.length(); 11 if (len < 2) { 12 return s; 13 } 14 boolean[][] dp = new boolean[len][len]; 15 int maxLength = 1; 16 int maxLeft = 0; 17 for (int i = 0; i < len; i++) { // a这种情况 18 dp[i][i] = true; 19 } 20 char[] chars = s.toCharArray(); 21 for (int i = 1; i <= len; i++) { 22 //定义左边界 23 for (int left = 0; left < len; left++) { 24 //定义右边界 25 int right = i + left; 26 if (right >= len) { 27 break; 28 } 29 if (chars[left] != chars[right]) { 30 dp[left][right] = false; 31 } else { 32 if (right - left < 3) { 33 dp[left][right] = true; // aa这种情况 34 } else { 35 dp[left][right] = dp[left + 1][right - 1]; 36 } 37 } 38 if (dp[left][right] && right - left + 1 > maxLength) { // 记录最大长度和此时的左边界 39 maxLength = right - left + 1; 40 maxLeft = left; 41 } 42 } 43 } 44 return s.substring(maxLeft, maxLeft + maxLength); 45 } 46 } 47 48 class Test_5 { 49 public static void main(String[] args) { 50 // String s = "babad"; 51 String s = "cbbd"; 52 ques_5_最长回文子串 p = new ques_5_最长回文子串(); 53 System.out.println(p.longestPalindrome(s)); 54 } 55 }