很难 一般不考
inplace算法 重要
f(i,N) 给定一个i位置,知道最终在哪个位置
当长度是3^k-1 环的起始点是1,3,。。。
3
k
−
1
3^{k-1}
3k−1
import javax.print.event.PrintEvent;
public class ShuffleProblem {
public static void shuffle(int[] arr,int L,int R){
while(R - L + 1 > 0){
int len = R - L + 1;
int base = 3;
int k = 1;
while(base <= (len + 1)/3){
base *= 3;
k++;
}
int half = (base - 1)/ 2;
int mid = (L + R)/2;
rotate(arr,L+half,mid,mid+half);
cycles(arr,L,base-1,k);
L = L + base - 1;
}
public static void cycles(int[] arr,int start,int len,int k){
for (int i = 0,trigger = 1; i < k ; i++,trigger*=3) {
int preValue = arr[trigger+start-1];
int cur = modifyIndex(trigger,len);
while(cur != trigger){
int tmp = arr[cur + start -1];
arr[cur + start -1] = preValue;
preValue = tmp;
cur = modifyIndex(cur,len);
}
arr[cur + start -1] = preValue;
}
}
public static void rotate(int[] arr,int L,int M,int R){
reverse(arr,L,M);
reverse(arr,M+1,R);
reverse(arr,L,R);
}
}
}
import java.util.Stack;
public class VisbleMountains {
//栈中的记录 从顶到di 由小到大
public static class Record{
public int value;
public int times;//收集的次数
public Record(int value){
this.value = value;
this.times = 1;
}
}
public static int getVisbleNum(int[] arr){
if(arr == null || arr.length < 2){
return 0;
}
int N = arr.length;
int maxIndex = 0;
//在环中找最大值在环中的位置
for (int i = 0; i < N; i++) {
maxIndex = arr[maxIndex] < arr[i] ? i : maxIndex;
}
Stack<Record> stack = new Stack<Record>();
//吧
stack.push(new Record(arr[maxIndex]));
//从最大值的下一个位置查找
int index = nextIndex(maxIndex,N);
//统计结果
int res = 0;
//遍历开始,再次相等说明转了一圈
while(index != maxIndex){
while(stack.peek().value < arr[index]){
int k = stack.pop().times;
//getInternalSum 是组合数Ck2
res += getInternalSum(k) + 2 * k;
}
//下面是栈内的元素大于等于arr【index]的情况
if(stack.peek().value == arr[index]){//相等的情况
stack.peek().times++;
}else{
stack.push(new Record(arr[index]));
}
index = nextIndex(index,N);
}
//清算阶段 ,只剩下栈内的元素
while(stack.size() > 2){
int times = stack.pop().times;
res += getInternalSum(times) + 2 * times;
}
if(stack.size() == 2){
int times = stack.pop().times;
res += getInternalSum(times)
+ (stack.peek().times == 1 ? times : 2 * times);
}
//这里我感觉有点问题 剩下最后一个最大的元素了,如果这个元素的个数大于1用这个没问题,内部Ck2,如果等于1.。应该是0吧。。
res += getInternalSum(stack.pop().times);
return res;
}
public static
//i的下一个位置
public static int nextIndex(int i,int size){
return i < (size - 1) ? (i + 1) : 0;
}
//i的上一个位置
public static int lastIndex(int i,int size){
return i > 0 ? (i-1) : (size -1);
}
}