共有 n 位员工,每位员工都有一个从 0 到 n - 1 的唯一 id 。
给你一个二维整数数组 logs ,其中 logs[i] = [idi, leaveTimei] :
返回处理用时最长的那个任务的员工的 id 。如果存在两个或多个员工同时满足,则返回几人中 最小 的 id 。
思路
使用枚举法将每一位员工的用时计算出来
public class Sulotion2432 {
public int hardestWorker(int n, int[][] logs) {
if (n == 1) {
return 0;
}
int res = logs[0][1];
int flag = logs[0][0];
for (int i = 1; i < logs.length; i++) {
int usid = logs[i][0];
int temp = logs[i][1] - logs[i - 1][1];
if (temp > res || (temp == res && usid < flag)) {
res = temp;
flag = logs[i][0];
}
}
return flag;
}
}
思路
使用计数的方式,创建一个数组,判断当前字符出现的次数以及当前字符的顺序(遍历后面字符的时候会判断前一个是否为0,以此来形成一个有顺序的鸣叫),如果当前字符合理,就将当前的数组计数加一,将前一个数组计数减一。因此当最终遍历完成如果有效的话所有计数应当全部为0;要判断同时有几只青蛙,只需要判断在数组中同时出现的最大数目。
public class Sulotion1419 {
public static int minNumberOfFrogs(String croakOfFrogs) {
if (croakOfFrogs.length() % 5 != 0) {
return -1;
}
int[] count = new int[4];
int res = 0;
for (int i = 0; i < croakOfFrogs.length(); i++) {
char c = croakOfFrogs.charAt(i);
if (c != 'c' & c != 'r' & c != 'o' & c != 'a' & c != 'k'){
return -1;
}
switch (c){
case 'c': count[0]++; break;
case 'r': if(count[0]==0) return -1; count[0]--; count[1]++; break;
case 'o': if(count[1]==0) return -1; count[1]--; count[2]++; break;
case 'a': if(count[2]==0) return -1; count[2]--; count[3]++; break;
case 'k': if(count[3]==0) return -1; count[3]--; break;
}
// 判断同时有几只青蛙在叫
res = Math.max(res, count[0]+count[1]+count[2]+count[3]);
}
// 判断叫声是否完整
return count[0]+count[1]+count[2]+count[3] == 0 ? res : -1;
}
}
思路
使用双重for循环显然是可以直接实现的,但是那样的话时间复杂度是O(n^2)。
所以我们的思路是创建一个长度为61数组,用来记录当前索引数下的数字量,当一个数对60取余得到的数加上60减去这个数的值必定可以对60取余为0,所以只需记录遍历的数对60取余对应的数组的索引,然后将所有与之相加为60的数的数量记录下来。
public class Sulotion1010 {
public int numPairsDivisibleBy60(int[] time) {
int res = 0;
int[] count = new int[61];
for (int i = 0; i < time.length; i++) {
res += count[(60 - time[i] % 60) % 60];
count[time[i] % 60]++;
}
return res;
}
}
这个题优点难度,目前自己完全不能解决,等后续持续学习
这个题主要用到图的广度优先遍历
思路
时间一共由四个数组组成,将这四个数字分离出来进行单独判断
import java.util.ArrayList;
public class Sulotion2437 {
public int countTime(String time) {
int res = 1;
ArrayList<Integer> arrayList = new ArrayList();
String[] str = time.split("");
if (str[0].equals("?") && str[1].equals("?")) {
res *= 24;
} else {
if (str[0].equals("?")) {
if (Integer.parseInt(str[1]) < 4) {
res *= 3;
} else {
res *= 2;
}
}
if (str[1].equals("?")) {
if (Integer.parseInt(str[0]) == 2) {
res *= 4;
} else {
res *= 10;
}
}
}
if (str[3].equals("?")) {
res *= 6;
}
if (str[4].equals("?")) {
res *= 10;
}
return res;
}
}
给定正整数 k ,你需要找出可以被 k 整除的、仅包含数字 1 的最 小 正整数 n 的长度。
返回 n 的长度。如果不存在这样的 n ,就返回-1。
思路
要判断有多长的由1组成的数可以被k整除,两种思路
- 使用
1*10+1
对k
取余余数等于0,返回结果,如果开始循环,证明无解- 分析可知,当
k
能被2和5
整除时肯定无解,所以直接返回-1
,其他数字肯定有解,所以进行循环查找最短的值就行。
public class Sulotion1015 {
public int smallestRepunitDivByK(int k) {
if (k % 2 == 0 || k % 5 == 0) {
return -1;
}
int res = 1;
int temp = 1 % k;
while (temp != 0) {
temp = (temp * 10 + 1) % k;
res++;
}
return res;
}
}
思路
Java中提供数字转为二进制,直接判断此数字的二进制是否存在与这个二进制字符串
S
中
官方解法使用滑动窗口
public class Sulotion1016 {
public boolean queryString(String s, int n) {
for (int i = 0; i < n; i++) {
String str = Integer.toString(i, 2);
if(!s.contains(str)){
return false;
}
}
return true;
}
}
思路
这个题花费的挺长时间在优化上,首先这个题的意思是让你计算
数组的值
(前一个减去后一个绝对值的和),然后可以翻转一次子数组使其达到最大值,以下记录下当时的思路:
public class Sulotion1330 {
public static int maxValueAfterReverse(int[] nums) {
int res = shuck(nums);
int max = 0;
for (int i = 0; i < nums.length - 1; i++) {
max = Math.max(max, Math.abs(nums[0] - nums[i + 1]) - (Math.abs(nums[i] - nums[i + 1])));
max = Math.max(max, Math.abs(nums[i] - nums[nums.length - 1]) - (Math.abs(nums[i] - nums[i + 1])));
}
int max2 = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
for (int i = 0; i < nums.length - 1; i++) {
int x = nums[i], y = nums[i + 1];
max2 = Math.max(max2,Math.min(x, y));
min = Math.min(min, Math.max(x, y));
}
res = Math.max(res + max, res + 2 * (max2 - min));
return res;
}
public static int shuck(int[] nums) {
int res = 0;
for (int i = 1; i < nums.length; i++) {
res += Math.abs(nums[i - 1] - nums[i]);
}
return res;
}
}
给你一个 不包含 任何零的整数数组 nums ,找出自身与对应的负数都在数组中存在的最大正整数 k 。
返回正整数 k ,如果不存在这样的整数,返回 -1 。
public class Sulotion2441 {
public static int findMaxK(int[] nums) {
Arrays.sort(nums);
for (int i = 0,j = nums.length-1; i < j; ) {
if (nums[i]+nums[j]==0){
return nums[j];
}else if(nums[i]+nums[j]<0){
i++;
}else{
j++;
}
}
return -1;
}
}
在一个仓库里,有一排条形码,其中第 i 个条形码为 barcodes[i]。
请你重新排列这些条形码,使其中任意两个相邻的条形码不能相等。 你可以返回任何满足该要求的答案,此题保证存在答案。
思路
将所给数组进行排序,然后分为两组,将两组相互交叉即可,因为一定有答案,所以会出现四种特殊情况,当左边全部相等,从左边开始进行交叉,当右边全部相等,从右边开始交叉,当中间分开区域相等,从中间向两边开始交叉。
public class Sulotion1054 {
public static int[] rearrangeBarcodes(int[] barcodes) {
Arrays.sort(barcodes);
int len = barcodes.length;
int[] res = new int[len];
int temp = 0;
if (barcodes.length % 2 > 0) {
if (barcodes[len - 1] == barcodes[len / 2]) {
for (int i = 0, j = len - 1; i < j; i++, j--) {
res[temp++] = barcodes[j];
res[temp++] = barcodes[i];
}
res[temp++] = barcodes[len / 2];
} else {
if (barcodes[len / 2] == barcodes[len / 2 + 1]) {
for (int i = 0, j = len - 1, k = len/2,l = len/2+1; i < len/2/2; i++, j--,k--,l++) {
res[temp++] = barcodes[k];
res[temp++] = barcodes[i];
res[temp++] = barcodes[l];
res[temp++] = barcodes[j];
}
res[temp++] = barcodes[len/2/2];
} else {
for (int i = len / 2, j = len - 1; i > 0; i--, j--) {
res[temp++] = barcodes[i];
res[temp++] = barcodes[j];
}
res[temp++] = barcodes[0];
}
}
} else {
for (int i = len / 2 - 1, j = len - 1; i >= 0; i--, j--) {
res[temp++] = barcodes[i];
res[temp++] = barcodes[j];
}
}
return res;
}
}
给定 m x n 矩阵 matrix 。
你可以从中选出任意数量的列并翻转其上的 每个 单元格。(即翻转后,单元格的值从 0 变成 1,或者从 1 变为 0 。)
返回 经过一些翻转后,行与行之间所有值都相等的最大行数 。
思路
求相同的行的最多数量,列可以翻转,类似
001,110
这种,可以将他们当作一类数据,如001
就是false,false,true
,110
为false,false,true
,只要将true
翻转即可得到相同的行,将矩阵中每一行的数据类型存储到Map
中,然后找到最大相同的数量。
public class Sulotion1072 {
public static int maxEqualRowsAfterFlips(int[][] matrix) {
Map<Map<Integer, Boolean>, Integer> map = new HashMap();
int res = 0;
for (int[] row : matrix) {
Map<Integer, Boolean> b = new Hashtable<>();
for (int i = 0; i < matrix[0].length; i++){
// 用第一行第一个表示为true,之后的false是都需要反转的
b.put(i, (row[0] ^ row[i]) == 1);
}
// getOrDefault:若存在b则返回对应的value否则创建默认0
map.put(b, map.getOrDefault(b, 0) + 1);
res = Math.max(res, map.get(b));
}
return res;
}
}
主要用到动态规划,后续学习动态规划一并处理,现在还是实力欠佳
思路
简单题我重拳出击,分别判断一个时间段是否在另一个时间段内
public class Sulotion2446 {
public boolean haveConflict(String[] event1, String[] event2) {
return !(event1[1].compareTo(event2[0]) < 0 || event2[1].compareTo(event1[0]) < 0);
}
}
给出基数为 -2 的两个数 arr1 和 arr2,返回两数相加的结果。
数字以 数组形式 给出:数组由若干 0 和 1 组成,按最高有效位到最低有效位的顺序排列。例如,arr = [1,1,0,1] 表示数字 (-2)^3 + (-2)^2 + (-2)^0 = -3。数组形式 中的数字 arr 也同样不含前导零:即 arr == [0] 或 arr[0] == 1。
返回相同表示形式的 arr1 和 arr2 相加的结果。两数的表示形式为:不含前导零、由若干 0 和 1 组成的数组。
class Solution1073 {
public int[] addNegabinary(int[] arr1, int[] arr2) {
int i = arr1.length - 1, j = arr2.length - 1;
int carry = 0;
List<Integer> ans = new ArrayList<Integer>();
while (i >= 0 || j >= 0 || carry != 0) {
int x = carry;
if (i >= 0) {
x += arr1[i];
}
if (j >= 0) {
x += arr2[j];
}
if (x >= 2) {
ans.add(x - 2);
carry = -1;
} else if (x >= 0) {
ans.add(x);
carry = 0;
} else {
ans.add(1);
carry = 1;
}
--i;
--j;
}
while (ans.size() > 1 && ans.get(ans.size() - 1) == 0) {
ans.remove(ans.size() - 1);
}
int[] arr = new int[ans.size()];
for (i = 0, j = ans.size() - 1; j >= 0; i++, j--) {
arr[i] = ans.get(j);
}
return arr;
}
}
你有一套活字字模 tiles,其中每个字模上都刻有一个字母 tiles[i]。返回你可以印出的非空字母序列的数目。
注意:本题中,每个活字字模只能使用一次。
public class Sulotion1079 {
int sum = 0;
public int numTilePossibilities(String tiles) {
int length = tiles.length();
int[] arr = new int[26];
for (int i = 0; i < length; i++) {
arr[tiles.charAt(i) - 'A']++;
}
find(arr, length, 0);
return sum;
}
private void find(int[] arr, int n, int index) {
if (n == 1) {
sum++;
return;
}
if (n > 0) {
int a = 1;
int b = 1;
for (int i = 2; i <= n; i++) {
a *= i;
}
for (int value : arr) {
if (value > 1) {
for (int i = 2; i <= value; i++) {
b *= i;
}
}
}
sum += (a / b);
for (int i = index; i < 26; i++) {
int value = arr[i];
if (value > 0) {
arr[i]--;
find(arr, n - 1, i);
arr[i]++;
}
}
}
}
}
给你二叉树的根节点 root 和一个整数 limit ,请你同时删除树中所有 不足节点 ,并返回最终二叉树的根节点。
假如通过节点 node 的每种可能的 “根-叶” 路径上值的总和全都小于给定的 limit,则该节点被称之为 不足节点 ,需要被删除。
叶子节点,就是没有子节点的节点。
思路
题目描述不是特别清晰,我重新描述一遍,就是将每条数枝的和加起来,判断是否大于
limit
如果大于limit
则不用管,如果小于,则将该树枝的叶子节点删除,如果一个节点的两个叶子节点都被删除 ,则该节点也被删除。使用dfs
遍历,将和加起来分别判断左右节点是否满足条件,然后做出相应的删除操作。
public class Sulotion1080 {
public TreeNode sufficientSubset(TreeNode root, int limit) {
shuck(root, limit, 0);
return root;
}
public static boolean shuck(TreeNode root, int limit, int num) {
if (root == null) {
return false;
}
if (root.left == null && root.right == null) {
return num + root.val >= limit;
}
boolean left = shuck(root.left, limit, num + root.val);
boolean right = shuck(root.right, limit, num + root.val);
if (!left) {
root.left = null;
}
if (!right) {
root.right = null;
}
return left||right;
}
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {
}
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
我们有一个 n 项的集合。给出两个整数数组 values 和 labels ,第 i 个元素的值和标签分别是 values[i] 和 labels[i]。还会给出两个整数 numWanted 和 useLimit 。
从 n 个元素中选择一个子集 s :
子集 s 的大小 小于或等于 numWanted 。
s 中 最多 有相同标签的 useLimit 项。
一个子集的 分数 是该子集的值之和。
返回子集 s 的最大 分数 。
public class Sulotion1090 {
public static int largestValsFromLabels(int[] values, int[] labels, int numWanted, int useLimit) {
int n = values.length;
Integer[] id = new Integer[n];
for (int i = 0; i < n; i++) {
id[i] = i;
}
Arrays.sort(id, (a, b) -> values[b] - values[a]);
int res = 0, choose = 0;
Map<Integer, Integer> map = new Hashtable<>();
for (int i = 0; i < n && choose < numWanted; i++) {
int label = labels[id[i]];
if (map.getOrDefault(label, 0) == useLimit) {
continue;
}
choose++;
res += values[id[i]];
map.put(label, map.getOrDefault(label, 0) + 1);
}
return res;
}
}
我们对 0 到 255 之间的整数进行采样,并将结果存储在数组 count 中:count[k] 就是整数 k 在样本中出现的次数。
计算以下统计数据:
minimum :样本中的最小元素。
maximum :样品中的最大元素。
mean :样本的平均值,计算为所有元素的总和除以元素总数。
median :
如果样本的元素个数是奇数,那么一旦样本排序后,中位数 median 就是中间的元素。
如果样本中有偶数个元素,那么中位数median 就是样本排序后中间两个元素的平均值。
mode :样本中出现次数最多的数字。保众数是 唯一 的。
以浮点数数组的形式返回样本的统计信息 [minimum, maximum, mean, median, mode] 。与真实答案误差在 10-5 内的答案都可以通过。
public class Sulotion1093 {
public static double[] sampleStats(int[] count) {
double[] res = new double[5];
int flag = 0, temp = 0;
double sum1 = 0.0;
long sum = 0;
for (int i = 0; i < count.length; i++) {
if (count[i] != 0 && flag == 0) {
res[0] = i;
flag++;
}
if (count[i] != 0) {
res[1] = i;
sum1 += count[i];
}
sum += (long)count[i] * i;
if (count[i] > temp) {
temp = count[i];
res[4] = i;
}
}
res[2] = sum / sum1;
if (sum1 % 2 == 0) {
int tes = 0;
for (int i = 0; i < count.length; i++) {
tes += count[i];
if (tes > sum1 / 2) {
res[3] = i;
break;
}
if (tes == sum1 / 2) {
int temp1 = i;
while(count[i+1]==0){
i++;
}
res[3] = (temp1 + i + 1) / 2.0;
break;
}
}
} else {
int tes = 0;
for (int i = 0; i < count.length; i++) {
tes += count[i];
if (tes >= (sum1 + 1) / 2) {
res[3] = i;
break;
}
}
}
return res;
}