本质上是求有不超过两个不同字符的最长substring:
159. Longest Substring with At Most Two Distinct Characters [Medium]
/**
* 自己的代码
* 遍历寻找只包含两个不同值的substring的长度,并不断更新长度最大值得到结果
* 用nextStart代表下一个substring的开头位置,nextStart应该等于当前substring包含的两个值(也可能是一个)中,最后出现的那个值中,连续部分的第一个的位置
* Runtime: 9 ms, faster than 75.03%
* Memory Usage: 81 MB, less than 8.75%
*/
class Solution {
public int totalFruit(int[] fruits) {
int nextStart = 0, max = 1; // fruits.length >= 1, therefore max >= 1
while (nextStart < fruits.length - max) { // if the untraversed substring is shorter than the current "max", no bigger "max" will be found
Integer type1 = fruits[nextStart], type2 = null;
int count = 1;
while (nextStart < fruits.length - 1 && fruits[nextStart] == fruits[nextStart + 1]) {
nextStart++;
count++;
}
if (nextStart == fruits.length - 1) { // the substring contains only one value from nextStart to the end of "fruits"
max = Math.max(max, count);
return max;
}
type2 = fruits[++nextStart]; // find the second value
boolean isType1 = false; // mark the last value in the substring, for now is type2
for (int i = nextStart; i < fruits.length && (fruits[i] == type1 || fruits[i] == type2); i++) {
if (fruits[i] == type1) {
if (!isType1) { // current element is type1, but the former element is type2
isType1 = true;
nextStart = i;
}
} else if (isType1) { // current element is type2, but the former element is type1
isType1 = false;
nextStart = i;
}
count++;
}
max = Math.max(max, count);
}
return max;
}
}
/**
* 大神做法,countType2类似nextStart的作用,都是记录下一个子串开始的位置or长度,这里更绝
* 也是在遍历过程中不断更新nextStart和max,但遍历和更新的思路顺畅很多,直接每个字符遍历一次,不走回头路
* Runtime: 5 ms, faster than 90.85%
* Memory Usage: 77.1 MB, less than 12.58%
*/
class Solution {
public int totalFruit(int[] fruits) {
int max = 0, curr = 0, countType2 = 0, type1 = -1, type2 = -1; // countType2 is the continuously repeated time of the lastest character in the current substring
for (int f : fruits) {
if (f != type1 && f != type2) { // change to a new substring, update variables
max = Math.max(max, curr);
type1 = type2;
type2 = f;
curr = countType2 + 1;
countType2 = 1;
} else { // current substring continues: curr++
if (f == type2) { // current status continues: countType2++
countType2++;
} else { // current status changes: switch type1 and type2, and set countType2 to 1
type1 = type2;
type2 = f;
countType2 = 1;
}
curr++;
}
}
max = Math.max(max, curr);
return max;
}
}
/**
* 最大程度压缩了代码,但做了一些重复判断,降低了效率
* Runtime: 8 ms, faster than 76.18%
* Memory Usage: 77.6 MB, less than 10.59%
*/
class Solution {
public int totalFruit(int[] fruits) {
int max = 0, curr = 0, countType2 = 0, type1 = -1, type2 = -1;
for (int f : fruits) {
curr = f == type1 || f == type2 ? curr + 1 : countType2 + 1;
countType2 = f == type2 ? countType2 + 1 : 1;
if (f != type2) {
type1 = type2;
type2 = f;
}
max = Math.max(max, curr);
}
return max;
}
}
本文探讨了一种高效的算法解决LeetCode题目159:在一个整数数组中找到最多包含两个不同字符的最长连续子串。两种代码实现对比,一种遍历并更新,另一种通过计数器和状态转移简化。展示了如何在内存和运行时间上优化求解过程。

1087

被折叠的 条评论
为什么被折叠?



