【leetcode】Weekly Contest 92
emm,两天打的周赛,万年三题qaq,不过这次题目好像比上次的难一丢丢。
1.Transpose Matrix
把矩阵A[i][j]的每个元素改成B[j][i],超级超级大水题,然后wa了两发qaq。
1 public int[][] transpose(int[][] A) { 2 int row = A.length; 3 int clon = A[0].length; 4 int[][] res = new int[clon][row]; 5 for(int i = 0;i<row;i++){ 6 for(int j = 0; j<clon;j++){ 7 res[j][i] = A[i][j]; 8 } 9 } 10 return res; 11 }
2. Smallest Subtree with all the Deepest Nodes
一开始脑子抽了,没理解到底求的是什么,看了两三遍才反应过来求含最深节点的根节点(emm,这个题意有点难解释,看例子比较好)。
然后发现其实求每个节点的深度,如果其左孩子节点和右孩子节点最大深度是一样的就返回该节点(所求的根节点),如果不是,就进入深度大的那个节点继续判断即可。
我的代码就是先求每个节点的深度,然后再去找所求节点,怕递归太深超时就用hashmap记录了每个节点的深度,这样就不需要重复计算。
1 HashMap<TreeNode, Integer> map; 2 public TreeNode subtreeWithAllDeepest(TreeNode root) { 3 if(root == null){ 4 return null; 5 } 6 map = new HashMap<>(); 7 while(getDeepth(root.left) != getDeepth(root.right)){ 8 if(getDeepth(root.right) > getDeepth(root.left)){ 9 root = root.right; 10 }else { 11 root = root.left; 12 } 13 } 14 return root; 15 } 16 public int getDeepth(TreeNode root){ 17 if(root == null){ 18 return 0; 19 }else if(map.containsKey(root)){ 20 return map.get(root); 21 }else { 22 int deepth = Math.max(getDeepth(root.left), getDeepth(root.right))+1; 23 map.put(root, deepth); 24 return deepth; 25 } 26 }
3. Prime Palindrome
第三题题意很简单,就是给一个数字,求不小于该数字的最小回文素数,emm,第一反应就是暴力肯定不行,然后就陷入了沉思中。
那么肯定要先找出一种遍历回文数或素数的办法,因为素数遍历不用暴力法我不会qaq,找依次遍历回文数好像简单很多,note提示了答案肯定小于2*10^8,那么我们只需要最大遍历到四位数,再把后半部分补全即可,这样只需要遍历最大1w次,再判断每个是否是素数即可。
不过奇数位和偶数位判断好像很麻烦的样子,又想到了偶数位回文数肯定不可能是素数(除了11),因为会被11整除啦,比如abba,可以拆成1111*a+110*(b-a)。那么生成回文数的方法只需要写一个就好啦!
1 boolean isPrime(int n){//判断是否是素数 2 if(n == 1){ 3 return false; 4 } 5 if(n == 2){ 6 return true; 7 } 8 int k = (int) Math.sqrt(n); 9 for(int i = 2;i<=k;i++){ 10 if(n%i==0){ 11 return false; 12 } 13 } 14 return true; 15 } 16 17 int getPalindrome(int n){//生成奇数位回文数 18 int res=n/10; 19 while(n!=0) 20 { 21 res=res*10+n%10;//从低到高依次把该位数字添加到末尾 22 n/=10; 23 } 24 return res; 25 } 26 27 public int primePalindrome(int N) { 28 if(N<=11){//小于11直接遍历即可 29 for(int i = N;i<=11;i++){ 30 if(isPrime(i)){ 31 return i; 32 } 33 } 34 } 35 for(int i = 10;;i++){//比11大就遍历回文数 36 int palindrome = getPalindrome(i); 37 if(palindrome<N){ 38 continue; 39 } 40 if(isPrime(palindrome)){ 41 return palindrome; 42 } 43 } 44 }
4.Shortest Path to Get All Keys
其实,补完题发现不是很难qaq,没做出来一个原因是明明想着用bfs搜就好了,但是写的时候被一股神秘力量操控,一直在想用递归写bfs,等反应过来的时候时间不太够了,这种限时训练还是需要提高思维和编码能力。
bfs搜的时候把key也记录下来就好啦,不难不难(逃。
1 class Path { 2 int bitMask;//记录key的数量,111(7)表示有三把钥匙,abc 3 int x; 4 int y; 5 6 public Path(int x, int y, int bitMask) { 7 this.x = x; 8 this.y = y; 9 this.bitMask = bitMask; 10 } 11 12 @Override 13 public boolean equals(Object o) { 14 Path p = (Path) o; 15 return bitMask == p.bitMask && x == p.x && y == p.y; 16 } 17 18 @Override 19 public int hashCode() {//用set的时候改写一下hashcode和equals 20 return 1331 * bitMask + 31 * x + 101 * y; 21 } 22 } 23 24 private static final int[][] directions = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; 25 26 public int shortestPathAllKeys(String[] grid) { 27 char[][] board = new char[grid.length][grid[0].length()]; 28 int[] num = new int[1]; 29 Path start = new Path(0, 0, 0); 30 initialize(grid, start, num, board); 31 32 Queue<Path> queue = new LinkedList<>(); 33 Set<Path> visited = new HashSet<>(); 34 35 queue.offer(start); 36 visited.add(start); 37 int step = 0; 38 39 while(!queue.isEmpty()) { 40 int size = queue.size(); 41 42 for(int i = 0; i < size; i++) { 43 Path current = queue.poll(); 44 45 if(current.bitMask == (1 << num[0]) - 1) { 46 return step; 47 } 48 49 for(int[] direction : directions) { 50 int x = direction[0] + current.x; 51 int y = direction[1] + current.y; 52 int bitMask = current.bitMask; 53 54 if(x >= 0 && x < grid.length && y >= 0 && y < grid[0].length()) { 55 char ch = board[x][y]; 56 57 if(ch == '#') { 58 continue ; 59 } 60 else if(ch >= 'a' && ch <= 'f') { 61 bitMask |= 1 << (ch - 'a'); 62 } 63 else if(ch >= 'A' && ch <= 'F' && ((bitMask >> (ch - 'A')) & 1) == 0) { 64 continue ; 65 } 66 67 if(visited.add(new Path(x, y, bitMask))) { 68 queue.offer(new Path(x, y, bitMask)); 69 } 70 } 71 } 72 } 73 step++; 74 } 75 return -1; 76 77 } 78 79 private void initialize(String[] grid, Path start, int[] num, char[][] board) {//找到起点和key有多少个 80 for(int i = 0; i < grid.length; i++) { 81 for(int j = 0; j < grid[0].length(); j++) { 82 char ch = grid[i].charAt(j); 83 board[i][j] = ch; 84 85 if(ch == '@') { 86 start.x = i; 87 start.y = j; 88 } 89 90 if(ch >= 'a' && ch <= 'f') { 91 num[0]++; 92 } 93 } 94 } 95 }
代码很长,主要就是bfs以及用一个int记录key是否已经拿到了,注释也写啦,题目也说了key一定是前k个小写字母。