0
点赞
收藏
分享

微信扫一扫

leetcode-第291场周赛

绣文字 2022-05-02 阅读 169

目录

2259. 移除指定数字得到的最大结果

给你一个表示某个正整数的字符串 number和一个字符 digit

number中 恰好 移除 一个 等于 digit 的字符后,找出并返回按 十进制 表示 最大 的结果字符串。生成的测试用例满足 digitnumber中出现至少一次。

示例 1:

示例 2:

示例 3:

思路:

  1. 首先第一个想法,我挨个挨个试一次呗,我从头到尾遍历,只要是跟我digit相等的字符,我就把他去掉,然后把他保存,后面只要遇到我就把这个字符去掉然后跟之前保存的比较,最后谁最大我就返回谁

but!but!你有没有发现,这种效率不是很高,什么你问我为什么不是很高。很简单。
number = "12131415161",digit="1";如果我们暴力法一次比较。我们需要比较6次!但是我们发现没有?实际上我number无论去掉哪一个字符,最终都是number.length()-1位数。既然是数学上比较大小的问题,那说明什么?肯定是高位越大的同样长度的数字更大啊。你说我去掉第一个1。我最高位就是2了,如果我去掉后面的其他的1。我的高位肯定是是1啊。这部显而易见。肯定是去掉第一个1就行了。也就是我只需要操作一次就行了啊。如此一来我们的思路↓

  1. 从头往后遍历
  2. 只要遇到number.charAt(i) == digit我就看number.charAt(i+1)是否比number.charAt(i)大,如果大,越早去掉越好。否则的话,就去掉最后一个
  3. 有个小细节,我们最后一个字符可能不太好比较,所以我们可以给number加一个其他字符。最后返回的时候删除就行了

代码实现:

class Solution {
    public String removeDigit(String number, char digit) {
        number = number + "-";//为了最后一个字符也能比较
        int len = number.length();
        char[] ch = number.toCharArray();
        String temp = "";

        for (int i = 1; i < len; i++) {
            if (digit == ch[i - 1] && i != len) {
                temp = number.substring(0, i - 1) + number.substring(i, len);
                if (ch[i] > ch[i - 1]) {
                    break;
                }
            }
        }
        return temp.substring(0,len-2);//记得把最后一个字符去掉
    }
}

2260. 必须拿起的最小连续卡牌数

给你一个整数数组 cards ,其中 cards[i] 表示第 i 张卡牌的 值 。如果两张卡牌的值相同,则认为这一对卡牌 匹配 。

返回你必须拿起的最小连续卡牌数,以使在拿起的卡牌中有一对匹配的卡牌。如果无法得到一对匹配的卡牌,返回 -1 。

示例 1:

示例 2:

思路:
没什么好说的,用HashMap的key不可重复的特性,保存和cards[i]相同值的前一个值的下标。那么我就知道当前这副牌有i - map.get(cards[i]) + 1张。从前往后不断迭代更新出最短的就行

代码实现:

class Solution {
    public int minimumCardPickup(int[] cards) {
        int len = cards.length;
        int res = Integer.MAX_VALUE;
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < len; i++) {
            if (map.containsKey(cards[i])) {
                res = Math.min(res, 1 + i - map.get(cards[i]));
            }
            map.put(cards[i], i);
        }
        if (res == Integer.MAX_VALUE) {
            return -1;
        }
        return res;
    }
}

2261. 含最多 K 个可整除元素的子数组

给你一个整数数组 nums 和两个整数 k 和 p ,找出并返回满足要求的不同的子数组数,要求子数组中最多 k 个可被 p 整除的元素。

如果满足下述条件之一,则认为数组 nums1 和 nums2 是 不同 数组:

两数组长度 不同 ,或者
存在 至少 一个下标 i 满足 nums1[i] != nums2[i] 。
子数组 定义为:数组中的连续元素组成的一个 非空 序列。

示例 1:

示例 2:

思路:

  1. 这不就是排列组合吗,但是这个排列组合是有顺序的,有顺序的排列组合
  2. 这个组合里有重复的数字,所以记得去重==>用Set数据结构

