【leetcode】Weekly Contest 94
题目不难,被第二题卡了半个多小时QAQ,另一个就是以后能用Hashmap和Hashset的绝不遍历。
1. Leaf-Similar Trees
dfs、层次遍历把叶子节点遍历然后对比即可,只要是先遍历左节点后遍历右节点就行。
1 class Solution { 2 public boolean leafSimilar(TreeNode root1, TreeNode root2) { 3 ArrayList<Integer> res1 = new ArrayList<>(); 4 ArrayList<Integer> res2 = new ArrayList<>(); 5 getLeaf(root1, res1); 6 getLeaf(root2, res2); 7 boolean equal = true; 8 if(res1.size() == res2.size()){//叶子节点数量都不一样就不可能一样 9 int i; 10 for(i = 0;i<res1.size();i++){ 11 if(res1.get(i) != res2.get(i)){ 12 equal = false; 13 break; 14 } 15 } 16 } 17 return equal; 18 } 19 20 void getLeaf(TreeNode root,ArrayList<Integer> res){//先序遍历获得所有叶子节点 21 if(root == null){ 22 return ; 23 } 24 if(root.left == null && root.right ==null){ 25 res.add(root.val); 26 } 27 getLeaf(root.left, res); 28 getLeaf(root.right, res); 29 } 30 }
874. Walking Robot Simulation
被这题卡了好久,一开始想写的是判断起始点到末尾点中间是否有障碍物,前进的终点位置是最近的那个障碍物前一个位置,后来意识到前进的距离最多是9,直接一个点一个点判断就好了,这样可以直接用Hashset找是否有那个点。
1 public static int robotSim(int[] commands, int[][] obstacles) { 2 int[][] dir = {{0,1},{1,0},{0,-1},{-1,0}}; 3 int nowdir = 0;//当前方向 4 int x = 0,y = 0;//记录当前位置 5 int max = 0; 6 int nx,ny;//下一个位置 7 Set<Long> obstacleSet = new HashSet(); 8 for (int[] obstacle: obstacles) { 9 long ox = (long) obstacle[0]; 10 long oy = (long) obstacle[1]; 11 obstacleSet.add((ox << 16) + oy);//前16位记录x的位置,后16位记录y的位置 12 } 13 14 for(int i = 0;i<commands.length;i++){ 15 if(commands[i] == -1){ 16 nowdir = (nowdir+1)%4; 17 }else if (commands[i] == -2) { 18 nowdir = (nowdir-1+4)%4; 19 }else { 20 for (int k = 0; k < commands[i]; ++k) { 21 nx = x + dir[nowdir][0]; 22 ny = y + dir[nowdir][1]; 23 long code = (((long) nx) << 16) + ((long) ny ); 24 if (!obstacleSet.contains(code)) { 25 x = nx; 26 y = ny; 27 max = Math.max(max, x*x + y*y); 28 } 29 } 30 } 31 } 32 return max; 33 }
875. Koko Eating Bananas
第三题不难,二分查找K的值(1-10^9),每次判断时间是否小于H即可,时间复杂度o(10^4*log10^9)。
1 class Solution { 2 public int minEatingSpeed(int[] piles, int H) { 3 int up = 0; 4 for (int i : piles) {//记录最大的数量,每小时吃的肯定不需要大于这个数量 5 up = Math.max(up, i); 6 } 7 return find(piles,H,1,up); 8 } 9 10 static int find(int[] piles, int H,int min,int max){//二分搜索 11 if(min == max){ 12 return min; 13 }else{ 14 int mid = (min+max)/2; 15 // System.out.println(min +" "+ max+" "+mid); 16 if(eatAll(piles, H, mid)){//能吃完,就尝试更小的(当然mid也可能是所求值) 17 return find(piles, H, min, mid); 18 }else {//吃不完,就每小时吃多点 19 return find(piles, H, mid+1, max); 20 } 21 } 22 } 23 24 static boolean eatAll(int[] piles,int H,int K){ 25 int need = 0; 26 for (int i : piles) { 27 need+=(i/K)+((i%K)==0?0:1); 28 } 29 return need<=H; 30 } 31 }
873. Length of Longest Fibonacci Subsequence
这题思路对了,用二位数组dp[i][j]记录以A[i]为倒数第二个点,A[j]为最后一个点的最大斐波那契数列长度,o(n^2)遍历这个二维数组填充数据,再遍历一次取得结果即可。
1 class Solution { 2 public int lenLongestFibSubseq(int[] A) { 3 int dp[][] = new int[A.length][A.length]; 4 HashMap<Integer, Integer> index = new HashMap<>();//记录数组值的下标 5 for(int i = 0;i<A.length;i++){ 6 index.put(A[i], i); 7 } 8 for(int i = 2;i<A.length;i++){ 9 for(int j = 0;j<i;j++){ 10 Integer k = index.get(A[i] - A[j]);//查看是否存在需要的值 11 if(k!=null && k<j){ 12 dp[i][j] = Math.max(dp[i][j], dp[j][k]+1); 13 } 14 } 15 } 16 int res = 0; 17 for (int[] is : dp) { 18 for (int i : is) { 19 res = Math.max(res, i); 20 } 21 } 22 return res==0?0:res+2; 23 } 24 }
一开始没用Hashmap记录,因此需要第三个循环搜索是否存在需要的值,然后就tle惹,用Hashmap降了一个时间复杂度。
本次题目都不是特别难,不过还是仰望那些20分钟AK的大佬(我看题目的时间可能都不止20min QAQ)。