非科班选手的刷题学习记录Day3

目录

1. 扑克牌顺子

2. 圆圈剩下的数字

3. 股票的最大利润

4. 不用+做加法


今天还是继续刷剑指~

1. 扑克牌顺子

剑指 Offer 61. 扑克牌中的顺子

难度简单229

若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。

示例 1:

输入: [1,2,3,4,5]
输出: True

示例 2:

输入: [0,0,1,2,5]
输出: True

限制:

数组长度为 5

数组的数取值为 [0, 13] .

写着写着思路就清晰的模拟题。

可以判定不是顺子:除王外有重复元素,最大值和最小值相差超过4

可以判定是顺子:有4/5个王,除了不是顺子的情况

class Solution {

public:

    bool isStraight(vector<int>& nums) {

        int count = 0;

        int minVal = INT_MAX;

        int maxVal = INT_MIN; 

        unordered_set<int> set;

        for(int i = 0; i < nums.size(); i++){

            if(nums[i] == 0){

                count++;

            }

            else{

                if(set.count(nums[i])){

                    return false;//不能有非0元素重复

                }

                set.insert(nums[i]);

                minVal = min(minVal,nums[i]);

                maxVal = max(maxVal,nums[i]);

            }

            if(count == 4){//四个大王已经可以保证是顺子

                return true;

            }

        }

        if(maxVal - minVal > 4){//最大值和最小值相差不能超过4否则无法构成顺子

            return false;

        }

        return true;

    }

};

2. 圆圈剩下的数字

剑指 Offer 62. 圆圈中最后剩下的数字

难度简单597

0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。

例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

示例 1:

输入: n = 5, m = 3
输出: 3

示例 2:

输入: n = 10, m = 17
输出: 2

限制:

  • 1 <= n <= 10^5
  • 1 <= m <= 10^6

约瑟夫环问题。挣扎着试图模拟,失败,看了题解才发现可以递归。

长度为n的序列,先删除第m%n个元素,剩下的是一个长度为n-1的序列,问题就转化为在长度n-1的序列中最后剩下的数字。

然而怎么从n-1剩下的数字下标转化到n剩下的数字下标,我看了一会推导才明白...

设f(n,m)=y,表示在长度为n的序列中,每次删除第m个数字(下标为(m-1)%n),最后剩下的数字的下标为y。

设f(n-1,m)=x,表示在长度为n-1的序列中,每次删除第m个数字,最后剩下的数字的下标为x。

在长度为n的序列中删除后,往后数x+1个,就到达长度为n-1的序列中剩下的数字,这个数字在原序列中的下标为((m-1)%n+(x+1))%n=(m+x)%n.

class Solution {

    int f(int n, int m) {

        if (n == 1) {

            return 0;

        }

        int x = f(n - 1, m);

        return (m + x) % n;

    }

public:

    int lastRemaining(int n, int m) {

        return f(n, m);

    }

};

3. 股票的最大利润

剑指 Offer 63. 股票的最大利润

假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?

示例 1:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。

示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

限制:

0 <= 数组长度 <= 10^5

这道题之前跟着代码随想录做过,再复习一下动态规划的基本步骤:

1.确定dp数组和下标的含义:dp[i]表示到第i天能获得的最大利润

2.确定递推公式:截至第i天能获得的最大利润=截至前一天能获得的最大利润和第i天的利润取最大值

3.初始化dp数组:第一天利润为0

4.确定遍历顺序:因为第i天的利润要从第i-1天推出,从前往后

5.举例推导dp数组

class Solution {

public:

    int maxProfit(vector<int>& prices) {

        if(prices.empty()){

            return 0;

        }

        vector<int> dp(prices.size());//1.dp[i]到第i天能获得的最大利润

        int minPrice = prices[0];//到当前位置的最小价格

        dp[0] = 0;

        for(int i = 1;i < prices.size(); i++){

            minPrice = min(minPrice,prices[i]);//更新到当天为止的最小价格

            dp[i] = max(dp[i - 1],prices[i] - minPrice);//2.第i天的最大利润=max(到前一天的最大利润,今天卖出的利润)

        }

        return dp.back();

    } 

};

4. 不用+做加法

剑指 Offer 65. 不用加减乘除做加法

写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

示例:

输入: a = 1, b = 1
输出: 2

提示:

  • ab 均可能是负数或 0
  • 结果不会溢出 32 位整数

前几天刚接触过位运算,记住了两个比较常用的结论:

a&b:a+b的进位

a^b:a+b(无进位)

每一位的结果包括本位和、进位两个部分,本位和就是上面的无进位和,用异或实现,进位是低位向当前位的进位,用与实现。

class Solution {

public:

    int add(int a, int b) {

        while(b){//直到不再向前产生进位

            int sum = a ^ b;//本位和+上一位产生的进位

            b = (unsigned int)(a & b) << 1;//a+b在当前位产生的进位//*负数移位需要转换成unsigned int

            a = sum;

        }

        return a;

    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值