Leetcode解题记录系列(2)

Leetcode解题记录系列(2)

121、买卖股票的最佳时机

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

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

暴力解法:首先定义一个变量代表我们的最大利润 maxprofit。
然后通过第一次循环,获取股票第一天到倒数第二天的价格。
因为如果最后一天买入股票就无法在未来的日子卖出,收益就为0,所以第一次循环的长度是prices.length - 1;在今日,我们在进行循环,来获取我们今日后的股票价格。
让两天的价格做减法,获取我们在这天出售股票的利润profit。
把profit和maxprofit进行比较,取最大值赋值给maxprofit;
C++代码:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int max_Profit=0;
        int currentProfit=0;
        if(prices.size()==0||prices.size()==1){
            return 0;
        }
        for(int i=0;i<prices.size()-1;i++){
            for(int j=i+1;j<prices.size();j++){
                currentProfit=prices[j]-prices[i];//目前利润
                if(currentProfit>max_Profit){//与最大利润作对比
                    max_Profit=currentProfit;
                }
            }
        }
        return max_Profit;
    }
};

但是这种暴力解法明显时间复杂度过大(O(n^2)),在leetcode上也难以满足时间要求
**改进:**尝试用一次遍历满足要求:
首先我们定义一个变量来代表股票的最小价格minprice,
然后再定义一个变量代表我们获取到的最大利润maxprofit。
通过循环,我们来获取每天的股票价格。
在当天的时候,比较我们的当日的价格和我们的最小价格的大小。
如果我们的当日价格小于我们已知的最小价格,我们就把当日的价格赋值给minprice
如果当日的价格,不小于我们的最小价格,我们就去判断当日卖出股票的利润(当日价格减去最小
价格)是否大于我们已知的最大利润maxprofit。
如果大于,我们就把当日的利润赋值给maxprofit,否则我们就进入下次循环。待循环完毕后,我
们就获取到了最大的利润

代码如下:

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int minPrice=10001;
        int max_Profit=0;
        int currentProfit=0;
        if(prices.size()==0||prices.size()==1){
            return 0;
        }
        for(int i=0;i<prices.size();i++){
            if(prices[i]<minPrice){
                minPrice=prices[i];
            }else{
                currentProfit=prices[i]-minPrice;
                if(currentProfit>max_Profit){
                    max_Profit=currentProfit;
                }
            }
        }
        return max_Profit;
    }
};

可以通过leetcode的测试

206、反转链表

题目描述: 定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
解法分析:分为迭代法和递归法
迭代法
一次遍历即可实现:首先要定义链表节点指针prev指向前一个节点,curr指针指向目前正在操作的指针,next指针指向下一个要操作的指针;
每一个循环内需要完成的工作:
1、让curr->next=next;
2、移动prev=curr;
3、移动curr=next;
4、移动next=curr->next
代码:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head==nullptr){
            return head;
        }
        ListNode* prev=nullptr;
        ListNode* curr=head;
        ListNode* next=curr->next;
        while(curr){
            next=curr->next;
            curr->next=prev;
            prev=curr;
            curr=next;   
        }
        return prev;
    }
};

递归方法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (head == NULL || head->next == NULL) {
            return head;
        }//如果找到末尾最后一个元素,就返回
        ListNode* ret = reverseList(head->next);
        head->next->next = head;
        head->next = NULL;
        return ret;
    }
};//返回到了第一个元素后,就会直接返回最后一个元素的指针

递归方法有些难度。。

27、合并两个有序链表

题目描述: 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
基本思想 设置两个指针依次对链表进行搜索,并比较大小,让小的放进res
代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* res=new ListNode(0);
        ListNode*sign=res;
        ListNode* sign1=l1;
        ListNode* sign2=l2;
        for(int i=0;sign1!=nullptr&&sign2!=nullptr;i++){
            if(sign1->val<=sign2->val){
                sign->next=sign1;
                sign=sign->next;
                sign1=sign1->next;
            }
           else{
                sign->next=sign2;
                sign=sign->next;
                sign2=sign2->next;
            }
        }
        if(sign1==nullptr){
            sign->next=sign2;
            return res->next;
        }else{
            sign->next=sign1;
            return res->next;
        }
    }
};

代码写得可能有些啰嗦了。。想要简洁的可以用?:表达式,具体代码如下:

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode*res = new ListNode(0);
        ListNode* sign = res;
        for (;l1 != NULL && l2 != NULL; sign = sign->next , l1->val <= l2->val ? l1 = l1->next : l2 = l2->next) {
            sign->next = l1->val <= l2->val ? l1 : l2;
        }
        sign->next = l1 == NULL ? l2 : l1;
        return res->next;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值