Leetcode - 第263场周赛

这次做出来了三题,不过前面两题都有一次错误提交,以后还是要仔细把题目看清楚🧐。
https://leetcode-cn.com/contest/weekly-contest-261/

1.检查句子中的数字是否递增

题目描述

句子是由若干token组成的一个列表token间用单个空格分隔,句子没有前导或尾随空格。每个token要么是一个由数字0-9组成的不含前导零的正整数,要么是一个由小写英文字母组成的单词 。
示例,”a puppy has 2 eyes 4 legs”是一个由7个token组成的句子:”2” 和 “4”是数字,其他像”puppy”这样的tokens属于单词。
给你一个表示句子的字符串s,你需要检查s中的全部数字是否从左到右严格递增(即,除了最后一个数字,s中的每个数字都严格小于它右侧的数字)。
如果满足题目要求,返回 true ,否则,返回 false 。

示例 1:

输入:s = “1 box has 3 blue 4 red 6 green and 12 yellow marbles”
输出:true
解释:句子中的数字是:1, 3, 4, 6, 12 。
这些数字是按从左到右严格递增的 1 < 3 < 4 < 6 < 12 。

示例 2:
输入:s = “hello world 5 x 5”
输出:false
解释:句子中的数字是:5, 5 。这些数字不是严格递增的。

示例 3:
输入:s = “sunset is at 7 51 pm overnight lows will be in the low 50 and 60 s”
输出:false
解释:s 中的数字是:7, 51, 50, 60 。这些数字不是严格递增的。

示例 4:
输入:s = “4 5 11 26”
输出:true
解释:s 中的数字是:4, 5, 11, 26 。
这些数字是按从左到右严格递增的:4 < 5 < 11 < 26 。

提示:

3 <= s.length <= 200
s 由小写英文字母、空格和数字 0 到 9 组成(包含 0 和 9)
s 中数字 token 的数目在 2 和 100 之间(包含 2 和 100)
s 中的 token 之间由单个空格分隔
s 中至少有 两个 数字
s 中的每个数字都是一个 小于 100 的 正 数,且不含前导零
s 不含前导或尾随空格

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/check-if-numbers-are-ascending-in-a-sentence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

使用istringstream来分割带空格的字符串,在写一个判断字符串是否是数字的函数,最后用stoi将字符串转换成数字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public:
bool isNum(string s){
for (char c : s){
if (c - '0' > 9 || c - '0' < 0)
return false;
}
return true;
}
bool areNumbersAscending(string s) {
istringstream iss(s);
string tmp;
int last = 0, curr = 0;
while (iss >> tmp){
if (isNum(tmp)){
curr = stoi(tmp);
if (curr <= last)
return false;
last = curr;
}
}
return true;
}
};

2.建议银行系统

题目描述

你的任务是为一个很受欢迎的银行设计一款程序,以自动化执行所有传入的交易(转账,存款和取款)。银行共有 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 。

示例:

输入:
[“Bank”, “withdraw”, “transfer”, “deposit”, “transfer”, “withdraw”]
[[[10, 100, 20, 50, 30]], [3, 10], [5, 1, 20], [5, 20], [3, 4, 15], [10, 50]]
输出:
[null, true, true, true, false, false]

解释:
Bank bank = new Bank([10, 100, 20, 50, 30]);
bank.withdraw(3, 10); // 返回 true ,账户 3 的余额是 $20 ,所以可以取款 $10 。
// 账户 3 余额为 $20 - $10 = $10 。
bank.transfer(5, 1, 20); // 返回 true ,账户 5 的余额是 $30 ,所以可以转账 $20 。
// 账户 5 的余额为 $30 - $20 = $10 ,账户 1 的余额为 $10 + $20 = $30 。
bank.deposit(5, 20); // 返回 true ,可以向账户 5 存款 $20 。
// 账户 5 的余额为 $10 + $20 = $30 。
bank.transfer(3, 4, 15); // 返回 false ,账户 3 的当前余额是 $10 。
// 所以无法转账 $15 。
bank.withdraw(10, 50); // 返回 false ,交易无效,因为账户 10 并不存在。

提示:

n == balance.length
1 <= n, account, account1, account2 <= 105
0 <= balance[i], money <= 1012
transfer, deposit, withdraw 三个函数,每个 最多调用 104 次

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/simple-bank-system
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

这题比较简单,但是要注意每个操作前都要坚持账户是否越界。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Bank {
private:
vector<long long> bal;
int n;
public:
Bank(vector<long long>& balance) {
bal = balance;
n = bal.size();
}


bool transfer(int account1, int account2, long long money) {
if (account1 > n || account2 > n)
return false;
if (bal[account1 - 1] < money)
return false;
else{
bal[account1 - 1] -= money;
bal[account2 - 1] += money;
return true;
}
}

bool deposit(int account, long long money) {
if (account > n)
return false;
bal[account - 1] += money;
return true;
}

bool withdraw(int account, long long money) {
if (account > n)
return false;
if (bal[account - 1] < money)
return false;
else{
bal[account - 1] -= money;
return true;
}
}
};

/**
* Your Bank object will be instantiated and called as such:
* Bank* obj = new Bank(balance);
* bool param_1 = obj->transfer(account1,account2,money);
* bool param_2 = obj->deposit(account,money);
* bool param_3 = obj->withdraw(account,money);
*/

3.统计按位或能得到最大值的子集数目

给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。
如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集 。如果选中的元素下标位置不一样,则认为两个子集 不同 。
对数组 a 执行 按位或 ,结果等于 a[0] OR a[1] OR … OR a[a.length - 1](下标从 0 开始)。

示例 1:
输入:nums = [3,1]
输出:2
解释:子集按位或能得到的最大值是 3 。有 2 个子集按位或可以得到 3 :

  • [3]
  • [3,1]

示例 2:
输入:nums = [2,2,2]
输出:7
解释:[2,2,2] 的所有非空子集的按位或都可以得到 2 。总共有 23 - 1 = 7 个子集。

示例 3:
输入:nums = [3,2,1,5]
输出:6
解释:子集按位或可能的最大值是 7 。有 6 个子集按位或可以得到 7 :

  • [3,5]
  • [3,1,5]
  • [3,2,5]
  • [3,2,1,5]
  • [2,5]
  • [2,1,5]

提示:
1 <= nums.length <= 16
1 <= nums[i] <= 105

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-number-of-maximum-bitwise-or-subsets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

求按位或得到最大值的子集个数。子集问题当然用回溯法啦,注意回溯函数要加一个上一个元素是否选了的参数,防止上一个元素没选的时候重复计数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution{ 
public:
int maxNum, maxCount;

void backtrack(vector<int>& nums, int cur, int i, bool lastChose){
if (cur == maxNum && lastChose)
maxCount++;
if (cur > maxNum){
maxCount = 1;
maxNum = cur;
}
if (i == nums.size())
return;
int orr = cur | nums[i];
backtrack(nums, orr, i+1, true);
backtrack(nums, cur, i+1, false);
}

int countMaxOrSubsets(vector<int>& nums) {
maxNum = 0;
maxCount = 0;
backtrack(nums, 0, 0, true);
return maxCount;
}
};