新年了,小虾米想踏踏实实地提高算法,看了最近的SRM495,试着做了几题
CarrotBoxesEasy
如果为了节省时间,可以写个最简实现,每次找一个符合条件的数减一,重复k次就好。但是实际练习,还是想能写个效率好些的,多省掉些循环,想法是每次找出最大和次大的数m1和m2,并统计m1有多少个dup,然后比较k和(m1-m2)*dup,如果K小,则最后位置就从这些m1中产生,如果k大,则k=k-(m1-m2)*dup,并将所有m1“削”为m2,继续下一次迭代,直到K小并找到最后位置。 public int theIndex(int[] carrots, int K) { int k = K; int m1, m2, dup, c=-1; while(c==-1) { m2 = m1 = dup = 0; for(int i=0; i<carrots.length; i++) { if(carrots[i]==m1) { dup++; continue; } if(carrots[i]>m1) { dup = 1; m2 = m1; m1 = carrots[i]; continue; } if(carrots[i]>m2) { m2 = carrots[i]; } } int delta = m1 - m2; if(delta*dup<k) { k -= delta*dup; for(int i=0; i<carrots.length; i++) if(carrots[i]==m1) carrots[i] -= delta; } else { int num = (k-1)%dup + 1; for(c=0; c<carrots.length; c++) if(carrots[c]==m1) { num--; if(num==0) break; } } } return c; }
ColorfulCards
从左向右找出第一个匹配的子串,然后再从右向左找出第一个匹配的子串,然后检查两个子串的各位,如果不同就为-1,相同就为该数。
public int[] theCards(int N, String colors) { this.cards = new int[colors.length()]; int lcards[] = new int[colors.length()]; int rcards[] = new int[colors.length()]; this.primes = this.getPrime(N); int pos=1; for(int i=0; i<colors.length(); i++) { boolean prime = colors.charAt(i)=='R'; while(primes[pos]!=prime) pos++; lcards[i] = pos++; } pos = N; for(int i=colors.length()-1; i>=0; i--) { boolean prime = colors.charAt(i)=='R'; while(this.primes[pos]!=prime) pos--; rcards[i] = pos--; } for(int i=0; i<cards.length; i++) this.cards[i] = (lcards[i]==rcards[i] ? lcards[i] : -1); return this.cards; }
HexagonPuzzle
通过分析发现其中有个规律:如果符合条件的六边形个数为n>3,则其将产生P(n,n-2)种排列情况【即n*(n-1)*...*3】,简单证明如下:如果n=3,则有3种排列;如果n=4,先固定第4个token,其余3个依然是3种排列,然后从3个token中任选一个与固定token置换,得到额外的3*P(3,1)种情况,总计P(3,1)+3*P(3,1)=P(4,2);如果n=5,类似的固定第5个token,得到P(4,2),再置换得到新的4*P(4,2)种情况,总计得P(4,2)+4*P(4,2)=P(5,3);类推得P(n,n-2)。然后问题变成找出图中各个符合条件的各个连通图,计算其排列情况数,根据排列组合的乘法原理,将它们相乘并对1000000007取模即得结果。 int dc[] = new int[]{-1, -1, 0, 1, 1, 0}; int dr[] = new int[]{-1, 0, 1, 1, 0, -1}; int map[][]; int MOD = 1000000007; int count = 0; boolean visit[][]; public int theCount(String[] board) { map = new int[board.length][board.length]; for(int i=0; i<board.length; i++) { Arrays.fill(map[i], -1); for(int j=0; j<board[i].length(); j++) if(board[i].charAt(j)=='.') map[i][j] = 0; } long ans = 1; visit = new boolean[map.length][map.length]; for(int r=0; r<map.length; r++) for(int c=0; c<map.length; c++) if(!visit[r][c]) { count = 0; visit(r, c); while(count>2) { ans *= count--; ans %= MOD; } } return (int)ans; } public void visit(int r, int c) { visit[r][c] = true; if(at(r,c)!=0) return; boolean acceptable = false; for(int i=0; i<dc.length; i++) { int r1 = r+dr[i]; int c1 = c+dc[i]; int r2 = r+dr[(i+1)%dr.length]; int c2 = c+dc[(i+1)%dc.length]; if(at(r1,c1)==0&&at(r2,c2)==0) { if(!visit[r1][c1]) visit(r1,c1); acceptable = true; } } if(acceptable) count++; } public int at(int r, int c) { if(r<0||r>=map.length||c<0||c>=map.length) return -1; return map[r][c]; }
DIV1中的两个高分题,还没有想明白,也许要去看网上高手们的解题报告了。继续努力,恩。