leetcode刷题记录36(2023-5-19)【H指数(数组、排序) | 分发糖果(贪心) | 最后一个单词的长度(小模拟) | 反转字符串中的单词(小模拟)】

274. H 指数

给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。

根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。

示例 1:

输入:citations = [3,0,6,1,5]
输出:3
解释:给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 3, 0, 6, 1, 5 次。
由于研究者有 3 篇论文每篇 至少 被引用了 3 次,其余两篇论文每篇被引用 不多于 3 次,所以她的 h 指数是 3。

示例 2:

输入:citations = [1,3,1]
输出:1

提示:

n == citations.length
1 <= n <= 5000
0 <= citations[i] <= 1000

主要思路就是对数组进行一个排序,然后从前往后进行遍历,判断引用数是否大于等于剩余文章数,如果是,就结束for循环,并返回结果。

class Solution
{
public:
    int hIndex(vector<int> &citations)
    {
        sort(citations.begin(), citations.end());
        int h_index = citations.size();
        for (int i = 0; i < citations.size(); i++)
        {
            h_index = citations.size() - i;
            if (citations[i] >= h_index)
            {
                return h_index;
            }
        }
        return 0;
    }
};

135. 分发糖果

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

每个孩子至少分配到 1 个糖果。
相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例 1:

输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。
示例 2:

输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。

提示:

n == ratings.length
1 < = n < = 2 ∗ 1 0 4 1 <= n <= 2 * 10^4 1<=n<=2104
0 < = r a t i n g s [ i ] < = 2 ∗ 1 0 4 0 <= ratings[i] <= 2 * 10^4 0<=ratings[i]<=2104

主要思路是:
① 首先给每个孩子分一个糖果。
② 按照得分值,对数组索引进行一个排序。
③ 从得分最低的孩子开始遍历,它的左相邻节点和右相邻节点应该都要满足条件2,利用这种局部性原理,进行扩散,按照步骤②中索引顺序遍历数组,最终得到总共需要的糖果数量。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 定义一个比较函数,根据原始vector的值来比较索引
bool compare(const std::pair<int, int> &a, const std::pair<int, int> &b)
{
    return a.second < b.second;
}

std::vector<int> get_sorted_indices(const std::vector<int> &vec)
{
    // 创建一个包含索引及其对应值的pair数组
    std::vector<std::pair<int, int>> indexed_vec(vec.size());
    for (size_t i = 0; i < vec.size(); ++i)
    {
        indexed_vec[i] = std::make_pair(i, vec[i]);
    }

    // 根据pair的值部分进行排序
    std::sort(indexed_vec.begin(), indexed_vec.end(), compare);

    // 提取排序后的索引
    std::vector<int> sorted_indices(vec.size());
    for (size_t i = 0; i < indexed_vec.size(); ++i)
    {
        sorted_indices[i] = indexed_vec[i].first;
    }

    return sorted_indices;
}

class Solution
{
public:
    int candy(vector<int> &ratings)
    {
        int numAllCandy = ratings.size();
        vector<int> numCandyEyeryone(ratings.size(), 1);
        vector<int> sortIndex = get_sorted_indices(ratings);
        for (int i = 0; i < sortIndex.size(); i++)
        {
            if ((sortIndex[i] - 1 >= 0 && ratings[sortIndex[i] - 1] > ratings[sortIndex[i]]))
            {
                if (numCandyEyeryone[sortIndex[i] - 1] <= numCandyEyeryone[sortIndex[i]])
                {
                    numAllCandy += (numCandyEyeryone[sortIndex[i]] + 1) - numCandyEyeryone[sortIndex[i] - 1];
                    numCandyEyeryone[sortIndex[i] - 1] = numCandyEyeryone[sortIndex[i]] + 1;
                }
            }
            if ((sortIndex[i] + 1 < ratings.size() && ratings[sortIndex[i] + 1] > ratings[sortIndex[i]]))
            {
                
                if (numCandyEyeryone[sortIndex[i] + 1] <= numCandyEyeryone[sortIndex[i]])
                {
                    numAllCandy += (numCandyEyeryone[sortIndex[i]] + 1) - numCandyEyeryone[sortIndex[i] + 1];
                    numCandyEyeryone[sortIndex[i] + 1] = numCandyEyeryone[sortIndex[i]] + 1;
                }
            }
        }
        return numAllCandy;
    }
};

