力扣爆刷第171天之TOP200五连刷121-125(跳跃游戏、买卖股票、旋转链表)

力扣爆刷第171天之TOP200五连刷121-125(跳跃游戏、买卖股票、旋转链表)

文章目录

一、55. 跳跃游戏

题目链接:https://leetcode.cn/problems/jump-game/description/

思路:所谓跳跃游戏指的是,每次根据数组中元素的值来确定接下来要走的步数,看看能否走到数组尾部。本质上来说就是维护一个右边界,检测是否超出了右边界,超出了就不可抵达。维护的右边界需要不断更新。

java 复制代码
class Solution {
    public boolean canJump(int[] nums) {
        int max = nums[0];
        for(int i = 1; i < nums.length; i++) {
            if(i > max) return false;
            if(i+nums[i] > max) max = i + nums[i]; 
        }
        return true;
    }
}

二、123. 买卖股票的最佳时机 III

题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/description/

思路:经典的买卖股票问题,最多买卖两次,不能同时购入,问最多可剩余多少钱。

1、首先分辨本题是一个动态规划题,动态规划本身就是状态与选择。

2、对于这个问题,每一天都有两种状态,即持有股票与不持有股票,而持有股票又分为:之前就已经持有了,和今天才持有。而不持有股票又分为:之前就不持有了,和今天才刚不持有。

3、所以我们可以为每一天定义两种操作,即持有与不持有,分别计算最大值。

java 复制代码
class Solution {
    public int maxProfit(int[] prices) {
        int[] dp = new int[4];
        dp[0] = -prices[0];
        dp[2] = -prices[0];
        for(int i = 1; i < prices.length; i++) {
            dp[0] = Math.max(dp[0], -prices[i]);
            dp[1] = Math.max(dp[1], dp[0] + prices[i]);
            dp[2] = Math.max(dp[2], dp[1] - prices[i]);
            dp[3] = Math.max(dp[3], dp[2] + prices[i]);
        }
        return dp[3];
    }
}

三、排序奇升偶降链表

题目链接:https://mp.weixin.qq.com/s/0WVa2wIAeG0nYnVndZiEXQ

思路:本题让把一个链表,奇数升序,偶数降序的链表,给进行排序,返回一个升序链表。其实不难。一共三步。

1、把链表按照奇数和偶数拆分为一个升序链表和一个降序链表。

2、把降序链表进行翻转,得到升序链表。

3、把两个升序链表进行归并排序。

java 复制代码
public ListNode sortList(ListNode root) {
        ListNode head1 = new ListNode();
        ListNode head2 = new ListNode();
        // 1、按照奇数和偶数进行拆分
        ListNode p = root, p1 = head1, p2 = head2;
        while (p != null) {
            p1.next = p;
            p = p.next;
            p1 = p1.next;
            p1.next = null;
            if(p != null) {
                p2.next = p;
                p = p.next;
                p2 = p2.next;
                p2.next = null;
            }
        }
        // 2、翻转偶数对应的降序序列
        p2 = head2.next;
        ListNode pro = null;
        head2.next = null;
        while(p2 != null) {
            pro = p2.next;
            p2.next = head2.next;
            head2.next = p2;
            p2 = pro;
        }
        // 3、归并两个升序链表
        p1 = head1.next;
        p2 = head2.next;
        ListNode head = new ListNode();
        p = head;
        while(p1 != null && p2 != null) {
            if(p1.val < p2.val) {
                p.next = p1;
                p1 = p1.next;
            }else{
                p.next = p2;
                p2 = p2.next;
            }
            p = p.next;
        }
        if(p1 != null) p.next = p1;
        if(p2 != null) p.next = p2;
        return head.next;
    }

四、61. 旋转链表

题目链接:https://leetcode.cn/problems/rotate-list/description/

思路:给一个链表和一个数字k,要求把链表向右自动k位,超出部分自动移到链表首部,其实很简单。

1、首先要处理的是k,需要把k限制在链表的总长度之内,可以先遍历一遍链表,然后把k对总长度进行取余,如果为0就不用旋转了,可以直接返回。

2、这样就好办了,只需要使用快慢指针,快指针先走k步,然后快慢指针同步向右走,当快指针抵达结尾处,慢指针指向的位置就是倒数第K个节点。

3、然后从慢指针位置截断,把右边的链表拼接到头结点上即可。

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || head.next == null) return head;
        // 1、对K进行取余,使得旋转位数小于总长度
        int count = 0;
        ListNode p = head;
        while(p != null) {
            count++;
            p = p.next;
        }
        k = k % count;
        if(k == 0) return head;
        // 2、快慢指针,定位到倒数第k个位置
        ListNode slow = head, fast = head;
        for(int i = 0; i < k; i++) {
            fast = fast.next;
        }
        while(fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        p = slow.next;
        slow.next = null;
        fast.next = head;
        return p;
    }
}

五、7. 整数反转

题目链接:https://leetcode.cn/problems/reverse-integer/description/

思路:整数翻转也属于经典题目了,只需要每次取余得到的余数作为新数的基数,然后每次对基数乘10左移,对原数除10截短,期间判断是否超限。

java 复制代码
class Solution {
    public int reverse(int x) {
        int res = 0, min = Integer.MIN_VALUE / 10, max = Integer.MAX_VALUE / 10;
        int a = Integer.MIN_VALUE % 10, b = Integer.MAX_VALUE % 10;
        while(x != 0) {
            int temp = x % 10;
            if(res < min || (res == min && temp < a)) return 0;
            if(res > max || (res == max && temp > b)) return 0;
            res = res * 10 + temp;
            x = x / 10;
        }
        return res;
    }
}
相关推荐
L小航呀1 小时前
代码随想录刷题 Day16
leetcode·面试
软行1 小时前
LeetCode 每日一题 3876. 构造奇偶一致的数组 II
c++·算法·leetcode
我不会起名字3222 小时前
一天一道算法题(29):单调栈
java·数据结构·python·算法·leetcode·golang·单调栈
苦瓜小生2 小时前
【前端】【力扣与手撕】十天带你刷完前端算法与手撕,全是最简单好记的最优解法!day4
前端·数据结构·算法·leetcode·面试
圣保罗的大教堂3 小时前
leetcode 2029. 石子游戏 IX 中等
leetcode
沧沧凉凉3 小时前
两个小时,AI 把我 2018 年那个 Unity 版保卫萝卜搬进了浏览器
前端·游戏·ai编程
sylviiiiiia4 小时前
leetcode hot100
python·算法·leetcode
Nil2085 小时前
leetcode 46全排列
算法·leetcode·职场和发展
辰烨chenye5 小时前
LeetCode Hot 100 题解 · 动态规划篇
算法·leetcode·动态规划
青山木5 小时前
Hot 100 --- 买卖股票的最佳时机
java·数据结构·算法·leetcode·贪心算法