1 笨笨的孩子慢慢学stay hungry stay foolish 2 学习,思考,实践,改变

0%

leecode168周赛

leecode5291统计位数为偶数的数字

给你一个整数数组 nums,请你返回其中位数为 偶数 的数字的个数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
输入:nums = [12,345,2,6,7896]
输出:2
解释:
12 是 2 位数字(位数为偶数) 
345 是 3 位数字(位数为奇数)  
2 是 1 位数字(位数为奇数) 
6 是 1 位数字 位数为奇数) 
7896 是 4 位数字(位数为偶数)  
因此只有 12 和 7896 是位数为偶数的数字

输入:nums = [555,901,482,1771]
输出:1
解释:
只有 1771 是位数为偶数的数字。

1 <= nums.length <= 500
1 <= nums[i] <= 10^5

思路1:c++,位数是除以10,而判断是否偶数是对2取余判断是否为0。

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
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;

int findNumbers(vector<int>& nums) {
int res=0;
for(auto num: nums){
int weishu=1;
while(num / 10 > 0){
weishu ++;
num /= 10;
}
cout<<weishu<<endl;
if(weishu % 2 == 0){
res ++;
}
}
return res;
}

int main(){
vector<int> test1 = {12,345,2,6,7896};
int res = findNumbers(test1);
cout<<res<<endl;
return 0;
}

思路2:Python,遍历nums里的数字。将数字转换为string。判断string的长度对2取余是否为0,是0则取1,否则取0(表示位数不是偶数)。再将是偶数的数字求和 sum。

1
2
def findNumbers(nums: List[int]) -> int:
return sum(1 if len(str(x)) % 2 == 0 else 0 for x in nums)

leecode5292划分数组为连续数字的集合

给你一个整数数组 nums 和一个正整数 k,请你判断是否可以把这个数组划分成一些由 k 个连续数字组成的集合。
如果可以,请返回 True;否则,返回 False。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
实例1
输入:nums = [1,2,3,3,4,4,5,6], k = 4
输出:true
解释:数组可以分成 [1,2,3,4] 和 [3,4,5,6]。

示例2
输入:nums = [3,2,1,2,3,4,3,4,5,9,10,11], k = 3
输出:true
解释:数组可以分成 [1,2,3] , [2,3,4] , [3,4,5] 和 [9,10,11]。

示例3
输入:nums = [3,3,2,2,1,1], k = 3
输出:true

示例4
输入:nums = [1,2,3,4], k = 3
输出:false
解释:数组不能分成几个大小为 3 的子数组。

1 <= nums.length <= 10^5
1 <= nums[i] <= 10^9
1 <= k <= nums.length

思路1:简单基本思路,将nums里的最小取出来,然后每次取[min,min+k]的值,不断从原nums里去除掉。如果可以这样去空原nums则返回true,否则只要有值不在nums里,则返回false。(但这个方法的时间复杂度太高$O(kn^2)$)

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
# -*- coding:utf-8 -*-
def isPossibleDivide(nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
if (len(nums) % k != 0):
return False

while (len(nums) != 0):
# each list
for x in range(min(nums), min(nums)+k):
if x in nums:
nums.remove(x)
else:
return False
return True


if __name__ == '__main__':
nums = [3,2,1,2,3,4,3,4,5,9,10,11]
k = 3
res = isPossibleDivide(nums,k)
print(res)

进一步,用hash优化查找x in nums。(c++中的map是平衡二叉树),排序时间复杂度$O(nlogn)$,

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
#include <stdio.h>
#include <iostream>
#include <vector>
#include <map>
using namespace std;

bool isPossibleDivide(vector<int>& nums, int k) {
if (nums.size() % k != 0) {
return false;
}

sort(nums.begin(), nums.end());
map<int,int> hash;
for(auto num:nums) hash[num]++;
int groups = nums.size() / k;
//group nums
for (int i=0; i<groups; i++) {
int min_index = 0;
while (hash[nums[min_index]] == 0) {
min_index++;
}
//if min~min+k is not in nums, false
int start = nums[min_index];
for (int j=start; j<start+k; j++) {
if (hash[j] == 0) {
return false;
}
else hash[j]--;
}
}
return true;
}

int main(){
vector<int> test2 = {1,2,3,2,3,3,4,4,5,9,10,11};
int res2 = isPossibleDivide(test2,3);
cout<<res2<<endl;
return 0;
}

思路3。新学习了multiset。避免了while这一段找min_index(见上),直接在multiset里查找并去掉,时间要短一点点,但空间用的要更多(因为multiset允许存储重复元素)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool isPossibleDivide2(vector<int>& nums, int k) {
if (nums.size() % k != 0) {
return false;
}
multiset<int> s;
for(auto num:nums) s.insert(num);
//multiset<int> s(a.begin(), a.end());
for (int i=0; i<nums.size() / k; i++) {
int min = *s.begin();
for (int j=min; j<min+k; j++) {
if (s.find(j) == s.end()) {
return false;
}
s.erase(s.find(j));
}
}
return true;
}

Reference

1, https://leetcode-cn.com/problems/find-numbers-with-even-number-of-digits

2, https://leetcode-cn.com/problems/divide-array-in-sets-of-k-consecutive-numbers

3,https://leetcode-cn.com/contest/weekly-contest-168/