topic
https://www.lintcode.com/problem/568
给出一个整数数组,所有的元素都在 [−10,10] 之间。
你有三次机会将数组中的一个数替换成任意数。
请求出可能的最长相等子段数列的长度。
数组的长度为 n, 1≤n≤10 ^5 。
第一个样例中,可以将数组变成
[0,0,0,0,0,3] 或者
[0,3,3,3,3,3],结果都是 5。
样例
输入:
[0,3,1,0,6,3]
输出:
5
输入:
[1,2]
输出:
2
Ideas
双指针即可:子串问题,通常考虑以某个位置为开头怎么样,某个位置结尾怎么样。
针对本题,我们考虑0...i 假设第i位不变,往后找到三个不同的位置,如果到了
位置j,j>i 时有4个数不等于i位置的数,那么就计算j-i之间的距离,取最大。
注意:整个数组的元素是一样的情况的,或者整个数组除了只有1个,2个,或者3个位置
的数不一样之外,其他位置一样的情况
Answer
public class Solution {
/**
* @param nums: an integer array.
* @return: return the possible longest length of the subarray that elements are the same.
*/
public int threeChances(int[] nums) {
int max = Integer.MIN_VALUE;
int n = nums.length;
if(n<=4) return n;
int L=0,R=1,cnt=0; //cnt 改变数超过3个,内层停止
for (; L<n-3 ; L++) {
int cur = nums[L]; //当前数不变动,让不一样的变成当前的一样
cnt = 0;
for (R=L+1; R< n; R++) {
int next = nums[R];
if(next!=cur)
cnt++;
if(cnt ==4){
max = Math.max(R-L,max);
break;
}
}
//R走到最后了,cnt小等于3个,那么可以结束循环了
if(cnt <=3){
//cnt:0数组中所有元素一样的情况以及其他情况
max = Math.max(max,R-L);
break;
}
}
return max;
}
}
local test code
public class LC568 {
public static int threeChances(int[] nums) {
int max = Integer.MIN_VALUE;
int n = nums.length;
if(n<=4) return n;
int L=0,R=1,cnt=0; //cnt 改变数超过3个,内层停止
for (; L<n-3 ; L++) {
int cur = nums[L]; //当前数不变动,让不一样的变成当前的一样
cnt = 0;
for (R=L+1; R< n; R++) {
int next = nums[R];
if(next!=cur)
cnt++;
if(cnt ==4){
max = Math.max(R-L,max);
break;
}
}
//R走到最后了,cnt小等于3个,那么可以结束循环了
if(cnt <=3){
//cnt:0数组中所有元素一样的情况以及其他情况
max = Math.max(max,R-L);
break;
}
}
return max;
}
public static void main(String[] args) {
System.out.println(threeChances(new int[]{
0,3,1,0,6,3})); //5
System.out.println(threeChances(new int[]{
1,2})); //2
System.out.println(threeChances(new int[]{
3,-4,-1,-5,4,6,6,7,-10,-5})); //5
System.out.println(threeChances(new int[]{
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0})); //68
}
}