发布于 

剑指Offer.46-把数字翻译成字符串&48-最长不含重复字符的子字符串

剑指Offer.46-把数字翻译成字符串&
剑指Offer.48-最长不含重复字符的子字符串

剑指 Offer 46. 把数字翻译成字符串

思路

该题是一道将数字翻译为字符串的题目,是斐波那契数列的变种问题。需要找到斐波那契数列的递进关系

状态转移方程组

情况1:当读取第一个数字的时候一定能够被翻译为1个字母,故dp[0]=1,dp[1]=1,当读取到第二个字母时,若其与前一个数字组合无法被翻译成新的字母时,此时依旧只有1种翻译的方法,dp[i]=dp[i-1]

当第二个字母能够与第一个字母一起被翻译为一个字母时,dp[i] = dp[i-2] + dp[i-1]

1
2
f(i) = f(i-2) + f(i-1)  //当数字x(i-1)x(i)能够被翻译为一个字母时
f(i) = f(i-1) //当数字x(i-1)x(i)不能被翻译为一个字母时

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int translateNum(int num) {
//斐波那契数列变种问题
//初始值[0] = 0
//[1] = 1
String s = String.valueOf(num);
int dp[] = new int[s.length() + 1];
dp[0] = 1;
dp[1] = 1;
//遍历时index应-1
for(int i=2;i<=s.length() ;i++){
String subNum = String.valueOf(s.charAt(i-2));
subNum += s.charAt(i-1);
Integer snum = Integer.parseInt(subNum);
if(snum >=10 && snum <= 25){
dp[i] = dp[i-1] + dp[i-2];
} else{
dp[i] = dp[i-1];
}
}
return dp[s.length()];
}
}

剑指 Offer 48. 最长不含重复字符的子字符串

问题描述

请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度

状态转移方程

首先定义f(i)表示以第i个字符结尾不包含重复字符的最长子串长度,当第i个字符在之前没有出现过时,f(i)=f(i-1)+1直接进行加1操作。

当第i个字符已经出现过,需要分两种情况进行讨论,首先计算第i个字符距离上次出现的字符的距离,将其记为d,这意味着两个重复字符之间的子串中没有其他重复的字符。当d小于或者等于f(i-1)时,等于上次字符出现的位置在f(i-1)对应的子串中,新无重复最大子串的长度即为d。

当d大于f(i-1)时,证明上次该字符上次出现的位置不在上个无重复最长子串中,可直接在其后进行追加,故此时f(i)=f(i-1)+1,将条件合并后得到状态转移方程。

1
2
dp[i] = dp[i-1]+1   //dp[i-1] < j-i
dp[i] = j-i //dp[i-1] >= j-i

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 动态规划
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character,Integer> map = new HashMap<>();
int res = 0,tmp = 0;
for(int j=0;j<s.length();j++){
int i = map.getOrDefault(s.charAt(j),-1);
map.put(s.charAt(j),j);
tmp = tmp < j - i?tmp+1:j-i;
res = Math.max(res,tmp);
}
return res;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 双指针 滑动窗口
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character,Integer> window = new HashMap<Character,Integer>();
int left = 0;
int right = 0;
int max = 0;
while(right < s.length()){
Character r = s.charAt(right);
right++;
//进行窗口内数据的一系列更新
if(window.containsKey(r)){
window.put(r,window.get(r)+1);
}else{
window.put(r,1);
}

//缩小窗口的条件需要自行指定
while(window.get(r) > 1){
Character l = s.charAt(left);
left++;
window.put(l,window.get(l)-1);
}
max = Math.max(right-left,max);
}
return max;
}
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 @John Doe 创建,使用 Stellar 作为主题。