leetcode周赛272场

2108. 找出数组中的第一个回文字符串

1.题意:

给你一个字符串数组 words ,找出并返回数组中的 第一个回文字符串 。如果不存在满足要求的字符串,返回一个 空字符串 “” 。

回文字符串 的定义为:如果一个字符串正着读和反着读一样,那么该字符串就是一个 回文字符串 。

示例 1:

输入:words = ["abc","car","ada","racecar","cool"]
输出:"ada"
解释:第一个回文字符串是 "ada" 。
注意,"racecar" 也是回文字符串,但它不是第一个。

示例 2:

输入:words = ["notapalindrome","racecar"]
输出:"racecar"
解释:第一个也是唯一一个回文字符串是 "racecar" 。

示例 3:

输入:words = ["def","ghi"]
输出:""
解释:不存在回文字符串,所以返回一个空字符串。

2.解题思路:

  • 给定数据为:
    • 1 <= words.length <= 100
    • 1 <= words[i].length <= 100
  • 暴力即可

3.代码:

class Solution {
public:
    bool isPalind(string str)
{
	int i = 0;
	int j = str.size() - 1;
	while (i < j)
	{
		if (str[i] != str[j])
			return false;
		++i;
		--j;
	}
    return true;
}
string firstPalindrome(vector<string>& words) 
{
	for (const auto &it : words)
	{
		if (isPalind(it))
			return it;
	}

	return "";
}
};

2109. 向字符串添加空格

1.题意:

给你一个下标从 0 开始的字符串 s ,以及一个下标从 0 开始的整数数组 spaces 。

数组 spaces 描述原字符串中需要添加空格的下标。每个空格都应该插入到给定索引处的字符值 之前 。

例如,s = “EnjoyYourCoffee” 且 spaces = [5, 9] ,那么我们需要在 ‘Y’ 和 ‘C’ 之前添加空格,这两个字符分别位于下标 5 和下标 9 。因此,最终得到 “Enjoy Your Coffee” 。
请你添加空格,并返回修改后的字符串。

示例 1:

输入:s = "LeetcodeHelpsMeLearn", spaces = [8,13,15]
输出:"Leetcode Helps Me Learn"
解释:
下标 8、13 和 15 对应 "LeetcodeHelpsMeLearn" 中加粗斜体字符。
接着在这些字符前添加空格。

示例 2:

输入:s = "icodeinpython", spaces = [1,5,7,9]
输出:"i code in py thon"
解释:
下标 1、5、7 和 9 对应 "icodeinpython" 中加粗斜体字符。
接着在这些字符前添加空格。

示例 3:

输入:s = "spacing", spaces = [0,1,2,3,4,5,6]
输出:" s p a c i n g"
解释:
字符串的第一个字符前可以添加空格。

2.题解思路:

  • 先创建一个目标字符串,长度就是原字符长度 + 空格长度
  • 然后双指针遍历两个字符串
    • 如果是spaces的值,那么目标字符串下标就替换为空格
    • 如果不是就替换为源字符串的值
  • 直到全部遍历完毕即可

3.代码:

class Solution {
public:
string addSpaces(string s, vector<int>& spaces) 
{
	int n = s.size();
	int length = n + spaces.size();
	string res(length,' ');
	int j = length - 1;
	int i = n - 1;
	int k = spaces.size() - 1;
	while (i >= 0 && j >= i)
	{
		if (k >= 0 && i == spaces[k] - 1)		//因为我创建的时候就初始化为空格,所以直接跳过即可
		{
			--j;
			--k;
			continue;
		}
		else
		{
			res[j] = s[i];
			--j;
			--i;
		}
	}

	return res;
}
};

2110. 股票平滑下跌阶段的数目

1.题意:

给你一个整数数组 prices ,表示一支股票的历史每日股价,其中 prices[i] 是这支股票第 i 天的价格。

一个 平滑下降的阶段 定义为:对于 连续一天或者多天 ,每日股价都比 前一日股价恰好少 1 ,这个阶段第一天的股价没有限制。

请你返回 平滑下降阶段 的数目。

示例 1:

输入:prices = [3,2,1,4]
输出:7
解释:总共有 7 个平滑下降阶段:
[3], [2], [1], [4], [3,2], [2,1] 和 [3,2,1]
注意,仅一天按照定义也是平滑下降阶段。

示例 2:

输入:prices = [8,6,7,7]
输出:4
解释:总共有 4 个连续平滑下降阶段:[8], [6], [7] 和 [7]
由于 8 - 6 ≠ 1 ,所以 [8,6] 不是平滑下降阶段。

示例 3:

输入:prices = [1]
输出:1
解释:总共有 1 个平滑下降阶段:[1]

