Leetcode Test
2216 美化数组的最少删除数(11.21)
给你一个下标从 0 开始的整数数组 nums
,如果满足下述条件,则认为数组 nums
是一个 美丽数组 :
nums.length
为偶数- 对所有满足
i % 2 == 0
的下标i
,nums[i] != nums[i + 1]
均成立
注意,空数组同样认为是美丽数组。
你可以从 nums
中删除任意数量的元素。当你删除一个元素时,被删除元素右侧的所有元素将会向左移动一个单位以填补空缺,而左侧的元素将会保持 不变 。
返回使 nums
变为美丽数组所需删除的 最少 元素数目*。*
提示:
1 <= nums.length <= 105
0 <= nums[i] <= 105
【贪心】
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>& nums) {int n = nums.size(), cnt = 0;for (int i = 0; i < n; i++) {if ((i - cnt) % 2 == 0 && i + 1 < n && 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
,由从 0
到 m * 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
一条路径的代价是:所有路径经过的单元格的 值之和 加上 所有移动的 代价之和 。从 第一行 任意单元格出发,返回到达 最后一行 任意单元格的最小路径代价。
提示:
m == grid.length
n == grid[i].length
2 <= m, n <= 50
grid
由从0
到m * n - 1
的不同整数组成moveCost.length == m * n
moveCost[i].length == n
1 <= moveCost[i][j] <= 100
【记忆化搜索】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]&i=0\\ min_{k=0}^{n-1}(dfs(i-1,k)+moveCost[grid[i-1][k]][j]+grid[i][j])&i>0 \end{cases} dfs(i,j)={grid[i][j]mink=0n−1(dfs(i−1,k)+moveCost[grid[i−1][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];//记忆了dfsint 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 里这些特殊字符和它们对应的字符实体包括:
- **双引号:**字符实体为
"
,对应的字符是"
。 - **单引号:**字符实体为
'
,对应的字符是'
。 - **与符号:**字符实体为
&
,对应对的字符是&
。 - **大于号:**字符实体为
>
,对应的字符是>
。 - **小于号:**字符实体为
<
,对应的字符是<
。 - **斜线号:**字符实体为
⁄
,对应的字符是/
。
给你输入字符串 text
,请你实现一个 HTML 实体解析器,返回解析器解析后的结果。
提示:
1 <= text.length <= 10^5
- 字符串可能包含 256 个ASCII 字符中的任意字符。
【模拟】遍历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, """ , 6)) *(p ++) = '\"', text += 6;else if (!strncmp(text, "'" , 6)) *(p ++) = '\'', text += 6;else if (!strncmp(text, "&" , 5)) *(p ++) = '&' , text += 5;else if (!strncmp(text, ">" , 4)) *(p ++) = '>' , text += 4;else if (!strncmp(text, "<" , 4)) *(p ++) = '<' , text += 4;else if (!strncmp(text, "⁄", 7)) *(p ++) = '/' , text += 7;else *(p ++) = *(text ++) ;return ans;
}
2824 统计和小于目标的下标对数目(11.24)
给你一个下标从 0 开始长度为 n
的整数数组 nums
和一个整数 target
,请你返回满足 0 <= i < j < n
且 nums[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 。我们称二叉树中的一条路径是 「伪回文」的,当它满足:路径经过的所有节点值的排列中,存在一个回文序列。
请你返回从根到叶子节点的所有路径中 伪回文 路径的数目。
提示:
- 给定二叉树的节点数目在范围
[1, 105]
内 1 <= Node.val <= 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 valuefor(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)
的总和,其中 t
是 s
的子字符串。输入用例保证返回值为 32 位整数。
注意,某些子字符串可能是重复的,但你统计时也必须算上这些重复的子字符串(也就是说,你必须统计 s
的所有子字符串中的唯一字符)。
提示:
1 <= s.length <= 105
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]
*/