1.顺时针打印数组
eg: 1 2 3
4 5 6
7 8 9 打印出来,结果为1 2 3 6 9 8 7 4 5
解: 注意 * * (只有一行) 只有一列,行列不同等情况。
1 package offer; 2 3 /** 4 * 剑指offer p127 20题 5 * @author hasee 6 * 7 */ 8 public class PrintArr { 9 public static void print(int[][] arr){ 10 if(arr == null) 11 return; 12 int width = arr[0].length,high = arr.length; 13 int x=0,y=0; 14 while (width>0 && high>0) { 15 for (int i = 0; i < width; i++) 16 System.out.print(arr[x][y+i]+" "); 17 for (int i = 1; i < high; i++) 18 System.out.print(arr[x+i][y+width-1]+" "); 19 //错误! for循环前必须加上if判断 20 //当只有一行时,这里不该打印,因为width和行无关 21 if(high>1) for (int i = width-2; i >= 0; i--) 22 System.out.print(arr[x+high-1][y+i]+" "); 23 //当只有一列时,这里不该打印,因为high和列无关 24 if(width>1) for (int i = high-2; i >= 1; i--) 25 System.out.print(arr[x+i][y]+" "); 26 System.out.println(); 27 x++; 28 y++; 29 width-=2; 30 high-=2; 31 } 32 } 33 public static void main(String[] args) { 34 int[][] arr = new int[1][1]; 35 for (int i = 1; i <= arr.length; i++) { 36 for (int j = 1; j <= arr[0].length; j++) { 37 arr[i-1][j-1] = (i-1)*arr[0].length+j; 38 } 39 } 40 print(arr); 41 } 42 }
2.数轴上从左到右有n各点a[0], a[1], ……,a[n -1],给定一根长度为L的绳子,求绳子最多能覆盖其中的几个点
1 package number; 2 3 /** 4 * 数轴上从左到右有n各点a[0], a[1], ……,a[n -1],给定一根长度为L的绳子,求绳子最多能覆盖其中的几个点。 5 * @author hasee 6 * 7 */ 8 public class MaxTimesOfL { 9 public static void main(String[] args) { 10 int[] arr = {-1, 0, 3, 9, 11, 13, 14, 25};//数轴上的点 11 System.out.println(mostCover(arr,5)); 12 } 13 /** 14 * 两个指针,一个front,一个rear,每次front-rear,比L小,看覆盖的点数。 15 * 保存覆盖点数的最大值,然后front++;比L大,rear++,每个数最多遍历2遍,复杂度O(N)。 16 * 对于这个算法,他给了一个形象的比喻: 17 * 就好像一条长度为L的蛇。头伸不过去的话,就把尾巴缩过来最多只需要走一次,就知道能覆盖几个点 18 * 参考自:http://blog.csdn.net/thebestdavid/article/details/12236687 19 * @param arr 20 * @param n 21 * @return 22 */ 23 public static int mostCover(int[] arr,int n){ 24 if (arr == null) 25 return -1; 26 //两个指针,指向头节点和尾节点,动态判断是否超过n来计算包含的点个数 27 //有点类似快速排序的双指针向前走 28 int head=0,rear=0; 29 int max=0; 30 while (rear<arr.length) { 31 if (arr[rear]-arr[head] > n) { 32 //此处错误,先前是rear-head+1,因为已经大于n了 所以不应该加一 33 max = max<rear-head ? rear-head : max; 34 head++; 35 }else 36 rear++; 37 } 38 return max; 39 } 40 41 }
3.给定一个有序数组a,长度为len,和一个数X,判断A数组里面是否存在两个数,他们的和为X,bool judge(int *a, int len, int x),存在返回true,不存在返回false
1 package nothing; 2 3 /** 4 * 给定一个有序数组a,长度为len,和一个数X,判断A数组里面是否存在两个数, 5 * 他们的和为X,bool judge(int *a, int len, int x),存在返回true,不存在返回false 6 * @author hasee 7 * 8 */ 9 public class Manacher { 10 public static void main(String[] args) { 11 int[] arr = {1,4,6,7,9,11,15}; 12 System.out.println(isHaveSum(arr,6)); 13 } 14 15 private static boolean isHaveSum(int[] arr, int sum) { 16 if(arr == null) 17 return false; 18 int head=0,tail=arr.length-1; //喜闻乐见的双指针,头尾,有点像二分查找 19 while(head<tail){ 20 if(arr[head]+arr[tail]<sum) 21 head++; 22 else if(arr[head]+arr[tail]>sum) 23 tail--; 24 else 25 return true; 26 } 27 return false; 28 } 29 30 }
4.发帖水王变体
随着Tango的发展,管理员发现,“超级水王”没有了。统计结果表明,有3个发帖很多的ID,他们的发帖数目都超过了帖子总数目N的1/4。你能从发帖ID列表中快速找出他们的ID吗?
参见:http://blog.csdn.net/whz_zb/article/details/7436045
分析:在这个题目中,有一个计算机科学中很普遍的思想,就是如何把一个问题转化为规模较小的若干个问题。分治、递推和贪心等都有这样的思想。在转化过程中,如果能保证小的问题跟原问题的解是一致的就成功了。这样,我们可以通过寻找这样的方式将小问题转化为更小的问题。如何将大问题拆成小问题,或者如何大规模的数据降成小规模,而不影响解呢?
题思路:其实想想,不同于三个数的剩下的数只占总数的1/4不到。。所以直接用3个数记录,不同于这3个数就集体都减一,最后留下的肯定是这3个数。