2.解题思路:

  • 经典dp题
    • 当前值如果小于前一个值,那么能组成的天数就是前一个值的天数,再加上自己.
    • 初始化当前天均为1,它自己能组成一天.
    • 所以转化方程为:
      • dp[i] += dp[i - 1].只在前一天比当前天大1的情况下可以转化.
    • 用一个变量存储,记得用long long,否则会溢出

3.代码

class Solution {
public:
    long long getDescentPeriods(vector<int>& prices)
    {
        int n = prices.size();
        if (n == 0)
            return 0;
        vector<long long> dp(n,1);
        long long res = 1;
        for (int i = 1; i < prices.size(); ++i)
        {
            if (prices[i - 1] - prices[i] == 1)
            {
                dp[i] += dp[i - 1];
            }
            res += dp[i];
        }
        
        return res;
    }
};

2111. 使数组 K 递增的最少操作次数

1.题意:

给你一个下标从 0 开始包含 n 个正整数的数组 arr ,和一个正整数 k 。

如果对于每个满足 k <= i <= n-1 的下标 i ,都有 arr[i-k] <= arr[i] ,那么我们称 arr 是 K 递增 的。

  • 比方说,arr = [4, 1, 5, 2, 6, 2]对于 k = 2 是 K 递增的,因为:

    • arr[0] <= arr[2] (4 <= 5)

    • arr[1] <= arr[3] (1 <= 2)

    • arr[2] <= arr[4] (5 <= 6)

    • arr[3] <= arr[5] (2 <= 2)

  • 但是,相同的数组 arr 对于 k = 1 不是 K 递增的(因为 arr[0] > arr[1]),对于 k = 3 也不是 K 递增的(因为 arr[0] > arr[3] )。

每一次 操作 中,你可以选择一个下标 i 并将 arr[i] 改成任意 正整数。

请你返回对于给定的 k ,使数组变成 K 递增的 最少操作次数

示例 1:

输入:arr = [5,4,3,2,1], k = 1
输出:4
解释:
对于 k = 1 ,数组最终必须变成非递减的。
可行的 K 递增结果数组为 [5,6,7,8,9],[1,1,1,1,1],[2,2,3,4,4] 。它们都需要 4 次操作。
次优解是将数组变成比方说 [6,7,8,9,10] ,因为需要 5 次操作。
显然我们无法使用少于 4 次操作将数组变成 K 递增的。

示例 2:

输入:arr = [4,1,5,2,6,2], k = 2
输出:0
解释:
这是题目描述中的例子。
对于每个满足 2 <= i <= 5 的下标 i ,有 arr[i-2] <= arr[i] 。
由于给定数组已经是 K 递增的,我们不需要进行任何操作。

示例 3:

输入:arr =[12,6,12,6,14,2,13,17,3,8,11,7,4,11,18,8,8,3], k = 1
输出:12

2.解题思路

  • 找出每个子数组的最长上升子序列
  • 然后加上长度 - 最长上升子序列即可
  • 问题转化为求多个数组的最长子序列问题
    • 动态规划,O(n²)会超时
    • 只能用贪心 + 二分, O(nlogn);

3.代码

class Solution {
public:
int addNum(vector<int> &nums)			//直接用dp求,超时
{
	int n = nums.size();
	vector<int> dp(n, 1);
	int res = 1;
	for (int i = 1; i < n; ++i)
	{
		for (int j = 0; j < i; ++j)
		{
			if (nums[i] >= nums[j])
				dp[i] = max(dp[i], dp[j] + 1);
		}
		res = max(res, dp[i]);
	}
	return n - res;
}

int kIncreasing(vector<int>& arr, int k)
{
	int n = arr.size();
	int res = 0;
	for (int i = 0; i < k; ++i)
	{
		vector<int> temp;
		for (int j = i; j < n; j += k)
		{
			temp.push_back(arr[j]);
		}
		res += addNum(temp);
	}

	return res;
}
};

//优化版本
class Solution {
public:
int addNum(vector<int> &nums)	//利用贪心和二分,降低时间复杂度
{
    int n = nums.size();
    vector<int> LIT;			//维护一个最长上升子序列的数组,改数组为递增
    for(const auto num : nums)
    {
        auto it = upper_bound(LIT.begin(),LIT.end(),num);		//每次都在递增的数组中,找到第一个比当前值小的元素.因
        if(it == LIT.end())
            LIT.push_back(num);									//如果没有,说明他就是最大的,加到后面
        else
            *it = num;											//找到了就替换,小的价值更大.虽然出来的子序列不一定是对的,但是长度一定是对的
    }
    
    return n - LIT.size();										//返回修改的次数
}

int kIncreasing(vector<int>& arr, int k)
{
	int n = arr.size();
	int res = 0;
	for (int i = 0; i < k; ++i)
	{
		vector<int> temp;			//变成多个子数组
		for (int j = i; j < n; j += k)
		{
			temp.push_back(arr[j]);			
		}
		res += addNum(temp);
	}

	return res;
}
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

公仔面i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值