本文介绍: 【Leetcode Sheet】Weekly Practice 17

Leetcode Test

2216 美化数组的最少删除数(11.21)

给你一个下标0 开始的整数数组 nums ,如果满足下述条件,则认为数组 nums一个 美丽数组

注意,空数组同样认为是美丽数组

可以nums删除任意数量的元素。当你删除一个元素时,被删除元素右侧的所有元素将会向左移动一个单位以填补空缺,而左侧的元素将会保持 不变

返回使 nums 变为美丽数组所需删除的 最少素数目*。*

提示

贪心

int minDeletion(int* nums, int numsSize) {
    //美丽数组要求
    //1:偶数下标i,nums[i]!=nums[i+1]
    //2:len(new-nums)是偶数

    int n=numsSize,left=0,right=1,cnt=0;
    //left记录偶数下标right探索一个数,cnt记录删除的个数

    while(right<n){
        if(nums[right]!=nums[left]){
            //符合等式条件
            left=right+1;
            right=left+1;
        }
        else{
            //不符合等式条件
            right++;
            cnt++;
        }
    }

    if(left<n){
        //如果最后剩余奇数个数字,则需要删除一个
        cnt++;
    }
    
    return cnt;
}

cpp极简版本】宫水三叶

2216. 美化数组的最少删除数 – 力扣(LeetCode)

class Solution {
public:
    int minDeletion(vector<int&gt;&amp; nums) {
        int n = nums.size(), cnt = 0;
        for (int i = 0; i < n; i++) {
            if ((i - cnt) % 2 == 0 &amp;&amp; i + 1 < n &amp;&amp; nums[i] == nums[i + 1]) {
                //如果当前下标是偶数,且下一个下标存在数组中,且当前num等于下一个num
                //则不符合条件cnt自增
                cnt++;
            }
        }
        return (n - cnt) % 2 != 0 ? cnt + 1 : cnt;
    }
};
/*
1:每次删除元素,剩余元素都会往前移动,因此当前下标为i-cnt
2:处理 nums 过程中,若当前下标为偶数,且与下一位置元素相同,那么当前元素需被删除,令 cnt 自增
3:最终数组长度为 n−cnt,若长度奇数,需要再额外删除结尾元素(cnt 再加一)
*/

2304 网格中的最小路径代价(11.22)

给你一个下标从 0 开始的整数矩阵 grid ,矩阵大小m x n ,由从 0m * n - 1 的不同整数组成。你可以在此矩阵中,从一个单元格移动到 一行 的任何其他单元格。如果你位于单元格 (x, y) ,且满足 x < m - 1 ,你可以移动到 (x + 1, 0), (x + 1, 1), …, (x + 1, n - 1) 中的任何一个单元格注意:最后一行中的单元格不能触发移动。

每次可能的移动都需要付出对应的代价,代价用一个下标从 0 开始的二维数组 moveCost 表示,该数大小(m * n) x n ,其中 moveCost[i][j] 是从值为 i单元格移动到下一行j单元格的代价。从 grid 最后一行单元格移动的代价可以忽略

grid 一条路径的代价是:所有路径经过的单元格的 值之和 加上 所有移动的 代价之和 。从 第一行 任意单元格出发,返回到达 最后一行 任意单元格的最小路径代价。

提示

【记忆化搜索dfs

d

f

s

(

i

,

j

)

=

