[interview]螺旋队列问题
摘要
本文主要讲解三种螺旋队列的实现方式和打印输出:
- 从中心往外端顺时针旋转,记为『外螺旋队列』
- 从左顶点开始,绕剩下的最大圈顺时针往内旋转,记为『内螺旋队列』
- 从左顶点开始,之字形旋转(只能同行同列地移动),记为『 』螺旋队列』
- 从左顶点开始,之字形旋转(只能沿-45°斜线移动),记为 『/ 螺旋队列 』
前三个螺旋队列图示如下:
1. 外螺旋队列
通过几个标记位,来确定其他值的大小,
由这两个值再来确定其他值,首先,我们可以确定这个值的大致范围: maxAbs=max{ fabs(r),fabs(c)},这样这个值就在 (2maxAbs-1)2~(2maxAbs+1)2的范围。接下来,我们从东南西北四个方向分析具体的值:
令N=maxAbs, 标志位上平方数元素的表示为:
- 北:f(r,c)=f(−N,N)−(N−c),r=−N,r<c
- 东:f(r,c)=f(−(N−1),(N−1))+(r+(N−1))+1,c=N,r>−c
- 南:f(r,c)=f(N,−(N−1))−(c+(N−1)),r=N,r>c
- 西:f(r,c)=f(N,−(N−1))+(N−r)+1,c=−N,r<−c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
int rotQueue1( int r, int c) { if (r>0 && r+c==1) return (2*r)*(2*r); if (r<=0 && r+c==0) return (2*c+1)*(2*c+1); int N= fabs (r)> fabs (c)? fabs (r): fabs (c); if ( r==-N && r<c) return rotQueue1(-N,N)-(N-c); else if ( c==N && r>-c) return rotQueue1(-(N-1),(N-1))+(r+(N-1))+1; else if ( r==N && r>c ) return rotQueue1(N,-(N-1))-(c+(N-1)); else if ( c==-N && r<-c) return rotQueue1(N,-(N-1))+(N-r)+1; } |
2. 内螺旋队列
可以通过迭代建立数组,外圈循环从 i←0 to n/2,表示从外到内,循环圈子慢慢缩小,内圈循环从按照北东南西的顺序递增地建立数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
int **rotQueue2( int r, int c) { int **a=malloc2D(r,c); int m=1; for ( int i=0; i<r/2; i++) { for ( int j=i;j<c-1-i;j++) a[i][j] = m++; for ( int j=i;j<r-1-i;j++) a[j][c-1-i] = m++; for ( int j=c-1-i;j>i;j--) a[r-1-i][j] = m++; for ( int j=r-1-i;j>i;j--) a[j][i] = m++; } if (r%2==1&&c%2==1) a[r/2][c/2]=m; return a; } |
3. 』螺旋队列
有两个方法确定数组:
- 可用标志位——平方数的加减得到,行列标从1开始的话, a(2k,1)=(2k)2 , a(1,2k-1)=(2k-1)2 类似于rotQueue1
- 类似于内螺旋队列,整体迭代赋值建立数组,下面用第二种。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
int **rotQueue3( int N) { int **a=malloc2D(N,N); int m=1; a[0][0]=m++; for ( int i=1;i<N; ++i ){ if (i%2==1){ for ( int j=0;j<=i;++j) // j为行 a[j][i]=m++; for ( int j=i-1;j>=0;--j) // j为列 a[i][j]=m++; } else { for ( int j=0;j<=i;++j) // j为列 a[i][j]=m++; for ( int j=i-1;j>=0;--j) // j为行 a[j][i]=m++; } } return a; } |
4. / 螺旋队列 (zigzag数组)
可以将这个数组看成一个上三角形和一个倒三角形的组合。分成两部分赋值即可。(分析略去)。
5. 输出
最后,给出动态分配二维数组和打印程序,主程序与最后的结果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
int ** malloc2D( int r, int c) { int **pt2D =( int **) malloc ( r* sizeof ( int *) ); for ( int i=0; i< r;i++){ pt2D[i] = ( int *) malloc ( c* sizeof ( int ) ); for ( int j=0;j<c;j++) pt2D[i][j]=0; } return pt2D; } void printRotQueue( int **a, int r, int c) { for ( int i=0; i<r;i++){ for ( int j=0;j<c;j++){ printf ( "%3d " ,a[i][j]); } printf ( "\n" ); } } int main() { int r=5,c=5; printf ( "rotQueue1(%d,%d):\n" ,r,r); for ( int i= -r/2; i<=r/2 ; ++i ){ for ( int j= -r/2;j<=r/2;++j){ printf ( "%3d " ,rotQueue1(i,j) ); } printf ( "\n" ); } int ** a2=rotQueue2(r,c); printf ( "\nrotQueue2(%d,%d):\n" ,r,c); printRotQueue(a2,r,c); printf ( "\nrotQueue3(%d,%d):\n" ,r,r); int ** a3=rotQueue3(r); printRotQueue(a3,r,r); return 0; } |
设计模式——代理模式
一、引言
前些天,广州恒大在亚冠赛地上创造了中国足球历史,以8:1比分挺进决赛。虽然我不怎么看足球,毕竟中国的足球,你都知道的啦,但还是挺为恒大感到骄傲,希望恒大能如愿的拿到冠军.....今天我将以亚冠买门票为题引出我今天想写的代理模式吧。
二、代理模式定义
1. 定义:代理模式也叫委托模式,代理模式为另一个对象提供一个替身或点位符以控制对这个对象的访问。
2. 类图:【如下图所示】
3. 类图说明
客户端与RealSubject交互时都必须通过Proxy。因为Proxy和RealSubject实现相同的接口(Subject),所以任何使用到RealSubject的地方,都可以用Proxy取代。同时Proxy也控制了对RealSubject的访问,如本例中,before()及after()的使用。
三、代理模式示例
1. Subject
package com.pattern.proxy.core; /** * 球迷接口 * @author yemaoan * */ public interface IFans { void buyTicket(); }
2. RealSubject
package com.pattern.proxy.core; /** * 球迷买票 * @author yemaoan * */ public class Fans implements IFans { private String name; public Fans(String name) { this.name = name; } public void buyTicket() { System.out.println(this.name + " 购买门票..."); } }
3. Proxy
package com.pattern.proxy.core; /** * 售票点 * @author yemaoan * */ public class Wicket implements IFans { private IFans fans; public Wicket(IFans fans) { this.fans = fans; } public void buyTicket() { this.before(); //Spring AOP【Before Advice】 this.fans.buyTicket(); //Joinpoint this.after(); //Spring AOP【After Advice】 } private void before() { System.out.println("准备去售票点购买球票..."); } private void after() { System.out.println("买到票啦,让我们一睹恒大夺冠吧..."); } }
4. Junit Test
package com.pattern.proxy.test; import org.junit.Test; import com.pattern.proxy.core.Fans; import com.pattern.proxy.core.IFans; import com.pattern.proxy.core.Wicket; public class TestFans { @Test public void testGetReport() { IFans fans = new Fans("swyma"); Wicket wicket = new Wicket(fans); wicket.buyTicket(); } }
四、代理模式扩展——动态代理
1. 定义:动态代理是在实现阶段不用关心谁,而在运行阶段才指定代理哪一个对象。Spring AOP核心也就是采用了动态代理机制。
2. 执行过程:【如下图所示】
3. 示例【模仿Spring AOP】
3.1 DynamicProxy
package com.pattern.proxy.core; public interface DynamicProxy<T> { T newProxyInstace(IFans fans); }
package com.pattern.proxy.core; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; /** * * @author yemaoan * * @param <T> */ public class FansDynamicProxy<T extends Object> implements DynamicProxy<T> { @Override public T newProxyInstace(IFans fans) { ClassLoader loader = fans.getClass().getClassLoader(); Class<?>[] interfaces = fans.getClass().getInterfaces(); InvocationHandler handler = new FansInvocatioHandler(fans); return (T) Proxy.newProxyInstance(loader, interfaces, handler); } }
3.2 InvocationHandler
package com.pattern.proxy.core; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import com.spring.aop.adivce.AdviceFactory; import com.spring.aop.adivce.AfterAdvice; import com.spring.aop.adivce.BeforeAdvice; /** * * @author yemaoan * */ public class FansInvocatioHandler implements InvocationHandler { private Object target = null; /** * * @param target 被代理的对象 */ public FansInvocatioHandler(Object target) { this.target = target; } @Override /** * @param proxy 被代理对象 * @param method 调用的方法 * @param args 方法调用时所需要的参数 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; if(method.getName().equals("buyTicket")) { AdviceFactory.getAdvice(BeforeAdvice.class).handle(); result = method.invoke(this.target, args); AdviceFactory.getAdvice(AfterAdvice.class).handle(); } return result; } }
3.3 模仿Spring AOP示例
package com.spring.aop.adivce; /** * Adivce * @author yemaoan * */ public interface IAdvice { void handle(); }
package com.spring.aop.adivce; /** * BeforeAdvice * @author yemaoan * */ public class BeforeAdvice implements IAdvice { @Override public void handle() { System.out.println("Spring AOP --> 前置通知"); } }
package com.spring.aop.adivce; /** * After Advice * @author yemaoan * */ public class AfterAdvice implements IAdvice { @Override public void handle() { System.out.println("Spring AOP --> 后置通知"); } }
package com.spring.aop.adivce; /** * Advice工厂类 * @author yemaoan * */ public class AdviceFactory { public static <T extends IAdvice> IAdvice getAdvice(Class<T> cls) { IAdvice advice = null; try { advice = (IAdvice) Class.forName(cls.getName()).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return advice; } }
3.4 测试代码
package com.pattern.proxy.test; import com.pattern.proxy.core.Fans; import com.pattern.proxy.core.FansDynamicProxy; import com.pattern.proxy.core.IFans; public class TestDynamic { public static void main(String[] args) { IFans fans = new Fans("summer"); IFans proxy = (IFans) new FansDynamicProxy().newProxyInstace(fans); proxy.buyTicket(); } }
五、总结
1. 本文是针对设计模式中的代理模式进行总结及梳理,并结合Spring AOP对Java JDK动态代理进行阐述。
六、题外话
经过三天三夜在颠簸的路途骑行,好友乃哥终于抵达厦门,以他的话来说就是各种心酸,各种坚持,确实挺不容易的。我暂且不说这种行为该不该提倡,但是这种坚持,这份毅力确实是值得我们尊敬。