您的位置:首页 > 其它

计蒜客 蓝桥杯模拟B组 程序设计 G 合并数字 尺取

2018-03-29 21:24 387 查看
//作为java组选手,不得不说,java丰富的封装类好像基本用不到,面向对象搞算法就再没用过,算是荒废了,要不是蓝桥杯报了java,哎。进入正题
尺取,是一种搜索剪枝的策略!尺取的过程是搜索,先声明这一点,接下来就好理解了。
接下来是数组模拟单向链表(说是单向链表,也许更像一颗一叉树,每个点都只指向上级节点)
头节点指向指向-1来表示null
初始化过程可以表示成,每个点的头节点就是他的下标减一(这样每个节点都指向了上一个节点且直接把头节点指向了null)。
不删除任何一个节点:
当l和r在当前位置不能保证相差一时,要保l,r相连,只能把l后移一位,r后移一位,(接下来会说明为什么r后面的元素没有被删除过,这里不证明),而l的下一位是r,这是显然的,所以这时,操作为:l=r++;
删除左侧节点:
删除的点是头节点:
头节点变为下一个点(l=r),r变成l的下一个节点,其实就是原来的r 的下一个节点,所以r++;这是,于不删除节点不同在于,重置了头节点,所以要让新的头节点不再指向原来的头节点而是null(-1)即next[l]=-1;
其他点:
删除l节点对前l-1个数没有影响,删除l后r的对应的值应不变。
删除右侧节点:
这个不太好说,先给个例子:
src的红色表示删除,nex的绿色表示l,黄色表示当前r,红色表示变化后的r,紫色表示移动后的l
 src     2 2 3 4 3 2 1
nex   -1 0 1 2 3 4 5

 src     2 2 3 4 3 2 1
nex   -1 0 1 1 3 4 5
 src     2 2 3 4 3 2 1
nex   -1 0 1 1 3 4 5
这里我们看到l从4到2的过程是越过了做为被删除的3的。
也就是说,删除右侧节点时,改变新右侧节点的next值可以在接下来的移动过程中保证l移动到这个点后返回没有删除的上一个点。
所以删除一个右侧节点要使得左侧节点不变,右侧节点变成下一个点。
所有操作介绍完了,我们来重新看刚才没有证明的内容。
对于所有操作 r节点自始至终没有左移过,而删除的点都在当前r的左侧,这是显然的。所以r后面的节点没有变化过。import java.util.*;
public class Main {
static Scanner in=new Scanner(System.in);
static int a[]=new int[100005];
static int next[]=new int[100005];
public static void main(String args[]) {
int n=in.nextInt();
for(int i=0;i<n;++i) {
next[i]=i-1;
a[i]=in.nextInt();
}
int l=0,r=1;
int ans=0;
while(l!=r&&r!=n) {
if(a[l]-a[r]==1) {
ans++;
if(next[l]==-1) {
l=r;
r++;
next[l]=-1;
}
else {
next[r]=l=next[l];
}
}
else if(a[r]-a[l]==1) {
ans++;
r++;
next[r]=l;
}
else {
l=r;
r++;
}
}
System.out.println(ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: