【Leetcode Sheet】Weekly Practice 24

Leetcode Test

447 回旋镖的数量(1.8)

给定平面上 n互不相同 的点 points ,其中 points[i] = [xi, yi]回旋镖 是由点 (i, j, k) 表示的元组 ,其中 ij 之间的距离和 ik 之间的欧式距离相等(需要考虑元组的顺序)。

返回平面上所有回旋镖的数量。

提示:

  • n == points.length
  • 1 <= n <= 500
  • points[i].length == 2
  • -104 <= xi, yi <= 104
  • 所有点都 互不相同

【枚举法】

class Solution {
public:
    int numberOfBoomerangs(vector<vector<int>> &points) {
        int ans = 0;
        unordered_map<int, int> cnt;
        for (auto &p1 : points) {
            cnt.clear();
            for (auto &p2 : points) {
                int d2 = (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]);
                ans += cnt[d2]++ * 2;
            }
        }
        return ans;
    }
};

2707 字符串中的额外字符(1.9)

给你一个下标从 0 开始的字符串 s 和一个单词字典 dictionary 。你需要将 s 分割成若干个 互不重叠 的子字符串,每个子字符串都在 dictionary 中出现过。s 中可能会有一些 额外的字符 不在任何子字符串中。

请你采取最优策略分割 s ,使剩下的字符 最少

提示:

  • 1 <= s.length <= 50
  • 1 <= dictionary.length <= 50
  • 1 <= dictionary[i].length <= 50
  • dictionary[i]s 只包含小写英文字母。
  • dictionary 中的单词互不相同。

【动态规划】

class Solution {
public:
    int minExtraChar(string s, vector<string>& dictionary) {
        int n = s.size();
        vector<int> d(n + 1, INT_MAX);
        unordered_map<string, int> mp;
        for (auto s : dictionary) {
            mp[s]++;
        }
        d[0] = 0;
        for (int i = 1; i <= n; i++) {
            d[i] = d[i - 1] + 1;
            for (int j = i - 1; j >= 0; j--) {
                if (mp.count(s.substr(j, i - j))) {
                    d[i] = min(d[i], d[j]);
                }
            }
        }
        return d[n];
    }
};

2696 删除字串后的字符串最小长度(1.10)

给你一个仅由 大写 英文字符组成的字符串 s

你可以对此字符串执行一些操作,在每一步操作中,你可以从 s 中删除 任一个 "AB""CD" 子字符串。

通过执行操作,删除所有 "AB""CD" 子串,返回可获得的最终字符串的 最小 可能长度。

注意,删除子串后,重新连接出的字符串可能会产生新的 "AB""CD" 子串。

提示:

  • 1 <= s.length <= 100
  • s 仅由大写英文字母组成

【栈】

int minLength(char *s){
    int n = strlen(s), m = 0;
    char *stack = (char *)malloc(sizeof(char) * n);
    for (int i = 0; i < n; i++) {
        stack[m++] = s[i];
        if (m >= 2 && (
            stack[m - 2] == 'A' && stack[m - 1] == 'B' ||
            stack[m - 2] == 'C' && stack[m - 1] == 'D'
        )) {
            m -= 2;
        }
    }
    free(stack);
    return m;
}

2645 构造有效数字串的最少插入数(1.11)

给你一个字符串 word ,你可以向其中任何位置插入 “a”、“b” 或 “c” 任意次,返回使 word 有效 需要插入的最少字母数。

如果字符串可以由 “abc” 串联多次得到,则认为该字符串 有效

提示:

  • 1 <= word.length <= 50
  • word 仅由字母 “a”、“b” 和 “c” 组成。

【计算组数】如果有一次下降,例如ba,则代表b和a肯定不是一个组里面的,需要插入字母变成2个组

int addMinimum(char * word){
    int n=strlen(word);
    int cnt=1;
    for(int i=1;i<n;i++){
        if(word[i]<=word[i-1]){
            cnt++;
        }
    }
    return cnt*3-n;
}

【动态规划】
d p [ 0 ] = 0 dp[0]=0 dp[0]=0