int main()
{
    vector<int> vec = {1, 3, 4};
    Solution sol;
    int res = sol.candy(vec);
    cout << res << endl;
    return 0;
}

58. 最后一个单词的长度

给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。

单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。

示例 1:

输入:s = “Hello World”
输出:5
解释:最后一个单词是“World”,长度为 5。

示例 2:

输入:s = " fly me to the moon "
输出:4
解释:最后一个单词是“moon”,长度为 4。

示例 3:

输入:s = “luffy is still joyboy”
输出:6
解释:最后一个单词是长度为 6 的“joyboy”。

提示:

1 < = s . l e n g t h < = 1 0 4 1 <= s.length <= 10^4 1<=s.length<=104
s 仅有英文字母和空格 ’ ’ 组成
s 中至少存在一个单词

#include <string>
#include <iostream>

using namespace std;

class Solution
{
public:
    int lengthOfLastWord(string s)
    {
        int i;
        for (i = s.size() - 1; i >= 0; i--)
        {
            if (s[i] != ' ')
            {
                break;
            }
        }
        int numChar = 0;
        for (; i >= 0; i--)
        {
            if (s[i] == ' ')
            {
                break;
            }
            else
            {
                numChar++;
            }
        }
        return numChar;
    }
};

int main()
{
    string s = "this is a Model  ";
    Solution sol;
    int res = sol.lengthOfLastWord(s);
    cout << res << endl;
    return 0;
}

151. 反转字符串中的单词

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:

输入:s = “the sky is blue”
输出:“blue is sky the”

示例 2:

输入:s = " hello world "
输出:“world hello”
解释:反转后的字符串中不能存在前导空格和尾随空格。

示例 3:

输入:s = “a good example”
输出:“example good a”
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。

提示:

1 <= s.length <= 104
s 包含英文大小写字母、数字和空格 ’ ’
s 中 至少存在一个 单词

从后向前遍历字符串,遍历完一个单词以后,正序插入到新的字符串中来:

#include <string>
#include <iostream>

using namespace std;

class Solution
{
public:
    string reverseWords(string s)
    {
        int len = s.size();
        string res(len, ' ');
        int idx = 0;
        for (int i = len - 1; i >= 0; i--)
        {
            while (i >= 0 && s[i] != ' ')
            {
                i--;
            }
            for (int j = i + 1; j < len && s[j] != ' '; j++)
            {
                if (idx > 0 && j == i + 1)
                {
                    idx++;
                }
                res[idx] = s[j];
                idx++;
            }
        }
        res = res.substr(0, idx);
        return res;
    }
};

int main()
{
    string s = "  hello world  ";
    Solution sol;
    string res = sol.reverseWords(s);
    cout << res << endl;
}

进阶:如果字符串在你使用的编程语言中是一种可变数据类型,请尝试使用 O(1) 额外空间复杂度的 原地 解法。

空间复杂度为O(1)的原地解法:https://leetcode.cn/problems/reverse-words-in-a-string/solutions/194450/fan-zhuan-zi-fu-chuan-li-de-dan-ci-by-leetcode-sol/?envType=study-plan-v2&envId=top-interview-150

class Solution {
public:
    string reverseWords(string s) {
        // 反转整个字符串
        reverse(s.begin(), s.end());

        int n = s.size();
        int idx = 0;
        for (int start = 0; start < n; ++start) {
            if (s[start] != ' ') {
                // 填一个空白字符然后将idx移动到下一个单词的开头位置
                if (idx != 0) s[idx++] = ' ';

                // 循环遍历至单词的末尾
                int end = start;
                while (end < n && s[end] != ' ') s[idx++] = s[end++];

                // 反转整个单词
                reverse(s.begin() + idx - (end - start), s.begin() + idx);

                // 更新start,去找下一个单词
                start = end;
            }
        }
        s.erase(s.begin() + idx, s.end());
        return s;
    }
};
  • 17
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Cherries Man

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

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

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

打赏作者

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

抵扣说明:

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

余额充值