1. 程式人生 > 其它 >[Leetcode Weekly Contest]291

[Leetcode Weekly Contest]291

連結:LeetCode

[Leetcode]2259. 移除指定數字得到的最大結果

給你一個表示某個正整數的字串 number 和一個字元 digit 。
從 number 中 恰好 移除 一個 等於 digit 的字元後,找出並返回按 十進位制 表示 最大 的結果字串。生成的測試用例滿足 digit 在 number 中出現至少一次。

按照以下策略移除數字可以使得最終結果最大:

  • 我們從左至右遍歷 \(\textit{number}\),如果遍歷到 \(\textit{number}[i] = \textit{digit}\),且 \(\textit{number}[i] < \textit{number}[i + 1]\)
    (如果存在,下同),則我們刪除該字元後得到的結果最大;
  • 如果遍歷完成依舊不存在滿足上一個條件的下標,則我們刪除 \(\textit{digit}\) 出現的最後一個下標,此時刪除該字元後得到的結果最大。
class Solution {
    public String removeDigit(String number, char digit) {
        int index = -1;
        String res = null;
        for(int i=0;i<number.length();++i) {
            if(i!=number.length()-1 && number.charAt(i) == digit && number.charAt(i+1)>number.charAt(i)) {
                res = number.substring(0, i) + number.substring(i+1, number.length());
                break;
            }
            if(number.charAt(i) == digit) index=i;
        }
        if(res!=null) return res;
        res = number.substring(0, index) + number.substring(index+1, number.length());
        return res;
    }
}

[Leetcode]2260. 必須拿起的最小連續卡牌數

給你一個整數陣列 cards ,其中 cards[i] 表示第 i 張卡牌的 值 。如果兩張卡牌的值相同,則認為這一對卡牌 匹配 。

返回你必須拿起的最小連續卡牌數,以使在拿起的卡牌中有一對匹配的卡牌。如果無法得到一對匹配的卡牌,返回 -1 。

雜湊表,記錄每個card的索引即可。

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

[Leetcode]2261. 含最多 K 個可整除元素的子陣列

給你一個整數陣列 nums 和兩個整數 k 和 p ,找出並返回滿足要求的不同的子陣列數,要求子陣列中最多 k 個可被 p 整除的元素。
如果滿足下述條件之一,則認為陣列 nums1 和 nums2 是 不同 陣列:

  • 兩陣列長度 不同 ,或者
  • 存在 至少 一個下標 i 滿足 nums1[i] != nums2[i] 。

子陣列 定義為:陣列中的連續元素組成的一個 非空 序列。

滑動視窗。移動end指標,作為子陣列右端點,同時收縮左指標,保證滑窗內是符合要求的子陣列,即最多k個可以被p整除的元素。

class Solution {
   public int countDistinct(int[] nums, int k, int p) {
       int start = 0;
       HashSet<Integer> set = new HashSet<>();
       HashSet<String> res = new HashSet<>();
       int count = 0;
       for(int end=0;end<nums.length;++end) {
           if(nums[end] % p == 0) {
                count ++;
                set.add(end);
           }
           if(count > k) {
                while(!set.contains(start)) start ++;
                start ++;
                count --;
           }
           addArray(res, nums, start, end);
       }
       return res.size();
    }

    public void addArray(HashSet<String> res, int[] nums, int start, int end) {
        String value = "";
        for(int ind=end;ind>=start;ind--) {
            value += ("-" + nums[ind]);
            res.add(value);
        }
    }
}

[Leetcode]2262. 字串的總引力

字串的 引力 定義為:字串中 不同 字元的數量。

例如,"abbca" 的引力為 3 ,因為其中有 3 個不同字元 'a'、'b' 和 'c' 。
給你一個字串 s ,返回 其所有子字串的總引力 。

子字串 定義為:字串中的一個連續字元序列。

找規律,分類討論:
如果 \(s[i]\) 之前沒有遇到過,那麼這些子串的引力值都會增加 1,這些子串的引力值之和會增加 i,再加上 1,即 \(s[i]\) 單獨組成的子串的引力值;
如果 \(s[i]\) 之前遇到過,設其上次出現的下標為 j,那麼向子串 \(s[0..i-1],\ s[1..i-1],\ s[2..i-1],\cdots,s[j..i-1]\) 的末尾新增 \(s[i]\) 後,這些子串的引力值是不會變化的,因為 \(s[i]\) 已經在 \(s[j]\) 處出現過了;而子串 \(s[j+1..i-1],\ s[j+2..i-1],\cdots,s[i-1..i-1]\) 由於不包含字元 \(s[i]\),這些子串的引力值都會增加 1,因此有 \(i-j-1\) 個子串的引力值會增加 1,這些子串的引力值之和會增加 \(i-j-1\),再加上 1,即 \(s[i]\) 單獨組成的子串的引力值。

class Solution {
    public long appealSum(String s) {
        long cur = 0, res = 0;
        HashMap<Character, Integer> hash = new HashMap<>();
        for(int i=0;i<s.length();++i) {
            char ch = s.charAt(i);
            if(!hash.containsKey(ch)) {
                cur += i+1;
            }
            else {
                cur += i-hash.get(ch);
            }
            res += cur;
            hash.put(ch, i);
        }
        return res;
    }
}

Leetcode