第二题轻轻松松嘿嘿嘿
新的周赛只写了一道题,太惨了,记录在下面
第 77 场双周赛,用了一个多小时写出来两道题,算法能力还需要加强www,明天参加完周赛再来更新,睡了睡了晚安
- 统计是给定字符串前缀的字符串数目
给你一个字符串数组 words 和一个字符串 s ,其中 words[i] 和 s 只包含 小写英文字母 。请你返回 words 中是字符串 s 前缀 的 字符串数目 。
一个字符串的 前缀 是出现在字符串开头的子字符串。子字符串 是一个字符串中的连续一段字符序列。
输入:words = ["a","b","c","ab","bc","abc"], s = "abc"
输出:3
解释:
words 中是 s = "abc" 前缀的字符串为:
"a" ,"ab" 和 "abc" 。
所以 words 中是字符串 s 前缀的字符串数目为 3 。
思路:暴力遍历
class Solution {
public int countPrefixes(String[] words, String s) {
int sum = 0;
for(String word : words) {
int flag = 1;
if (word.length() > s.length()) continue;
for(int i = 0; i < word.length(); ++i) {
if(word.charAt(i) != s.charAt(i)) flag = 0;
}
if(flag == 1) sum += 1;
}
return sum;
}
}
-
最小平均差
给你一个下标从 0 开始长度为 n 的整数数组 nums 。下标 i 处的 平均差 指的是 nums 中 前 i + 1 个元素平均值和 后 n - i - 1 个元素平均值的 绝对差 。两个平均值都需要 向下取整 到最近的整数。请你返回产生 最小平均差 的下标。如果有多个下标最小平均差相等,请你返回 最小 的一个下标。
注意:两个数的 绝对差 是两者差的绝对值。
n 个元素的平均值是 n 个元素之 和 除以(整数除法) n 。
0 个元素的平均值视为 0 。
输入:nums = [2,5,3,9,5,3]
输出:3
解释:
- 下标 0 处的平均差为:|2 / 1 - (5 + 3 + 9 + 5 + 3) / 5| = |2 / 1 - 25 / 5| = |2 - 5| = 3 。
- 下标 1 处的平均差为:|(2 + 5) / 2 - (3 + 9 + 5 + 3) / 4| = |7 / 2 - 20 / 4| = |3 - 5| = 2 。
- 下标 2 处的平均差为:|(2 + 5 + 3) / 3 - (9 + 5 + 3) / 3| = |10 / 3 - 17 / 3| = |3 - 5| = 2 。
- 下标 3 处的平均差为:|(2 + 5 + 3 + 9) / 4 - (5 + 3) / 2| = |19 / 4 - 8 / 2| = |4 - 4| = 0 。
- 下标 4 处的平均差为:|(2 + 5 + 3 + 9 + 5) / 5 - 3 / 1| = |24 / 5 - 3 / 1| = |4 - 3| = 1 。
- 下标 5 处的平均差为:|(2 + 5 + 3 + 9 + 5 + 3) / 6 - 0| = |27 / 6 - 0| = |4 - 0| = 4 。
下标 3 处的平均差为最小平均差,所以返回 3 。
思路:一开始就想到前缀和,但是没理解前缀和的精髓,去化简公式了,化简之后发现两个平均值要单独取整,所以最后还是按照原公式做,加上一个数组来记录前缀和;另外注意用long类型防止溢出。
class Solution {
public int minimumAverageDifference(int[] nums) {
int n = nums.length;
long[] sum = new long[n + 1];
for(int i = 0; i < n; ++i) {
sum[i + 1] = sum[i] + nums[i];
}
int minn = Integer.MAX_VALUE, result = 0;
for(int i = 0; i < n; ++i) {
int chu = 0;
if(i == n - 1) chu = 0;
else chu = (int)((sum[n] - sum[i+1]) / (n - i - 1));
int res = Math.abs((int)(sum[i+1] / (i + 1)) - chu);
if (res < minn) {
minn = res;
result = i;
}
}
return result;
}
}
- 移除指定数字得到的最大结果 显示英文描述
给你一个表示某个正整数的字符串 number 和一个字符 digit 。从 number 中 恰好 移除 一个 等于 digit 的字符后,找出并返回按 十进制 表示 最大 的结果字符串。生成的测试用例满足 digit 在 number 中出现至少一次。
输入:number = "1231", digit = "1"
输出:"231"
解释:可以移除第一个 '1' 得到 "231" 或者移除第二个 '1' 得到 "123" 。
由于 231 > 123 ,返回 "231" 。
思路:如果直接用数字做,有测试用例非常非常大,比如“3583799376562395845793479237239465237598237459573929667”这样,已经完全超过了数据类型的范围,而且看题目的输入输出都是字符串,所以很明显要从字符串中找规律。
我的思路是比较简单的,假设字符串中ch与digit相等,那么会出现两种,第一种类似于7678,ch后面有大于ch字符的,如果删掉的话后面的字符串就会前移,那么从前往后遍历找第一个s(i+1)>ch的,一定是最大的;第二种,所有的ch后一位都小于ch,例如9897,从后往前遍历找第一个ch。
class Solution {
public String removeDigit(String number, char digit) {
int len = number.length();
int flag = 1;
for(int i = 0; i < len; ++i) {
char ch = number.charAt(i);
if(ch == digit) {
if(i == len - 1) return number.substring(0, i);
if(number.charAt(i + 1) > ch) {
flag = 0;
return number.substring(0, i) + number.substring(i + 1, len);
}
}
}
if (flag == 1) {
for(int i = len - 1; i >= 0; --i) {
char ch = number.charAt(i);
if(ch == digit) {
return number.substring(0, i) + number.substring(i + 1, len);
}
}
}
return " ";
}
}
- 必须拿起的最小连续卡牌数
给你一个整数数组 cards ,其中 cards[i] 表示第 i 张卡牌的 值 。如果两张卡牌的值相同,则认为这一对卡牌 匹配 。返回你必须拿起的最小连续卡牌数,以使在拿起的卡牌中有一对匹配的卡牌。如果无法得到一对匹配的卡牌,返回 -1 。
输入:cards = [3,4,2,3,4,7]
输出:4
解释:拿起卡牌 [3,4,2,3] 将会包含一对值为 3 的匹配卡牌。注意,拿起 [4,2,3,4] 也是最优方案。
思路:把每个元素以及出现的下标存到map里,然后遍历map.values()
class Solution {
public int minimumCardPickup(int[] cards) {
Map<Integer, List<Integer>> map = new HashMap<>();
for(int i = 0; i < cards.length; ++i) {
if(!map.containsKey(cards[i])) {
List<Integer> myList = new ArrayList<Integer>();
myList.add(i);
map.put(cards[i],myList);
} else {
map.get(cards[i]).add(i);
}
}
int min = 100000;
for(List list : map.values()) {
if (list.size() == 1) continue;
for(int i = 0; i < list.size() - 1; ++i) {
int res = (int)list.get(i + 1) - (int)list.get(i);
if (res < min) min = res;
}
}
if(min == 100000) return - 1;
else return min + 1;
}
}