zoukankan      html  css  js  c++  java
  • 【leetcode】Weekly Contest 91

      leetcode周赛,早上起来发现没网,用热点意识模糊的a了三个水题。

    1.Lemonade Change

      简单模拟题,收到十元用五元钱找回,收到20元时优先用一张10一张5,如果10不够用3张5,如果没有就返回flase(贪心)。

     1     public boolean lemonadeChange(int[] bills) {
     2         int five = 0;
     3         int ten = 0;
     4         int twenty = 0;
     5         for (int i = 0; i < bills.length; i++) {
     6             if (bills[i] == 5) {
     7                 five++;
     8             } else if (bills[i] == 10) {
     9                 if (five > 0) {
    10                     five--;
    11                     ten++;
    12                 } else {
    13                     return false;
    14                 }
    15             } else if (bills[i] == 20) {
    16                 if (ten > 0 && five > 0) {
    17                     five--;
    18                     ten--;
    19                     twenty++;
    20                 } else if (five >= 3) {
    21                     five -= 3;
    22                     twenty++;
    23                 } else {
    24                     return false;
    25                 }
    26             }
    27         }
    28         return true;
    29     }

    2.All Nodes Distance K in Binary Tree

      找到target的位置,根据左(0)右(1)记录路径,再遍历(我用的是先根)一遍整颗树,每个点与target的距离是其“两点的深度和”减去“公共前缀的两倍”,判断是否与K相等即可。

     1     public List<Integer> distanceK(TreeNode root, TreeNode target, int K) {
     2         String t = findTarget(root,target,new String());
     3         return helper(root, K,t, new LinkedList<>(), new String());
     4     }
     5     public List<Integer> helper(TreeNode root,int k,String target,List<Integer> res,String s){//先根遍历
     6         if(root!=null){
     7             if(disK(target, s.toString(), k)){
     8                 res.add(root.val);
     9             }
    10             helper(root.left, k, target, res, s+"0");
    11             helper(root.right, k, target, res, s+"1");
    12         }
    13         return res;
    14     }
    15     public boolean disK(String s1,String s2,int k){//计算距离,距离=点1的深度+点2的深度-2倍的公共前缀深度
    16         if(s1.length()>s2.length()){
    17             String s = s1;
    18             s1 = s2;
    19             s2 = s;
    20         }
    21         int i;
    22         for(i = 0;i<s1.length();i++){
    23             if(s1.charAt(i) != s2.charAt(i)){
    24                 break;
    25             }
    26         }
    27         int dis = s1.length() + s2.length() - i*2;
    28         return dis == k;
    29     }
    30     public String findTarget(TreeNode root, TreeNode target,String res){//查找target节点,返回路径
    31         if(root == null){
    32             return "w";
    33         }
    34         if(root == target){
    35             return res;
    36         }
    37         String s = findTarget(root.left, target, res+"0");
    38         if(s.equals("w")){
    39             return findTarget(root.right, target, res+"1");
    40         }else {
    41             return s;
    42         }
    43     }

    3.Score After Flipping Matrix

      在一行中,每一列中的值比后面所有的列和都要大,因此把第一列的值置为1是第一目标,所以首先转换行用于把第一列的值全置为1,第二列到最后一列只需要根据每一列的1的个数是否大于行数的一半,如果大于就翻转列,反之则该列已经最大。

     1     public int matrixScore(int[][] A) {
     2         int score = 0;
     3         for (int i = 0; i < A.length; i++) {//把第一列的所有值都用行转换变为1
     4             if (A[i][0] == 0) {
     5                 swap(A, true, i);
     6             }
     7             score += Math.pow(2, A[i].length - 1);
     8         }
     9         for (int j = 1; j < A[0].length; j++) {
    10             int count = 0;//每一列1的个数
    11             for (int i = 0; i < A.length; i++) {
    12                 if (A[i][j] == 1) {
    13                     count++;
    14                 }
    15             }
    16             count = Math.max(count, A.length - count);//如果小于一半,就反转
    17             score += Math.pow(2, A[0].length - 1 - j) * count;
    18         }
    19         return score;
    20     }
    21 
    22     public void swap(int[][] A, boolean row, int num) {//用于转换行、列(后来发现转换列其实不需要,只需要计算每列的个数,如果反转就把个数反转即可,因为该列是否反转与后序无关联)
    23         if (row) {
    24             for (int i = 0; i < A[0].length; i++) {
    25                 A[num][i] ^= 1;
    26             }
    27         }
    28     }

    4.Shortest Subarray with Sum at Least K

      感觉A.length<=50000是最大的难点,当时没做出来,补题学到了一种很厉害的思路。首先用P[i]数组记录数组中第0个元素到第i个元素的和,因此P[y]-p[x]就是从位置x到y的和。

      然后,用一个双端队列,扫描一遍p数组,使队列保持递增(因为对于i<j,p[i]>p[j],则最小的距离肯定不是后面某个位置的值到i的和,而是到j的和,因此需要保持队列递增)。

      扫描每个点(比如i)的时候,用i与队列中首位的值配对,如果到队列首位位置的和比K大,则可以把队列首位的值remove掉,因为对于j>i来说,后面的所有符合条件的位置离队列首位记录的位置更远。

      可能听描述有点抽象,看代码就好啦!

     1     public int shortestSubarray(int[] A, int K) {
     2         int[] P = new int[A.length + 1];
     3         int res = Integer.MAX_VALUE;
     4         for (int i = 0; i < A.length; i++) {
     5             P[i + 1] = P[i] + A[i];
     6         }
     7         Deque<Integer> deque = new LinkedList<>();// 下面保证单调递增队列
     8         for (int i = 0; i < A.length + 1; i++) {
     9             while (!deque.isEmpty() && P[i] <= P[deque.getLast()]) {// 如果x1<y2
    10                                                                     // 且p[y2]<p[x1]则把x1抛弃
    11                 deque.removeLast();
    12             }
    13             while (!deque.isEmpty() && P[i] >= P[deque.getFirst()] + K) {// 从前找满足的位置
    14                 res = Math.min(res, i - deque.removeFirst());// 如果满足就把队列中的那个点去掉,因为i之后的点-队列中的点位置肯定比当前点大
    15             }
    16             deque.addLast(i);
    17         }
    18         return res == Integer.MAX_VALUE ? -1 : res;
    19     }

      oN的时间复杂度和空间复杂度,正好利用了区间和大于k这个条件(我才不会说我一开始看错题在思考怎么判断等于k)。很妙!

  • 相关阅读:
    三角形的最大周长
    Java 虚拟机运行时数据区详解
    四数相加 II
    Java 注解详解
    四因数
    【论文笔记+复现踩坑】End-to-end Recovery of Human Shape and Pose(CVPR 2018)
    假如 Web 当初不支持动态化
    保姆级干货分享
    C# ±180的值转成0-360
    C# 校验算法小结
  • 原文地址:https://www.cnblogs.com/zzzdp/p/9251907.html
Copyright © 2011-2022 走看看