zoukankan      html  css  js  c++  java
  • [Leetcode Weekly Contest]263

    链接:LeetCode

    [Leetcode]2042. 检查句子中的数字是否递增

    句子是由若干 token 组成的一个列表,token 间用 单个 空格分隔,句子没有前导或尾随空格。每个 token 要么是一个由数字 0-9 组成的不含前导零的 正整数 ,要么是一个由小写英文字母组成的 单词 。

    示例,"a puppy has 2 eyes 4 legs" 是一个由 7 个 token 组成的句子:"2" 和 "4" 是数字,其他像 "puppy" 这样的 tokens 属于单词。
    给你一个表示句子的字符串 s ,你需要检查 s 中的 全部 数字是否从左到右严格递增(即,除了最后一个数字,s 中的 每个 数字都严格小于它 右侧 的数字)。

    如果满足题目要求,返回 true ,否则,返回 false 。

    遍历即可。

    class Solution {
        public boolean areNumbersAscending(String s) {
            int last = -1;
            for(var ss:s.split(" ")) {
                if(isDigit(ss)) {
                    int cur = Integer.parseInt(ss);
                    if(cur <= last) return false;
                    last = cur;
                }
            }
            return true;
        }
    
        public boolean isDigit(String s) {
            for(var ch:s.toCharArray()) {
                if (!Character.isDigit(ch)) return false;
            }
            return true;
        }
    }
    

    [Leetcode]2043. 简易银行系统

    你的任务是为一个很受欢迎的银行设计一款程序,以自动化执行所有传入的交易(转账,存款和取款)。银行共有 n 个账户,编号从 1 到 n 。每个账号的初始余额存储在一个下标从 0 开始的整数数组 balance 中,其中第 (i + 1) 个账户的初始余额是 balance[i] 。

    请你执行所有 有效的 交易。如果满足下面全部条件,则交易 有效 :

    指定的账户数量在 1 和 n 之间,且
    取款或者转账需要的钱的总数 小于或者等于 账户余额。
    实现 Bank 类:

    Bank(long[] balance) 使用下标从 0 开始的整数数组 balance 初始化该对象。
    boolean transfer(int account1, int account2, long money) 从编号为 account1 的账户向编号为 account2 的账户转帐 money 美元。如果交易成功,返回 true ,否则,返回 false 。
    boolean deposit(int account, long money) 向编号为 account 的账户存款 money 美元。如果交易成功,返回 true ;否则,返回 false 。
    boolean withdraw(int account, long money) 从编号为 account 的账户取款 money 美元。如果交易成功,返回 true ;否则,返回 false 。

    按照题意实现即可,注意判断账户是否有效。

    class Bank {
        private long[] balance;
        private final int N;
        public Bank(long[] balance) {
            this.balance = balance;
            this.N = balance.length;
        }
    
        public boolean isAvailableAccount(int account) {
            return account >=1 && account <= this.N;
        }
    
        public boolean hasEnoughMoney(int account, long money) {
            return this.balance[account-1] >= money;
        }
    
        public boolean transfer(int account1, int account2, long money) {
            if(!isAvailableAccount(account1) || !isAvailableAccount(account2)) return false;
            if(!hasEnoughMoney(account1,money)) return false;
            this.balance[account1-1] -= money;
            this.balance[account2-1] += money;
            return true;
        }
    
        public boolean deposit(int account, long money) {
            if(!isAvailableAccount(account)) return false;
            this.balance[account-1] += money;
            return true;
        }
    
        public boolean withdraw(int account, long money) {
            if(!isAvailableAccount(account) || !hasEnoughMoney(account,money)) return false;
            this.balance[account-1] -= money;
            return true;
        }
    }
    
    /**
     * Your Bank object will be instantiated and called as such:
     * Bank obj = new Bank(balance);
     * boolean param_1 = obj.transfer(account1,account2,money);
     * boolean param_2 = obj.deposit(account,money);
     * boolean param_3 = obj.withdraw(account,money);
     */
    

    [Leetcode]2044. 统计按位或能得到最大值的子集数目

    给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。

    如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。

    对数组 a 执行 按位或 ,结果等于 a[0] OR a[1] OR ... OR a[a.length - 1](下标从 0 开始)。

    这道题中要找的是 子序列 中,包含几个可行解,很容易的可以想到 dfs:
    观察数据规模, 1 ≤ n ≤ 16,最暴力的 dfs 也才 2^16 ,可以接受还需要找到 按位或 的 最大值 。观察到所有的数字都是正数,则显然有 (a | b ≥ max(a, b)),即一个正数A按位或另一个正数B,得到的结果C一定是不减的。
    由此我们可以知道:我们要寻找的最大值 = 所有数字按位或结果。
    另外,可用在回溯过程中剪枝,假设我们找到了一个组合,其位或结果为最大值,则接下来剩余的m个数都不需要再搜索了,因为我们想到这m个数加或者不加,其结果不变,则直接返回2**m即可。

    class Solution {
        private int mx = 0;
        private int count = 0;
        public int countMaxOrSubsets(int[] nums) {
            for(var num:nums) {
                mx = mx | num;
            }
            dfs(nums,-1,0);
            return count;
        }
    
        public void dfs(int[] nums,int startIndex,int cur) {
            int n = nums.length;
            if(cur == mx) {
                // count += Math.pow(2, n-startIndex-1);
                count += 1<<(n-startIndex-1);
                return;
            }
            for(int i=startIndex+1;i<nums.length;++i) {
                dfs(nums,i,cur|nums[i]);
            }
        }
    }
    

    [Leetcode]2045. 到达目的地的第二短时间

    城市用一个 双向连通 图表示,图中有 n 个节点,从 1 到 n 编号(包含 1 和 n)。图中的边用一个二维整数数组 edges 表示,其中每个 edges[i] = [ui, vi] 表示一条节点 ui 和节点 vi 之间的双向连通边。每组节点对由 最多一条 边连通,顶点不存在连接到自身的边。穿过任意一条边的时间是 time 分钟。

    每个节点都有一个交通信号灯,每 change 分钟改变一次,从绿色变成红色,再由红色变成绿色,循环往复。所有信号灯都 同时 改变。你可以在 任何时候 进入某个节点,但是 只能 在节点 信号灯是绿色时 才能离开。如果信号灯是 绿色 ,你 不能 在节点等待,必须离开。

    第二小的值 是 严格大于 最小值的所有值中最小的值。

    例如,[2, 3, 4] 中第二小的值是 3 ,而 [2, 2, 4] 中第二小的值是 4 。
    给你 n、edges、time 和 change ,返回从节点 1 到节点 n 需要的 第二短时间 。

    注意:

    你可以 任意次 穿过任意顶点,包括 1 和 n 。
    你可以假设在 启程时 ,所有信号灯刚刚变成 绿色 。

    BFS。由于 ( extit{time})( extit{change}) 是固定的,经过多少条边就知道花费了多少时间。因此这题本质上可以看成边权均为 1 的图,我们要求的就是 1 到 n 的严格次短路的长度,知道长度就知道花费的时间。

    class Solution {
    
        public int secondMinimum(int n, int[][] edges, int time, int change) {
            List<Integer>[] adj = new ArrayList[n];
            for(int i = 0; i < n; ++i) adj[i] = new ArrayList<>();
            int[] dis = new int[n];
            boolean[] sec = new boolean[n];
            for(int[] edge : edges) {
                int v = edge[0] - 1, u = edge[1] - 1;
                adj[v].add(u);adj[u].add(v);
            }
            for(int i = 1; i < n; ++i) dis[i] = Integer.MAX_VALUE;
            Queue<Integer> q = new LinkedList<>();
            q.offer(0);
            while(!q.isEmpty()) {
                int head = q.poll();
                for(int u : adj[head]) {
                    if(dis[u] > dis[head] + 1) {
                        dis[u] = dis[head] + 1;
                        q.offer(u);
                    }
                    else if(dis[u] == dis[head] || (sec[head] && dis[u] == dis[head] + 1)){
                        if(!sec[u]) q.offer(u);
                        sec[u] = true;
                    }
                }
            }
            int path = dis[n - 1] + (sec[n - 1] ? 1 : 2);
            return lenToTime(path, time, change);
        }
    
        private int lenToTime(int len, int time, int change) {
            int cur = 0, tol = 0;
            for(int i = 0; i < len; i++) {
                tol += time;
                if(i == len - 1) break;
                int period = tol / change;
                if((period & 1) == 1) {
                    tol += (period + 1) * change - tol;
                }
            }
            return tol;
        }
    }
    
    

    Leetcode

  • 相关阅读:
    [POJ 2096]Collecting Bugs
    [SPOJ 375]Query on a tree
    [BZOJ 4423][AMPPZ2013]Bytehattan
    [BZOJ 2038][2009国家集训队]小Z的袜子(hose)
    [SDOI 2017]数字表格
    [NOI 2010]能量采集
    [HNOI 2014]世界树
    [HNOI 2016]序列
    [HNOI 2016]大数
    [HEOI 2014]大工程
  • 原文地址:https://www.cnblogs.com/hellojamest/p/15435359.html
Copyright © 2011-2022 走看看