给你一个下标从 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 再加一)
*/
给你一个下标从 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];//记忆了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;
}
「HTML 实体解析器」 是一种特殊的解析器,它将 HTML 代码作为输入,并用字符本身替换掉所有这些特殊的字符实体。
HTML 里这些特殊字符和它们对应的字符实体包括:
"
,对应的字符是 "
。'
,对应的字符是 '
。&
,对应对的字符是 &
。>
,对应的字符是 >
。<
,对应的字符是 <
。⁄
,对应的字符是 /
。给你输入字符串 text
,请你实现一个 HTML 实体解析器,返回解析器解析后的结果。
提示:
1 <= text.length <= 10^5
【模拟】遍历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;
}
给你一个下标从 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;
}
给你一棵二叉树,每个节点的值为 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 value
for(int i=0;i<maxVal;i++){
arr[i]=0;
}
return dfs(root,arr);
}
我们定义了一个函数 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;
}
给定一个整数数组 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]
*/