ps:为啥Set可以去重?那我就跟你好好battle一下了。Set的主要实现类是HashSet,他继承了Set接口。拥有Set接口众多的方法。HashSet底层是用HashMap的key作为他的value的。HashMap底层是Hash表,根据他的key的hash值作为下标,下标只有一个所以key不可重复。因此HashSet的value不能重复。你可能会问,我用HashMap的key作为value值,那HashMap的value用来干嘛呢?不好意思,这个value是个特殊值,一般没用。只有当HashSet加入一个重复值时,底层发现已经有该值了,会将value返回,表示加入的值重复了。

扯那么多其实这道题没啥捷径,从前往后遍历吧。如果有好方法,希望有人可以在评论告诉我
代码实现:

class Solution {
    public int countDistinct(int[] nums, int k, int p) {
        HashSet<String> ans = new HashSet<>();
        int len = nums.length;
        for (int i = 0; i < len; i++) {
            int cnt = k;
            StringBuilder sb = new StringBuilder();
            for (int j = i; j < len; j++) {
                sb.append(nums[j]).append("+");
                if (nums[j] % p == 0) {
                    cnt--;
                }
                if (cnt < 0) {
                    break;
                }
                ans.add(sb.toString());
            }
        }
        return ans.size();
    }
}

6050. 字符串的总引力

字符串的 引力 定义为:字符串中 不同 字符的数量。

例如,“abbca” 的引力为 3 ,因为其中有 3 个不同字符 ‘a’、‘b’ 和 ‘c’ 。
给你一个字符串 s ,返回 其所有子字符串的总引力 。

子字符串 定义为:字符串中的一个连续字符序列。

示例 1:

示例 2:

思路:

  1. 将所有子串按照其末尾字符的下标分组。
  2. 考虑两组相邻的子串:以 s[i-1]s[i−1] 结尾的子串、以 s[i]s[i] 结尾的子串。
  3. 以 s[i]s[i] 结尾的子串,可以看成是以 s[i-1]s[i−1] 结尾的子串,在末尾添加上 s[i]s[i] 组成。

上面这一串提示是思考子串统计类问题的通用技巧之一。

  1. 从左往右遍历 ss,考虑将 s[i]s[i] 添加到以 s[i-1]s[i−1] 结尾的子串的末尾。添加后,这些子串的引力值会增加多少?
  2. 分类讨论:
  • 如果 s[i]s[i] 之前没有遇到过,那么这些子串的引力值都会增加 11,这些子串的引力值之和会增加 ii,再加上 11,即 s[i]s[i] 单独组成的子串的引力值;
  • 如果 s[i]s[i] 之前遇到过,设其上次出现的下标为 jj,那么向子串 s[0…i-1],\ s[1…i-1],\ s[2…i-1],\cdots,s[j…i-1]s[0…i−1], s[1…i−1], s[2…i−1],⋯,s[j…i−1] 的末尾添加 s[i]s[i] 后,这些子串的引力值是不会变化的,因为 s[i]s[i] 已经在 s[j]s[j] 处出现过了;而子串 s[j+1…i-1],\ s[j+2…i-1],\cdots,s[i-1…i-1]s[j+1…i−1], s[j+2…i−1],⋯,s[i−1…i−1] 由于不包含字符 s[i]s[i],这些子串的引力值都会增加 11,因此有 i-j-1i−j−1 个子串的引力值会增加 11,这些子串的引力值之和会增加 i-j-1i−j−1,再加上 11,即 s[i]s[i] 单独组成的子串的引力值。

代码实现:

class Solution {
    public long appealSum(String s) {
        int len = s.length();
        int[] pos = new int[26];
        Arrays.fill(pos, -1);
        long sum = 0;
        for (int i = 0; i < s.length(); i++) {
            int index = s.charAt(i) - 'a';
            sum += (i - pos[index]) * (len - i);
            pos[index] = i;
        }

        return sum;
    }
}
举报

相关推荐

0 条评论