{

g

r

i

d

[

i

]

[

j

]

i

=

0

m

i

n

k

=

0

n

1

(

d

f

s

(

i

1

,

k

)

+

m

o

v

e

C

o

s

t

[

g

r

i

d

[

i

1

]

[

k

]

]

[

j

]

+

g

r

i

d

[

i

]

[

j

]

)

i

>

0

dfs(i,j)=begin{cases} grid[i][j]&amp;i=0\ min_{k=0}^{n-1}(dfs(i-1,k)+moveCost[grid[i-1][k]][j]+grid[i][j])&amp;i>0 end{cases}

dfs(i,j)={grid[i][j]mink=0n1(dfs(i1,k)+moveCost[grid[i1][k]][j]+grid[i][j])i=0i>0
到达第 0 行的单元格,则代价是到达单元格的数值

到达第 i 行的单元格 (i, j) ,则代价是到达单元格 (i-1, k)的代价 + (i-1, k)到(i, j)的路径代价 + (i, j)的数值

int **memo=NULL;

//dfs(i,j)是从第0行的任意单元格出发,到达(i,j)单元格的最小路径代价
int dfs(int i,int j,int **grid,int **moveCost,int n){
    if(i==0) return grid[i][j];
    if(memo[i][j]>=0) return memo[i][j];//记忆了dfs
    
    int ret=INT_MAX;
    for(int k=0;k<n;k++){
        ret=fmin(ret,dfs(i-1,k,grid,moveCost,n)+moveCost[grid[i-1][k]][j]+grid[i][j]);
    }
    memo[i][j]=ret;
    return ret;
}

int minPathCost(int** grid, int gridSize, int* gridColSize, int** moveCost, int moveCostSize, int* moveCostColSize) {
    int m=gridSize,n=gridColSize[0];
    memo=(int**)malloc(sizeof(int*)*m);
    for(int i=0;i<m;i++){
        memo[i]=(int*)malloc(sizeof(int)*n);
        for(int j=0;j<n;j++){
            memo[i][j]=-1;
        }
    }

    int ret=INT_MAX;
    for(int j=0;j<n;j++){
        ret=fmin(ret,dfs(m-1,j,grid,moveCost,n));
    }
    for(int i=0;i<m;i++){
        free(memo[i]);
    }
    free(memo);
    return ret;
}

1410 HTML实体解析器(11.23)

「HTML 实体解析器」 是一种特殊解析器,它将 HTML 代码作为输入,并用字符本身替换掉所有这些特殊字符实体

HTML 里这些特殊字符和它们对应字符实体包括:

  • **双引号:**字符实体为 &amp;quot;对应字符"
  • **单引号:**字符实体为 &amp;apos; ,对应的字符'
  • **与符号:**字符实体为 &amp;amp; ,对应对的字符是 &amp;
  • **大于号:**字符实体为 &amp;gt; ,对应的字符是 >
  • **小于号:**字符实体为 &amp;lt; ,对应的字符是 <
  • **斜线号:**字符实体为 &amp;frasl; ,对应的字符是 /

给你输入字符串 text ,请你实现一个 HTML 实体解析器,返回解析器解析后的结果

提示

模拟遍历1次并替换substring使用strncmp函数进行子串比较

char* entityParser(char* text) {
    char* ans = (char*)calloc(1, sizeof(char) * (strlen(text) + 1));
    char* p = ans;
    while (*text) 
        if      (*text != '&'                ) *(p ++) =     *(text ++) ;
        else if (!strncmp(text, "&quot;" , 6)) *(p ++) = '"', text += 6;
        else if (!strncmp(text, "&apos;" , 6)) *(p ++) = ''', text += 6;
        else if (!strncmp(text, "&amp;"  , 5)) *(p ++) = '&' , text += 5;
        else if (!strncmp(text, "&gt;"   , 4)) *(p ++) = '>' , text += 4;
        else if (!strncmp(text, "&lt;"   , 4)) *(p ++) = '<' , text += 4;
        else if (!strncmp(text, "&frasl;", 7)) *(p ++) = '/' , text += 7;
        else                                   *(p ++) =     *(text ++) ;
    return ans;
}

2824 统计和小于目标的下标对数目(11.24)

给你一个下标从 0 开始长度n整数数组 nums 和一个整数 target ,请你返回满足 0 <= i < j < nnums[i] + nums[j] < target 的下标对 (i, j)数目

提示

  • 1 <= nums.length == n <= 50
  • -50 <= nums[i], target <= 50

【双指针

int cmp(void *a,void *b){
    return *(int*)a-*(int*)b;
}

int countPairs(int* nums, int numsSize, int target){
    int n=numsSize,cnt=0;
    qsort(nums,n,sizeof(int),cmp);
    for(int i=0,j=n-1;i<j;i++){
        while(i<j && nums[i]+nums[j]>=target){
            j--;
        }
        cnt+=j-i;
    }
    return cnt;
}

1457 二叉树中的伪回文路径(11.25)

给你一棵二叉树每个节点的值为 1 到 9 。我们二叉树中的一条路径是 「回文」的,当它满足:路径经过的所有节点值的排列中,存在一个回文序列

请你返回从根到叶子节点的所有路径中 回文 路径的数目

提示

dfs + hash

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int maxVal=10;

bool check(int *arr){
    int cnt=0;
    for(int i=0;i<maxVal;i++){
        if(arr[i]%2==1){
            cnt++;
        }
    }
    return cnt<=1;//如果有2个数字是奇数个,则肯定不可能是回文
}

int dfs(struct TreeNode *root,int *arr){
    if(root==NULL){
        return 0;
    }

    arr[root->val]++;//当前数字进入hash
    int ret=0;
    if(root->left==NULL && root->right==NULL){
        //叶子节点
        if(check(arr)){
            ret=1;
        }
    }
    else{
        //中间的节点
        ret=dfs(root->left,arr)+dfs(root->right,arr);
        //递归左右子树
    }
    arr[root->val]--;//返回前撤销更新回溯
    return ret;
}

int pseudoPalindromicPaths (struct TreeNode* root) {
    int arr[maxVal];//hash table for value
    for(int i=0;i<maxVal;i++){
        arr[i]=0;
    }
    return dfs(root,arr);
}

828 统计子串中的唯一字符(11.26)

我们定义了一个函数 countUniqueChars(s) 来统计字符串 s 中的唯一字符,并返回唯一字符的个数

例如:s = "LEETCODE" ,则其中 "L", "T","C","O","D" 都是唯一字符,因为它们只出现一次,所以 countUniqueChars(s) = 5

本题将会给你一个字符s我们需要返回 countUniqueChars(t)总和,其中 ts 的子字符串输入用例保证返回值为 32 位整数。

注意,某些子字符串可能是重复的,但你统计时也必须算上这些重复的子字符串(也就是说,你必须统计 s 的所有子字符串中的唯一字符)。

提示

【变化量】828. 统计子串中的唯一字符 – 力扣(LeetCode)

int uniqueLetterString(char* s) {
    int n=strlen(s),ans=0;
    char c;
    for(c='A';c<='Z';c++){
        int flag1=-1,flag0=-1;
        //flag0上一次出现的下标
        //flag1上上一次出现的下标
        for(int i=0;i<n;i++){
            if(s[i]==c){
                flag1=flag0;
                flag0=i;
            }
            ans+=flag0-flag1;
        }
    }
    return ans;
}

907 子数组的最小值之和(11.27)

给定一个整数数组 arr,找到 min(b)总和,其中 b范围arr每个(连续)子数组。

由于答案可能很大,因此 返回答案模 10^9 + 7

提示

  • 1 <= arr.length <= 3 * 104
  • 1 <= arr[i] <= 3 * 104

【单调栈 / 动态规划907. 子数组的最小值之和 – 力扣(LeetCode)

int sumSubarrayMins(int* arr, int arrSize) {
    long long ans = 0;
    long long mod = 1e9 + 7;//取余
    
    int monoStack[arrSize], dp[arrSize];
    int top = 0;
    for (int i = 0; i < arrSize; i++) {
        while (top > 0 && arr[monoStack[top - 1]] > arr[i]) {
            top--;
        }
        int k = top == 0 ? (i + 1) : (i - monoStack[top - 1]);
        dp[i] = k * arr[i] + (top == 0 ? 0 : dp[i - k]);
        ans = (ans + dp[i]) % mod;
        monoStack[top++] = i;
    }
    return ans;
}
/*
从左向右遍历数组并维护一个单调递增的栈,如果栈顶的元素大于等于当前元素 arr[i] 则弹出栈,此时栈顶的元素即为左边第一个小于当前值的元素

我们求出以当前值为最右且最小的子序列的长度 k ,根据上述递推公式求出 dp[i],最终的返回值即为∑dp[i]
*/

原文地址:https://blog.csdn.net/m0_65787507/article/details/134638450

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_16131.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注