• 力扣学习计划75题-第二篇


    第三天

    第一题、合并两个有序链表

     思路

    首先碰到链表问题,我们第一时间需要想到链表判空问题,然后在继续写代码,然后我这里采用的是递归的解法,其实合并两个有序链表和合并俩个数组差不多,这么说不知各位看官老爷有没有豁然开朗,因为是链表不用考虑数组扩容的问题,所以我直接是从两个链表的头节点开始比较,然后看谁大谁小,小的就确定位置了,大的值和小的那个值的next的值比较,这样递归下去每个值的位置就确定好了,最后返回最开始的那个头节点。

    代码

    1. public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
    2. if (list1 == null) {
    3. return list2;
    4. }
    5. if (list2 == null) {
    6. return list1;
    7. }
    8. if (list1.val < list2.val) {
    9. list1.next = mergeTwoLists(list1.next, list2);
    10. return list1;
    11. } else {
    12. list2.next = mergeTwoLists(list1, list2.next);
    13. return list2;
    14. }
    15. }

    第二题、反转链表

     思路一

    使用辅助栈求解,因为栈是先进后出的。实现原理就是把链表节点一个个入栈,当全部入栈完之后再一个个出栈,出栈的时候在把出栈的结点串成一个新的链表。

    代码一

    1. public ListNode ReverseList(ListNode head) {
    2. Stack stack= new Stack<>();
    3. //把链表节点全部摘掉放到栈中
    4. while (head != null) {
    5. stack.push(head);
    6. head = head.next;
    7. }
    8. if (stack.isEmpty())
    9. return null;
    10. ListNode node = stack.pop();
    11. ListNode dummy = node;
    12. //栈中的结点全部出栈,然后重新连成一个新的链表
    13. while (!stack.isEmpty()) {
    14. ListNode tempNode = stack.pop();
    15. node.next = tempNode;
    16. node = node.next;
    17. }
    18. //最后一个结点就是反转前的头结点,一定要让他的next等于空,否则会构成环
    19. node.next = null;
    20. return dummy;
    21. }

    思路二

    双链表求解,也就是是把原链表的结点一个个摘掉,每次摘掉的链表都让他成为新的链表的头结点,然后更新新链表。

    1. public ListNode ReverseList(ListNode head) {
    2. //新链表
    3. ListNode newHead = null;
    4. while (head != null) {
    5. //先保存访问的节点的下一个节点,保存起来
    6. ListNode temp = head.next;
    7. //每次访问的原链表节点都会成为新链表的头结点,
    8. head.next = newHead;
    9. //更新链表
    10. newHead = head;
    11. head = temp;
    12. }
    13. return newHead;
    14. }

    第四天

    第一题、链表的中间结点

     思路

    快慢指针,用两个指针 slow 与 fast 一起遍历链表,开始的时候两个指针都指向头节点,slow 一次走一步,fast 一次走两步。那么当 fast 到达链表的末尾时,slow 必然位于中间。

    代码

    1. public ListNode middleNode(ListNode head) {
    2. ListNode fast = head;
    3. ListNode slow = head;
    4. while (fast != null && fast.next != null) {
    5. slow = slow.next;
    6. fast = fast.next.next;
    7. }
    8. return slow;
    9. }

    第二题、环形链表 II

     思路一

    还是快慢指针,看下图

     首先我们知道当两指针相遇就是存在环,然后找环入口那个推导过程我就不说了,这里直接说结论,当两指针相遇后,随便拿一个指针回到头节点,然后两个指针这个时候以相同的速度开始走,再次相遇的时候就是环的入口点。

    代码一

    1. public ListNode detectCycle(ListNode head) {
    2. ListNode fast = head;
    3. ListNode slow = head;
    4. while (true) {
    5. if (fast == null || fast.next == null) {
    6. return null;
    7. }
    8. fast = fast.next.next;
    9. slow = slow.next;
    10. if (fast == slow)
    11. break;
    12. }
    13. fast = head;
    14. while (slow != fast) {
    15. slow = slow.next;
    16. fast = fast.next;
    17. }
    18. return fast;
    19. }

    思路二

    利用哈希的思想,我们遍历链表的节点,把每个节点记录下来,要是后面再次遍历到这个节点那么就说明有环,然后返回这个节点就可以了。

    代码二

    1. public ListNode detectCycle(ListNode head) {
    2. Set set = new HashSet<>();
    3. ListNode cur = head;
    4. while (cur != null) {
    5. if (set.contains(cur)) {
    6. return cur;
    7. }else {
    8. set.add(cur);
    9. }
    10. cur = cur.next;
    11. }
    12. return null;
    13. }

    第五天

    第一题、买卖股票的最佳时机

    思路一

    用 maxprofit 来表示获取的最大利润,用 minprice 记录是历史最低价格,假设股票是在那天买的,然后我们的利润就是price[i] - minprice,所以这个时候我们遍历一次数组就好了。

    代码一

    1. public int maxProfit(int[] prices) {
    2. int minprice = Integer.MAX_VALUE;
    3. int maxprofit = 0;
    4. for(int i : prices){
    5. maxprofit = Math.max(maxprofit, i - minprice);
    6. minprice = Math.min(minprice, i);
    7. }
    8. return maxprofit;
    9. }

    思路二

    直接暴力求解,一个个去试出最大 maxprofit 。

    代码二

    1. public int maxProfit(int[] prices) {
    2. int maxprofit = 0;
    3. for (int i = 0; i < prices.length - 1; i++) {
    4. for (int j = i + 1; j < prices.length; j++) {
    5. int profit = prices[j] - prices[i];
    6. if (profit > maxprofit) {
    7. maxprofit = profit;
    8. }
    9. }
    10. }
    11. return maxprofit;
    12. }

    第二题、最长回文串

    思路

    题本身不难,我就说几个需要注意的地方,首先我这是用数组来求解,因为大写字母加小写字母一共52个,所以我们创建一个容量52的数组来存储字符,然后A-Z,a-z在ASCII码表中不是连着一起的,所以我们后面存数组的时候要分开来存,然后如果某个字母有偶数个,因为偶数有对称性,可以把它全部用来构造回文串;但如果是奇数个的话,并不是完全不可以用来构建,也不是只能选最长的那个,而是只要砍掉1个,剩下的变成偶数就可以全部计入了,而奇数字母里,可以保留1个不砍,把它作为回文串的中心,所以最后还要再加回一个1,但是,如果是没有奇数的情况,这个1也不能随便加,所以还要分情况讨论。我能想到的需要注意的就这些了。

    代码

    1. public int longestPalindrome(String s) {
    2. int[] ch = new int[26 + 26];
    3. for (char ss : s.toCharArray()) {
    4. if (ss >= 'a') {
    5. ch[ss - 'a'] += 1;
    6. } else {
    7. ch[ss - 'A' + 26] += 1;
    8. }
    9. }
    10. int res = 0;
    11. int odd = 0;
    12. for (int cc : ch) {
    13. res += cc;
    14. if (cc % 2 == 1) {
    15. odd += 1;
    16. }
    17. }
    18. return odd == 0 ? res : res - odd + 1;
    19. }

  • 相关阅读:
    2024计算机二级6
    创新无处不在的便利体验——基于智能视频和语音技术的安防监控系统EasyCVR
    洛谷P1763 埃及分数
    不同实验样品在实时荧光定量PCR检测中要求有哪些?
    红包雨中:Redis 和 Lua 的邂逅
    leetcode 21
    javaweb疫苗预约网站源码
    springboot缓存
    关于MAC电脑无法正常登陆H3C iNodes登陆的解决办法
    ansible - Role
  • 原文地址:https://blog.csdn.net/qq_52592775/article/details/126328326