d [ i ] = d [ i − 1 ] + 2 ( w o r d [ i ] 单独存在于一组 a b c 中) d[i]=d[i-1]+2(word[i]单独存在于一组abc中) d[i]=d[i1]+2word[i]单独存在于一组abc中)

d [ i ] = d [ i − 1 ] − 1 ( w o r d [ i ] 可以和 w o r d [ i − 1 ] 在同一组 a b c 中) d[i]=d[i-1]-1(word[i]可以和word[i-1]在同一组abc中) d[i]=d[i1]1word[i]可以和word[i1]在同一组abc中)

int addMinimum(char * word) {
    int n = strlen(word);
    int d[n + 1];
    memset(d, 0, sizeof(d));
    for (int i = 1; i <= n; i++) {
        d[i] = d[i - 1] + 2;
        if (i > 1 && word[i - 1] > word[i - 2]) {
            d[i] = d[i - 1] - 1;
        }
    }
    return d[n];
}

2085 统计出现过一次的公共字符串(1.12)

给你两个字符串数组 words1words2 ,请你返回在两个字符串数组中 都恰好出现一次 的字符串的数目。

提示:

  • 1 <= words1.length, words2.length <= 1000
  • 1 <= words1[i].length, words2[j].length <= 30
  • words1[i]words2[j] 都只包含小写英文字母。

【hash】

class Solution {
public:
    int countWords(vector<string>& words1, vector<string>& words2) {
        unordered_map<string,int>f1,f2;
        for(auto w:words1){
            f1[w]++;
        }
        for(auto w:words2){
            f2[w]++;
        }
        int cnt=0;
        for(auto [w,num]:f1){
            if(num==1 && f2[w]==1){
                cnt++;
            }
        }
        return cnt;
    }
};

2182 构造限制重复的字符串(1.13)

给你一个字符串 s 和一个整数 repeatLimit ,用 s 中的字符构造一个新字符串 repeatLimitedString ,使任何字母 连续 出现的次数都不超过 repeatLimit 次。你不必使用 s 中的全部字符。

返回 字典序最大的 repeatLimitedString

如果在字符串 ab 不同的第一个位置,字符串 a 中的字母在字母表中出现时间比字符串 b 对应的字母晚,则认为字符串 a 比字符串 b 字典序更大 。如果字符串中前 min(a.length, b.length) 个字符都相同,那么较长的字符串字典序更大。

提示:

  • 1 <= repeatLimit <= s.length <= 105
  • s 由小写英文字母组成

【贪心 + 双指针 + hash计数】

char* repeatLimitedString(char* s, int repeatLimit) {
    int *cnt=(int*)malloc(sizeof(int)*26);
    for(int i=0;i<26;i++){
        cnt[i]=0;
    }
    int n=strlen(s);
    for(int i=0;i<n;i++){
        cnt[s[i]-'a']++;
    }
    
    char *ret=(char*)malloc(sizeof(char)*(n+1));
    char *p=ret;
    memset(ret,0,sizeof(char)*(n+1));

    int m=0;
    for(int i=25,j=24; i>=0 && j>=0; ){
        //当前字符用完
        if(cnt[i]==0){
            m=0;
            i--;
        }
        //当前字符未超过limit
        else if(m < repeatLimit){
            cnt[i]--;
            *(p++)='a'+i;
            m++;
        }
        //当前字符超过限制,查找其他可填入字符
        else if(j>=i || cnt[j]==0){
            j--;
        }
        //当前字符超过limit,填入其他字符
        else{
            cnt[j]--;
            *(p++)='a'+j;
            m=0;
        }
    }
    return ret;
}

83 删除排序链表中的重复元素(1.14)

给定一个已排序的链表的头 head删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表

提示:

  • 链表中节点数目在范围 [0, 300]
  • -100 <= Node.val <= 100
  • 题目数据保证链表已经按升序 排列

【模拟】

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* deleteDuplicates(struct ListNode* head) {
    if(head == NULL) return head;
    
    struct ListNode* t=head;
    while(t->next != NULL){
        if(t->next->val == t->val){
            t->next=t->next->next;
        }
        else{
            t=t->next;
        }
    }
    return head;
}

你可能感兴趣的:(Leetcode,Series,leetcode,算法)