前提:给定一个数组arr,长度为N,arr中的值不是0就是1.arr[i]表示第i栈灯的状态,0表示灭灯,1表示亮灯。每一盏灯都有开关,但是按下i号灯的开关会改变i-1,i,i+1栈灯的状态。
问题一:如果N栈灯排成一条直线,请问最少按下多少次开关,能让灯都亮起来i为中间位置时,i号灯的开关能影响i-1,i,i+1,0号灯的开关只能影响0和1位置的灯N-1号灯只能影响N-2和N-1位置的灯。
思想:迭代法,通过记录前一位状态和当前状态,迭代交替的遍历发现为状态零则进行转变,每转变一次计数加一,到最后判断当前状态是否等于前一状态,等于则返回计数值,不等于则返回无穷。函数主体进行俩中状态的比较一种是改变当前状态,一种是不做改变,看哪种返回值最小。
代码
public static int noloopRight3(int[] arr) {
if(arr.length == 1) {
return arr[0] ^ 1;
}else if(arr.length == 2) {
return arr[0] !=arr[1] ? Integer.MAX_VALUE: arr[0] ^ 1;
}
//不改变状态
int p1 = iteraterLight(arr, arr[0], arr[1]);
int p2 = iteraterLight(arr, arr[0] ^ 1, arr[1] ^ 1);
p2 = p2 == Integer.MAX_VALUE? p2 : p2 +1;
return Math.min(p1, p2);
}
public static int iteraterLight(int[] arr, int proStatus, int curStatus) {
int i = 2;
int op = 0;
while(i < arr.length) {
if(proStatus == 0) {
op++;
proStatus = curStatus ^ 1;
curStatus = arr[i++] ^ 1;
}else {
proStatus = curStatus;
curStatus = arr[i++];
}
}
return proStatus != curStatus ? Integer.MAX_VALUE: op + curStatus ^ 1;
}
问题二:如果N栈灯排成一个圈,请问最少按下多少次开关,能让灯都亮起来 i为中间位置时,i号灯的开关能影响i-1,i,i+1,0号灯的开关能影响N-1,0和1位置的灯,N-1号灯能影响0,N-2和N-1位置的灯。
思想:同样迭代法,与方法一相比要多考虑几种情况多输入起始位置状态,终止位置状态。在循环迭代完要再进行一次终止位置的判断,就是在考虑proStatus==0和!=0的情况。然后函数主体pro从arr[1]开始cur从arr[2]开始。分别讨论0位置状态是否改变和1位置状态是否改变四种情况。
代码:
public static int haveloopLight3(int[] arr) { if(arr.length == 1) { return arr[0] ^ 1; } if(arr.length == 2) { return arr[0] != arr[1] ? Integer.MAX_VALUE : arr[0] ^ 1; } if(arr.length == 3) { return arr[0] != arr[1] || arr[0] !=arr[2]? Integer.MAX_VALUE : arr[0] ^ 1; } int p1 = iteraterLight2(arr, arr[1], arr[2], arr[0], arr[arr.length-1]); //0变1不变 int p2 = iteraterLight2(arr, arr[1] ^ 1, arr[2], arr[0] ^ 1, arr[arr.length-1] ^ 1); //0不变1变 int p3 = iteraterLight2(arr, arr[1] ^ 1, arr[2] ^ 1, arr[0] ^ 1, arr[arr.length-1]); //0变1变 int p4 = iteraterLight2(arr, arr[1], arr[2] ^ 1, arr[0], arr[arr.length - 1] ^ 1); p2 = p2 == Integer.MAX_VALUE? p2 : p2 + 1; p3 = p3 == Integer.MAX_VALUE? p3 : p3 + 1; p4 = p4 == Integer.MAX_VALUE? p4 : p4 + 2; return Math.min(Math.min(p1, p2), Math.min(p3, p4)); } public static int iteraterLight2(int[] arr,int proStatus, int curStatus, int firstStatus,int endStatus) { int index = 3; int op = 0; while(index < arr.length) { if(proStatus == 0) { op++; proStatus = curStatus ^ 1; curStatus = arr[index++] ^ 1; }else { proStatus = curStatus; curStatus = arr[index++]; } } if(proStatus == 0) { proStatus = curStatus ^ 1; endStatus ^= 1; curStatus = endStatus; }else { proStatus = curStatus; curStatus = endStatus; } return firstStatus != endStatus || proStatus != curStatus ? Integer.MAX_VALUE : op + curStatus ^ 1; }