这里写目录标题
编程之美 3.1
s1 = AABCD, s2 = CDAA
Return : true
给定两个字符串 s1 和 s2,要求判定 s2 是否能够被 s1 做循环移位得到的字符串包含。
s1 进行循环移位的结果是 s1s1 的子字符串,因此只要判断 s2 是否是 s1s1 的子字符串即可。
2. 字符串循环移位
编程之美 2.17
s = "abcd123" k = 3
Return "123abcd"
将字符串向右循环移动 k 位。
将 abcd123 中的 abcd 和 123 单独翻转,得到 dcba321,然后对整个字符串进行翻转,得到 123abcd。
3. 字符串中单词的翻转
程序员代码面试指南
s = "I am a student"
Return "student a am I"
将每个单词翻转,然后将整个字符串翻转。
4. 两个字符串包含的字符是否完全相同
242. Valid Anagram (Easy)
s = "anagram", t = "nagaram", return true.
s = "rat", t = "car", return false.
可以用 HashMap 来映射字符与出现次数,然后比较两个字符串出现的字符数量是否相同。
由于本题的字符串只包含 26 个小写字符,因此可以使用长度为 26 的整型数组对字符串出现的字符进行统计,不再使用 HashMap。
public boolean isAnagram(String s, String t) {
int[] cnts = new int[26];
for (char c : s.toCharArray()) {
cnts[c - 'a']++;
}
for (char c : t.toCharArray()) {
cnts[c - 'a']--;
}
for (int cnt : cnts) {
if (cnt != 0) {
return false;
}
}
return true;
}
5. 计算一组字符集合可以组成的回文字符串的最大长度
Input : "abccccdd"
Output : 7
Explanation : One longest palindrome that can be built is "dccaccd", whose length is 7.
使用长度为 256 的整型数组来统计每个字符出现的个数,每个字符有偶数个可以用来构成回文字符串。
因为回文字符串最中间的那个字符可以单独出现,所以如果有单独的字符就把它放到最中间。
public int longestPalindrome(String s) {
int[] cnts = new int[256];
for (char c : s.toCharArray()) {
cnts[c]++;
}
int palindrome = 0;
for (int cnt : cnts) {
palindrome += (cnt / 2) * 2;
}
if (palindrome < s.length()) {
palindrome++; // 这个条件下 s 中一定有单个未使用的字符存在,可以把这个字符放到回文的最中间
}
return palindrome;
}
6. 字符串之间的关系问题
字符串同构
Given "egg", "add", return true.
Given "foo", "bar", return false.
Given "paper", "title", return true.
记录一个字符上次出现的位置,如果两个字符串中的字符上次出现的位置一样,那么就属于同构。
//好处: 不需要再循环一次了。
上下两个都需要map,不能使用一个map,除非两个的字符串中的映射都是一致的比如两个的a都映射到c,这样用一个map
public boolean isIsomorphic(String s, String t) {
int n = s.length();
int[] mapS = new int[128];
int[] mapT = new int[128];
for (int i = 0; i < n; i++) {
char c1 = s.charAt(i);
char c2 = t.charAt(i);
//当前的映射值是否相同
if (mapS[c1] != mapT[c2]) {
return false;
} else {
//是否已经修改过,修改过就不需要再处理
if (mapS[c1] == 0) {
mapS[c1] = i + 1;
mapT[c2] = i + 1;
}
}
}
return true;
}
比较一般的方法
public boolean isIsomorphic(String s, String t) {
return isIsomorphicHelper(s, t) && isIsomorphicHelper(t, s);
}
private boolean isIsomorphicHelper(String s, String t) {
int n = s.length();
HashMap<Character, Character> map = new HashMap<>();
for (int i = 0; i < n; i++) {
char c1 = s.charAt(i);
char c2 = t.charAt(i);
if (map.containsKey(c1)) {
if (map.get(c1) != c2) {
return false;
}
} else {
map.put(c1, c2);
}
}
return true;
}
public boolean wordPattern(String pattern, String str) {
HashMap<Character,String> map = new HashMap<>();
String[] array = str.split(" ");
if(pattern.length() != array.length){
return false;
}
for(int i = 0; i < pattern.length();i++){
char key = pattern.charAt(i);
if(map.containsKey(key)){
if(!map.get(key).equals(array[i])){
return false;
}
}else{
//判断 value 中是否存在
if(map.containsValue(array[i])){
return false;
}
map.put(key, array[i]);
}
}
return true;
}
作者:windliang
链接:https://leetcode-cn.com/problems/word-pattern/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by--53/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
7.回文串
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
1.最简单的,回文的判断一定要直接拿过来做
2,回溯法,类似于全排列
在这里插入代码片
class Solution {
public int minCut(String s) {
int[] dp = new int[s.length()];
dp[0] = 0;
for(int i = 1; i < s.length(); i++){
dp[i] = dp[i-1]+1;
for(int j = 0; j < i; j++){
if(checkPalindrome(s,j,i)){
dp[i] = j > 0 ? Math.min(dp[j-1]+1,dp[i]) : 0;
}
}
}
return dp[s.length()-1];
}
private boolean checkPalindrome(String str, int left, int right) {
// 严格小于即可
while (left < right) {
if (str.charAt(left) != str.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
}
更简单一点:使用动态规划存储是不是回文
if (s.charAt(i) == s.charAt(j) && (i - j < 2 || dp[j + 1][i - 1])) {
dp[j][i] = true;
min_s[i] = j == 0 ? 0 : Math.min(min_s[i], min_s[j - 1] + 1);
}
class Solution {
public int minCut(String s) {
int n = s.length();
int[] min_s = new int[n];
boolean[][] dp = new boolean[n][n];
for (int i = 0; i < n; i++) {
min_s[i] = i;
for (int j = 0; j <= i; j++) {
if (s.charAt(i) == s.charAt(j) && (i - j < 2 || dp[j + 1][i - 1])) {
dp[j][i] = true;
min_s[i] = j == 0 ? 0 : Math.min(min_s[i], min_s[j - 1] + 1);
}
}
}
return min_s[n - 1];
}
}
作者:powcai
链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii/solution/zi-ding-xiang-xia-he-zi-di-xiang-shang-by-powcai-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
7.0 回文子字符串个数
647. Palindromic Substrings (Medium)
//主要思想,遍历一遍 以每个字符串为核心
Input: "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".
从字符串的某一位开始,尝试着去扩展子字符串。
private int cnt = 0;
public int countSubstrings(String s) {
for (int i = 0; i < s.length(); i++) {
extendSubstrings(s, i, i); // 奇数长度
extendSubstrings(s, i, i + 1); // 偶数长度
}
return cnt;
}
private void extendSubstrings(String s, int start, int end) {
while (start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)) {
start--;
end++;
cnt++;
}
}
//我的不简洁
class Solution {
int res = 0;
public int countSubstrings(String s) {
for(int i = 0; i < s.length(); i++){
helper(s, i);
}
return res;
}
private void helper(String s, int ind) {
int start = ind;
int end = ind;
//回文的个数是奇数
while(start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)){
res++;
start--;
end++;
}
//个数是偶数
if(ind > 0){
start = ind - 1;
end = ind;
while(start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)){
res++;
start--;
end++;
}
}
}
}
7.1分割回文串
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
回溯法:类似与全排列的情况。在最后一步添加
class Solution {
public List<List<String>> partition(String s) {
List<List<String>> res = new ArrayList<>();
backtrack(res, s, new ArrayList<String>());
return res;
}
private void backtrack(List<List<String>> res, String s, ArrayList<String> tmp) {
if (s == null || s.length() == 0) res.add(new ArrayList<>(tmp));
for (int i = 1; i <= s.length(); i++) {
if (isPalidrome(s.substring(0, i))) {
// System.out.println(s.substring(0, i));
tmp.add(s.substring(0, i));
backtrack(res, s.substring(i, s.length()), tmp);
tmp.remove(tmp.size() - 1);
}
}
}
private boolean isPalidrome(String sb) {
int left = 0;
int right = sb.length() - 1;
while (left < right) {
if (sb.charAt(left) != sb.charAt(right)) return false;
left++;
right--;
}
return true;
}
}
作者:powcai
链接:https://leetcode-cn.com/problems/palindrome-partitioning/solution/dong-tai-gui-hua-dfs-by-powcai/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
7.2 最长回文子串
中心扩散法 巧妙,奇数个偶数个的情况都考虑了
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) return "";
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return R - L - 1;
}
作者:LeetCode
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
动态规划 这个好,边界不用考虑
public class Solution {
public String longestPalindrome(String s) {
int len = s.length();
if (len < 2) {
return s;
}
boolean[][] dp = new boolean[len][len];
// 初始化
for (int i = 0; i < len; i++) {
dp[i][i] = true;
}
int maxLen = 1;
int start = 0;
for (int j = 1; j < len; j++) {
for (int i = 0; i < j; i++) {
if (s.charAt(i) == s.charAt(j)) {
if (j - i < 3) {
dp[i][j] = true;
} else {
dp[i][j] = dp[i + 1][j - 1];
}
} else {
dp[i][j] = false;
}
// 只要 dp[i][j] == true 成立,就表示子串 s[i, j] 是回文,此时记录回文长度和起始位置
if (dp[i][j]) {
int curLen = j - i + 1;
if (curLen > maxLen) {
maxLen = curLen;
start = i;
}
}
}
}
return s.substring(start, start + maxLen);
}
}
作者:liweiwei1419
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
8. 判断一个整数是否是回文数
9. Palindrome Number (Easy)
要求不能使用额外空间,也就不能将整数转换为字符串进行判断。
将整数分成左右两部分,右边那部分需要转置,然后判断这两部分是否相等。
public boolean isPalindrome(int x) {
if (x == 0) {
return true;
}
if (x < 0 || x % 10 == 0) {
return false;
}
int right = 0;
//x是右半部分的数构建的
while (x > right) {
right = right * 10 + x % 10;
x /= 10;
}
//如果是奇数,只需要除以10即可
return x == right || x == right / 10;
}
9. 统计二进制字符串中连续 1 和连续 0 数量相同的子字符串个数
696. Count Binary Substrings (Easy)
Input: "00110011"
Output: 6
Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01".
//1 将字符串分为不同的groups
//每个groups都
//使用preLen记录前一个group,思想很好
public int countBinarySubstrings(String s) {
int preLen = 0, curLen = 1, count = 0;
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) == s.charAt(i - 1)) {
curLen++;
} else {
preLen = curLen;
curLen = 1;
}
if (preLen >= curLen) {
count++;
}
}
return count;
}
//我的思路, 和上一道题类似,轮询下,以i和i-1为枢轴,如果满足条件就扩大/
class Solution {
int res = 0;
public int countBinarySubstrings(String s) {
for(int i = 1; i < s.length(); i++){
helper(s, i - 1, i);
}
return res;
}
private void helper(String s, int b, int e){
if(s.charAt(b)==s.charAt(e)) return;
res++;
while(b > 0 && e < s.length() - 1 && s.charAt(b-1)==s.charAt(b) && s.charAt(e)==s.charAt(e+1)){
res++;
b--;
e++;
}
}
}
原来可以叫做中心扩展法
public int countBinarySubstrings(String s) {
int result = 0;
char[] chars = s.toCharArray();
for(int i = 1; i < s.length(); i++){
int left = i - 1, right = i;
char leftChar = chars[left], rightChar = chars[right];
if(leftChar == rightChar)
continue;
while(left >= 0 && right < s.length() && chars[left] == leftChar && chars[right] == rightChar){
left--;
right++;
result++;
}
}
return result;
}
作者:ustcyyw
链接:https://leetcode-cn.com/problems/count-binary-substrings/solution/696java-zhong-xin-kuo-zhan-yu-hui-wen-chuan-xiang-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
10.不同的子序列
给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数。
一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE"
是 "ABCDE"
的一个子序列,而 "AEC"
不是)
题目数据保证答案符合 32 位带符号整数范围。
子串问题
重复的DNA序列
class Solution {
List<String> ans = new ArrayList<>() ;
HashSet<String> set = new HashSet<>() ;
public List<String> findRepeatedDnaSequences(String s) {
if(s == null) return ans ;
int len = s.length() ;
if(len <= 10) return ans ;
for(int i = 0 ; i + 10 <= len ; i++){
String temp = s.substring(i,i+10) ;
if(set.add(temp)){
continue ;
}else if(!ans.contains(temp)){
ans.add(temp) ;
}
}
return ans ;
}
}
我的:使用lambda去重
class Solution {
public List<String> findRepeatedDnaSequences(String s) {
//暴力:每隔十个放到map中
List<String> res = new ArrayList<>();
Set<String> map = new HashSet<>();
for (int i = 0; i < s.length(); i++) {
if(i+10 <= s.length()){
String temp = s.substring(i,i+10);
if(map.contains(temp)) {
res.add(temp);
continue;
}
map.add(temp);
}else{
break;
}
}
return res.stream().distinct().collect(Collectors.toList());
}
}
匹配问题
验证IP地址
- 根据分割后长度的不同,分成两种情况考虑
- 每种情况仔细考虑不同的情况
class Solution {
public String validIPAddress(String IP) {
String[] IP4Arr = IP.split("\\.",-1);
if(IP4Arr.length == 4){
return isIP4Arr(IP4Arr);
}
String[] IP6Arr = IP.split(":",-1);
if(IP6Arr.length == 8){
return isIP6Arr(IP6Arr);
}
return "Neither";
}
public String isIP4Arr(String[] IP4Arr){
for(String ip : IP4Arr){
if(ip.length() > 3 || ip.length() <= 0){
return "Neither";
}
for(int i = 0 ;i < ip.length();++i){
if(!Character.isDigit(ip.charAt(i))){
return "Neither";
}
}
int num = Integer.parseInt(ip);
if(num > 255 || String.valueOf(num).length() != ip.length()){
return "Neither";
}
}
return "IPv4";
}
public String isIP6Arr(String[] IP6Arr){
for(String ip : IP6Arr){
if(ip.length() > 4 || ip.length() <= 0){
return "Neither";
}
for(int i = 0 ;i < ip.length();++i){
char c = ip.charAt(i);
if(!Character.isDigit(c) && !( 'a' <= c && c <= 'f') && !('A' <= c && c <= 'F')){
return "Neither";
}
}
}
return "IPv6";
}
}
作者:souljoy
链接:https://leetcode-cn.com/problems/validate-ip-address/solution/zhi-xing-yong-shi-1-ms-zai-suo-you-java-ti-jia-203/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
动态字符串
Z 字形变换
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1) return s;
vector<string> rows(min(numRows, int(s.size())));
int curRow = 0;
bool goingDown = false;
for (char c : s) {
rows[curRow] += c;
if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
curRow += goingDown ? 1 : -1;
}
string ret;
for (string row : rows) ret += row;
return ret;
}
};
作者:LeetCode
链接:https://leetcode-cn.com/problems/zigzag-conversion/solution/z-zi-xing-bian-huan-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。