备战复试,每日三题Day04

备战复试,每日三题

题目一:买卖股票的最佳时间

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:

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

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

提示:

1 <= prices.length <= 105
0 <= prices[i] <= 104

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock

class Solution {
public:
/*
         动态规划问题:
        dp[i][j]:表示在第i天持有的现金,i表示天数,j表示状态(0代表未持有股票,1代表持有股票)
        basecase:第一天,若未持有股票,则手中现金为0,若持有则花了当天股票的价钱买入了股票(所以为负值)
        状态转移方程:当天手中持有的现金与是否持有股票以及前一天是否持有股票有关:
               即若今天未持有股票,则可能是昨天也未持有股票,或是昨天持有但今天卖了,那今天的最大收益就是比较这两种情况的最大值。
               若今天持有股票,则可能昨天未持有今天刚买入,也可能昨天持有,今天未卖出,那今天的最大收益就是比较这两种情况的最大值。
        最后一天一定是未持有的状态收益大。
        
    */
    int maxProfit(vector<int>& prices) {
        int len=prices.size();
        int dp[len][2];//dp数组
        if(len<2){
            return 0;
        }
        // basecase
        dp[0][0]=0;
        dp[0][1]=-prices[0];
        for(int i=1;i<len;i++){
            //状态转移方程
            // 即若今天未持有股票,则可能是昨天也未持有股票,或是昨天持有但今天卖了,那今天的最大收益就是比较这两种情况的最大值。
            dp[i][0]=fmax(dp[i-1][1]+prices[i],dp[i-1][0]); //C++中用fmax,fmin求两个数之间的最大最小值
            // 若今天持有股票,则可能昨天未持有今天刚买入,也可能昨天持有,今天未卖出,那今天的最大收益就是比较这两种情况的最大值。
            dp[i][1]=fmax(-prices[i],dp[i-1][1]);
        }
        // 最后一天一定是未持有的状态收益大
        return dp[len-1][0];

    }
};

这是一道动态规划的题目,动态规划的步骤一般是确定dp数组,起始状态以及状态转移方程。

题目二: 无重复元素的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:

输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:

输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
示例 4:

输入: s = “”
输出: 0

提示:

0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int num[128]={};//num数组用来记录字符出现的次数
        int i=0,j=0,res=0,k=0,h=0;
        while(j<s.length()){
            //从字符串s的第一个元素开始,以该字符与空字符的ASCII差值作为num数组的下标
            k=s[j++]-' ';
            //num数组中存储的元素表示该字符已出现的次数
            num[k]++;
            //当次数大于1时,表明出现当前子串中出现重复元素
            while(num[k]>1){
                //缩短该子串
                h=s[i++]-' ';
                //对应字符出现次数-1
                num[h]--;
            }
            //记录不含重复元素子串的最大长度
            res=fmax(res,j-i);
        }
        return res;
    }
};

题目三: 两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:

输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:

输入:head = []
输出:[]
示例 3:

输入:head = [1]
输出:[1]

提示:

链表中节点的数目在范围 [0, 100] 内
0 <= Node.val <= 100

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/swap-nodes-in-pairs

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head==nullptr||head->next==nullptr){
            return head;
        }
        //以下讨论至少有两个节点的情况
        ListNode *p=head,*q=head->next,*r=q->next;
        //因为至少有两个节点,所以前两个节点一定发生了互换,则交换后链表头节点为q所指向的节点
        head=q;
        //当r不为空时,交换p,q所指向的节点
        while(r!=nullptr){
            q->next=p;
            p->next=r;
            //因为是两两交换,所以还剩一个节点时就不用再交换,退出循环
            if(r->next==nullptr){
                break;
            }
            //若剩余节点大于1,则必发生两两交换,所以将p的next指向交换后的下一个节点
            p->next=r->next;
            // 将p,q指向将要互换的两个节点,为下一轮交换作准备
            p=r;
            q=r->next;
            r=q->next;
        }
        //此时退出循环有两种情况,①剩余一个节点②剩余两个节点,可用以下过程统一处理
        p->next=r;
        q->next=p;
        return head;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值