问题描述
小F手中有一个长度为 N 的排列 P,它包含从 1 到 N 的元素。小F想知道是否可以通过一系列操作将排列 P 排序为升序排列。为了达到目标,他可以进行两种操作:
- 操作 1:选择两个索引
i和j(i < j),并交换P[i]和P[j]。 - 操作 2:对排列进行左移操作。例如,如果排列是
['1', '2', '3'],则左移后排列变为['2', '3', '1']。
你需要先执行一次 操作 1,然后可以进行任意多次 操作 2。
你需要帮助小F判断是否可以通过这些操作使排列 P 排序。如果可以返回 1,否则返回 0。特别的,如果长度 N 为1,请直接返回1。
例如:当 N = 3 且 P = [3, 2, 1] 时,小F可以选择 i = 0 和 j = 1,执行 操作 1,将排列变为 ['2', '3', '1']。接下来,执行两次 操作 2,排列变为 ['1', '2', '3'],已成功排序。因此,答案为 1。
测试样例
样例1:
输入:
N = 3,P = [3, 2, 1]
输出:1
样例2:
输入:
N = 4,P = [4, 3, 2, 1]
输出:1
样例3:
输入:
N = 5,P = [5, 4, 3, 2, 1]
输出:0
先执行一次操作一再多次操作二和先执行多次操作2再执行操作1效果是一样的。因为操作1只能执行一次,所以不符合递增规律的数不能超过两个。
import java.util.Arrays;
public class Main {
public static int solution(int N, int[] P) {
// PLEASE DO NOT MODIFY THE FUNCTION SIGNATURE
// write code here
//先找到最下的位置
int min=Integer.MAX_VALUE,i,len=P.length,minidx=0,j;
for(i=0;i<len;i++){
if(P[i]<min){
min=P[i];
minidx=i;
}
}
int[] newP=new int[len];
for(i=0;i<len;i++){
newP[i]=P[(minidx+i)%len];
}
System.out.println(Arrays.toString(newP));
int count=0,max=Integer.MIN_VALUE;
for(i=1;i<len;i++){
max=Math.max(max,newP[i]);
if(newP[i]<max||newP[i]<newP[i-1]){
count++;
}
}
System.out.println(count);
if(count>2){
return 0;
} else if (count==0) {
return 1;
}
int one=0 ,two=0 ;
for(i=1;i<len;i++){
if(newP[i]<newP[i-1]){
one=i;
break;
}
}
if(count==2){
for(i=one+1;i<len;i++){
if(newP[i]<newP[i-1]){
two=i;
break;
}
}
}
int tmp;
if(count==1){
tmp=newP[i];
newP[i]=newP[i-1];
newP[i-1]=tmp;
}else{
tmp=newP[one-1];
newP[one-1]=newP[two];
newP[two]=tmp;
}
for(i=1;i<len;i++){
if(newP[i]<newP[i-1]){
return 0;
}
}
return 1;
}
public static void main(String[] args) {
System.out.println(solution(3, new int[]{3, 2, 1}) == 1);
System.out.println(solution(4, new int[]{4, 3, 2, 1}) == 1);
System.out.println(solution(5, new int[]{5, 4, 3, 2, 1}) == 0);
}
}