Leetcode Day 3 打卡

Day 3

Leetcode 414.第三大的数

sort等内置排序函数的时间复杂度通常为O(nlongn).因此想要O(n)的复杂度就不能对整个数组进行排序。

C++中

  • #include <unordered_set>中的的unordered_set<int>集合可以用于去重。
  • 使用 std::sort (默认升序)结合仿函数 std::greater<int>() 可进行降序排序。如std::sort(numsNoRepeat.begin(), numsNoRepeat.end(), std::greater<int>());
  • #include <climits>中的INT_MIN表示 int 类型的最小可能值。这个值通常是 -2147483648(在大多数32位和64位系统上),对应于二进制补码表示的最小整数值。 常被用作初始值来查找最大值,因为任何有效的整数都会比 INT_MIN 大。
  • size_t:无符号整数,安全,防止负值错误
    • 表示内存大小:当你需要表示一个对象的大小(比如通过 sizeof 操作符获得的结果)时,size_t 是返回类型。
    • 数组索引:在数组操作中,size_t 常用于表示数组的索引,因为它保证是非负的。
    • 内存分配:在使用动态内存分配函数(如 malloc)时,size_t 被用来表示要分配的字节数。
#include <vector>
#include <unordered_set>
#include <algorithm>

class Solution {
public:
    int thirdMax(std::vector<int>& nums) {
        std::unordered_set<int> uniqueNums(nums.begin(), nums.end());
        std::vector<int> numsNoRepeat(uniqueNums.begin(), uniqueNums.end());
        
        if (numsNoRepeat.size() < 3) {
            int max = INT_MIN;
            for (int num : nums) {
                max = std::max(max, num);
            }
            return max;
        }
        
        std::sort(numsNoRepeat.begin(), numsNoRepeat.gegin()+3, std::greater<int>());
        int first = numsNoRepeat[0];
        int second = numsNoRepeat[1];
        int third = numsNoRepeat[2];
        
        for (size_t i = 3; i < numsNoRepeat.size(); ++i) {
            int num = numsNoRepeat[i];
            if (num > first) {
                third = second;
                second = first;
                first = num;
            } else if (second < num && num < first) {
                third = second;
                second = num;
            } else if (third < num && num < second) {
                third = num;
            }
        }
        return third;
    }
};

Python中

  • set()函数可用于去重
  • sorted()函数可用于排序。且与列表的 sort() 方法不同,sorted() 不会对原始列表进行修改,而是返回一个新的排序后的列表。
class Solution:
    def thirdMax(self, nums: List[int]) -> int:
        nums_no_repeat = list(set(nums))# 使用set()去除重复元素
        if len(nums_no_repeat) < 3:     # 若去重后的列表长度小于3,返回最大元素
            return max(nums)
        # 找到去重列表前三个数中的第一、第二、第三大的数
        first, second, third = sorted(nums_no_repeat[0:3], reverse = 1)
        for num in nums_no_repeat[3:]:  # 从第四位开始,遍历去重列表
            if num > first:             # 若num大于第一大的数,则:
                third = second          # 修改第三大的数为原来第二大的数
                second = first          # 修改第二大的数为原来第一大的数
                first = num             # 修改第一大的数为num
            elif second < num < first:  # 若num位于第一大的数和第二大的数之间,则:
                third = second          # 修改第三大的数为原来第二大的数
                second = num            # 修改第二大的数为num
            elif third < num < second:  # 若num位于第二大的数和第三大的数之间,则:
                third = num             # 修改第三大的数为num
        return third    # 遍历结束,返回第三大的数

Leetcode 1518. 换水问题

模拟方法

记一开始有 b 瓶水,e 个空瓶换一瓶水。

两种迭代思路:

  • 首先我们一定可以喝到 b 瓶酒,剩下 b 个空瓶。接下来我们可以拿瓶子换酒,每次拿出 e 个瓶子换一瓶酒,然后再喝完这瓶酒,得到一个空瓶。以此类推,我们可以统计得到答案。
class Solution {
public:
    int numWaterBottles(int numBottles, int numExchange) {
        int bottle = numBottles, ans = numBottles;
        while (bottle >= numExchange) {
            bottle -= numExchange;
            ++ans;
            ++bottle;
        }
        return ans;
    }
};
  • 首先我们一定可以喝到 b 瓶酒,剩下 b 个空瓶。接下来每次拿出所有能换的瓶子换n瓶水,以此类推。

    class Solution:
        def numWaterBottles(self, numBottles: int, numExchange: int) -> int:
            # 初始化条件
            emp_bottle = numBottles
            ans = numBottles
            while(emp_bottle >= numExchange):
                n = emp_bottle // numExchange # 每换一次多喝到的瓶数
                ans += n 
                emp_bottle = n + (emp_bottle%numExchange) # 换完并喝完后剩余的总空瓶数
            return ans
    

Leetcode 877. 石子游戏

这道题是「486. 预测赢家」的特例。和第 486 题相比,这道题增加了两个限制条件:

  • 数组的长度是偶数;
  • 数组的元素之和是奇数,所以没有平局。

还没学动态规划前,掌握数学解法即可。

数学解法思路:有偶数堆石子,可以将石子堆分为奇数堆和偶数堆,经过几次模拟可以发现,作为先手方总可以只取奇数堆或者偶数堆,那么只需要先计算好奇数堆还是偶数堆的总和大,那么取对应的那组即可。因此先手必胜。

fig1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值