本文旨在对于笔者日常比赛的整理复盘,如果有不足的地方,欢迎大家在评论区指出
句子 是一个单词列表,列表中的单词之间用单个空格隔开,且不存在前导或尾随空格。每个单词仅由大小写英文字母组成(不含标点符号)。
例如,"Hello World"
、"HELLO"
和 "hello world hello world"
都是句子。
给你一个句子 s 和一个整数 k ,请你将 s 截断 ,使截断后的句子仅含 前 k 个单词。返回 截断 s 后得到的句子。
句子的最大长度为500,所以这道题的解法就比较任意,题目中限制了句子中的每一个单词之间都是单个空格隔开,所以我们可以直接调用java
中的split方法来做,之后返回分割数组的前k个就好了
Java
class Solution {
public String truncateSentence(String s, int k) {
String[] arr = s.split(" ");
StringBuilder res = new StringBuilder();
for(int i=0; i<k; i++){
if(i != k-1) res.append(arr[i] + " ");
else res.append(arr[i]);
}
return res.toString();
}
}
给你用户在 LeetCode 的操作日志,和一个整数 k 。日志用一个二维整数数组 logs 表示,其中每个 logs[i] = [IDi, timei] 表示 ID 为 IDi 的用户在 timei 分钟时执行了某个操作。
多个用户 可以同时执行操作,单个用户可以在同一分钟内执行 多个操作 。
指定用户的 用户活跃分钟数(user active minutes,UAM) 定义为用户对 LeetCode 执行操作的 唯一分钟数 。 即使一分钟内执行多个操作,也只能按一分钟计数。
请你统计用户活跃分钟数的分布情况,统计结果是一个长度为 k 且 下标从 1 开始计数 的数组 answer ,对于每个 j(1 <= j <= k),answer[j] 表示 用户活跃分钟数 等于 j 的用户数。
返回上面描述的答案数组 answer 。
首先这道题的思路就是统计每一个 I D ID ID活跃的所有分钟数,并对每一个 I D ID ID对应的分钟集合进行去重,最后遍历所有的 I D ID ID,将该 I D ID ID对应的活跃次数累加到答案中,而 I D ID ID的范围有 1 0 9 10^9 109,所以我们想到使用map来做,对于分钟数的去重想到了set,这道题也就迎刃而解了
Java
class Solution {
public int[] findingUsersActiveMinutes(int[][] logs, int k) {
Map<Integer, Set<Integer>> map = new HashMap<>();
for(int[] log:logs){
Set<Integer> set = map.get(log[0]);
if(set == null){
set = new HashSet<Integer>();
map.put(log[0], set);
}
map.get(log[0]).add(log[1]);
}
int[] res = new int[k];
for(Integer id:map.keySet()){
res[map.get(id).size()-1] += 1;
}
return res;
}
}
给你两个正整数数组 nums1 和 nums2 ,数组的长度都是 n 。
数组 nums1 和 nums2 的 绝对差值和 定义为所有 |nums1[i] - nums2[i]|(0 <= i < n)的 总和(下标从 0 开始)。
你可以选用 nums1 中的 任意一个 元素来替换 nums1 中的 至多 一个元素,以 最小化 绝对差值和。
在替换数组 nums1 中最多一个元素 之后 ,返回最小绝对差值和。因为答案可能很大,所以需要对 109 + 7 取余 后返回。
|x| 定义为:
首先翻译一下题目大意,就是我们要最小化num1
与nums2
的绝对值差的和,我们只可以将nums1
中的一个元素换成nums1
中已经存在的元素,题目要求我们求出这个最小的绝对值差和,其中绝对值差和的定义为 ∑ i = 1 n ( ∣ n u m s 1 [ i ] − n u m s 2 [ i ] ∣ ) \sum_{i=1}^{n}(|nums1[i]-nums2[i]|) ∑i=1n(∣nums1[i]−nums2[i]∣),我们可以这样想,因为只可以换一个元素,所以我们必然要找到nums1
与nums2
中绝对值差值最大的一组值,之后将nums1
中的值替换为nums1
中与nums2
最接近的值,举一个题目中的例子:
nums1 = [1, 7, 5]
nums2 = [2, 3, 5]
1. 首先找到max(|nums1[i]-nums2[i]|) = nums1[1]-nums2[1] = |7-3| = 4(i=1)
2. 之后再nums1中找到与nums2[1]最接近的那个数字也就是1或者5,这里用1来举例,我们
将nums1中的7替换为1后:nums1 = [1, 1, 5],nums2 = [2, 3, 5],此时的绝对值
差和达到最小为3
Java
class Solution {
public int minAbsoluteSumDiff(int[] nums1, int[] nums2) {
int MOD = 1000000007;
int n = nums1.length;
// 求出二者的绝对值差的和
long absSum = 0;
for(int i=0; i<n; i++){
absSum += Math.abs(nums1[i]-nums2[i]);
}
// 找到绝对值差最大的那组下标
int maxIdx = 0;
for(int i=0; i<n; i++){
if(Math.abs(nums1[i]-nums2[i])>Math.abs(nums1[maxIdx]-nums2[maxIdx])){
maxIdx = i;
}
}
// 找到nums1中最接近nums2[maxIdx]的值
int tarIdx = 0;
for(int i=0; i<n; i++){
if(Math.abs(nums1[i]-nums2[maxIdx])<Math.abs(nums1[tarIdx]-nums2[maxIdx])){
tarIdx = i;
}
}
long dif = Math.abs(nums1[tarIdx]-nums2[maxIdx])-Math.abs(nums1[maxIdx]-nums2[maxIdx]);
return (int)((absSum+dif)%MOD);
}
}
给你一个由正整数组成的数组 nums 。
数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。
数组的一个 子序列 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。
计算并返回 nums 的所有 非空 子序列中 不同 最大公约数的 数目 。
这道题最难分析的是如何遍历出所有的情况,我们可以直接枚举最大公约数的所有情况,也就是从1枚举到数组中的最大值,这样也就枚举了答案的所有情况,之后我们使用g[y]
表示y的倍数的最大公约数,那么如果g[y] = y
也就是说数组中存在某个序列的最大公约数为y,此时答案加1,也就是最大公约数的种类多了一个,而对于g[y]
的求解就是枚举数组中所有数字x的约数y,不断的将g[y]
与x求最大公约数,最后进行上面的判断就好了
Java
class Solution {
private int gcd(int a, int b){
return b==0? a:gcd(b, a%b);
}
public int countDifferentSubsequenceGCDs(int[] nums) {
int n = nums.length;
// 找到数组中元素的最大值
int maxV = 0;
for(int i=0; i<n; i++) maxV = Math.max(maxV, nums[i]);
int[] g = new int[maxV+1]; // g[i]表示i的倍数的最大公约数
for(int x:nums){
for(int y=1; y<=x/y; y++){
if(x%y==0){
g[y]=gcd(g[y], x);
g[x/y]=gcd(g[x/y], x);
}
}
}
int res = 0;
for(int i=1; i<=maxV; i++){
if(g[i]==i) res += 1;
}
return res;
}
}