leetcode top100 - 02

2. 两数相加

  1. 转换成数字进行运算,最后转换成链表。可能会出现溢出的情况。
    因为无论是int还是long类型表达的数字长度是有限的,而链表的长度是可以无限追加的。
  2. 解释是干扰你的,其实就是依次从低位到高位的进位过程

笔试思路

把链表依次填充到数组中,数组容易操作,然后逐位进行加法运算;

面试思路

使用链表的思路去解决。

  1. 注意考虑 链表长度不一样的情况,短链表需要一直陪跑,补充0。
    只要有一个不为空,则……
    while(l1 != null || l2 != null){

    }

  2. 最后一位可能出现进位,需要补1

  3. n%10,n/10的玩法

  • 扩展
  1. 队列和栈的常用方法巧记

    压栈弹栈,入队拉出队

    栈的常用方法:
    push:推入,类似于“扑通”声。
    pop:弹出,类似于“砰”的一声。
    peek:窥视,类似于“皮皮”声。
    isEmpty:判断是否为空,类似于“是不是空”的疑问。

    队列的常用方法:
    offer:入队,类似于“哦菲儿”声。
    poll:出队,类似于“咕噜”声。
    peek:查看队首元素,类似于“皮皮”声。
    isEmpty:判断是否为空,类似于“是不是空”的疑问。

    以下是一些将谐音词汇和栈、队列联系起来的方法:

    栈的谐音词汇可以联系到“扑通”声和“砰”的一声,这是因为栈的特点是后进先出,类似于一个物体被推入栈中时发出的声音,以及从栈中弹出物体时发出的声音。

    队列的谐音词汇可以联系到“哦菲儿”和“咕噜”的声音,这是因为队列的特点是先进先出,类似于一个物体被推入队列中时发出的声音,以及从队列中弹出物体时发出的声音。

    栈和队列的 peek 方法可以联系到“皮皮”声,因为这个方法用于查看栈顶或队首的元素,类似于在看一张扑克牌的牌面。

    栈和队列的 isEmpty 方法可以联系到“是不是空”的疑问,因为这个方法用于判断栈或队列是否为空。当栈或队列为空时,就可以想象自己在问“是不是空呢?”这样可以更容易地记忆这个方法。

    通过将谐音词汇和栈、队列联系起来,可以帮助我们更加轻松地记忆栈和队列的常用方法。

  2. 遍历链表的方法优化
    在 while 循环中使用了 l1.next 和 l2.next,导致最后一个节点没有被处理。另外,在对链表进行遍历时,应该使用 while (node != null) 循环,而不是 do-while 循环。

    用while循环来替代do-while循环,这样就不需要判断链表是否为空或者只有一个节点了;

    复制代码
    java
    • 1
    • 2
    • 3
    • 4
    • 5
    // 遍历链表 while (l1 != null) { l1Stack.push(l1.val); l1 = l1.next; }
  3. 把队列数据压进链表的方法优化

    老代码

    复制代码
    java
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    ListNode res = new ListNode(queue1.poll()); ListNode pre = res; while (!queue1.isEmpty()) { ListNode next = new ListNode(queue1.poll()); pre.next = next; pre = next; }

    gpt:

    复制代码
    java
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    ListNode dummy = new ListNode(-1); ListNode cur = dummy; while (!queue1.isEmpty()) { ListNode node = new ListNode(queue1.poll()); cur.next = node; cur = cur.next; } return dummy.next;

    dummy 是一个节点,也称作虚拟节点。它是一个不存储任何实际数据的节点,只是作为辅助节点来帮助构建链表。

    在链表的头部添加节点时,如果直接添加到头节点之前,则需要对头节点进行特殊处理。而使用 dummy 节点可以避免这种特殊处理,只需要将新节点添加到 dummy 节点的 next 上即可。最后返回 dummy 节点的 next,即整个链表的头节点。

    例如,在构建一个单向链表时,可以使用 dummy 节点作为链表的头节点,它不存储任何实际数据,只是作为一个占位符。这样在添加第一个节点时,可以直接将其添加到 dummy 节点的 next 上,而不需要进行特殊处理。

    在链表的删除操作中,有时也可以使用 dummy 节点来简化代码逻辑。例如,如果需要删除链表中所有值为 x 的节点,可以使用 dummy 节点作为头节点,并将其 next 指向原链表的头节点。然后遍历整个链表,对于每个节点,如果其值为 x,则将其从链表中删除。最后返回 dummy 节点的 next,即删除 x 节点后的链表头节点。这种方法可以避免对头节点进行特殊处理。

    bing:
    以下代码可以优化的地方有:

    可以使用一个循环变量cur来代替pre,这样可以避免多余的赋值操作。
    可以在循环中直接使用queue1.poll()方法来获取队列中的元素,而不需要先定义一个next变量。
    可以在循环结束后将cur.next置为null,这样可以避免链表中出现多余的节点。
    优化后的代码如下:

    复制代码
    java
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    ListNode res = new ListNode(queue1.poll()); ListNode cur = res; while (!queue1.isEmpty()) { cur.next = new ListNode(queue1.poll()); cur = cur.next; } cur.next = null;

解法进化周期

1.野蛮期

复制代码
java
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
/** * 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 addTwoNumbers(ListNode l1, ListNode l2) { // 倒序遍历两个列表 Stack<Integer> stack1 = new Stack(); Stack<Integer> stack2 = new Stack(); Stack<Integer> stack3 = new Stack(); StringBuilder sb1 = new StringBuilder(); StringBuilder sb2 = new StringBuilder(); int ans = 0; while(l1.next != null){ stack1.push(l1.val); l1 = l1.next; } while(l2.next != null){ stack2.push(l2.val); l2 = l2.next; } while(stack1.size() > 0){ sb1.append(stack1.pop()); } while(stack2.size() > 0){ sb2.append(stack2.pop()); } ans = Integer.parseInt(sb1.toString()) + Integer.parseInt(sb2.toString()); do{ stack3.push(ans%10); ans = ans/10; }while(ans/10 != 0); ListNode res = new ListNode(); ListNode cur = res; while(stack3.size() > 0){ cur = add(cur, stack3.pop()); } return res; } public ListNode add(ListNode node, int value ){ node.value = value; ListNode node1 = new ListNode(); node.next = node1; return node1; } } ``` ### 2.驯化期(笔试思路) ```java class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ArrayList<Integer> l1List = new ArrayList<>(); ArrayList<Integer> l2List = new ArrayList<>(); while(l1 != null) { l1List.add(l1.val); l1 = l1.next; } while(l2 != null) { l2List.add(l2.val); l2 = l2.next; } // 短数组填充0 int l1l2Difference = l1List.size() - l2List.size(); if(l1l2Difference != 0){ if (l1l2Difference > 0) { // l1为长链表 for (;l1l2Difference > 0; l1l2Difference--){ l2List.add(0); } }else { // l1为短链表 for (;l1l2Difference < 0; l1l2Difference++){ l1List.add(0); } } } // 数值从低位开始加 int length = l1List.size(); ArrayList<Integer> ansList = new ArrayList<>(); int cur = 0; int carry = 0; //进位 for (int i = 0; i < length; i++) { cur = l1List.get(i) + l2List.get(i) + carry; if (cur / 10 > 0){ carry = 1; ansList.add(cur % 10); }else { carry = 0; ansList.add(cur); } } if (carry == 1) { ansList.add(1); } // 数组转换成链表 ListNode head = new ListNode(ansList.get(0)); ListNode curNode = head; for(int i = 1; i < ansList.size(); i++) { curNode.next = new ListNode(ansList.get(i)); // 只关注后面的node,可以避免追加额外的节点 curNode = curNode.next; } return head; } }

3.优雅期(面试思路)

复制代码
java
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { // 结果链表 ListNode dummy = new ListNode(-1); ListNode curNode = dummy; int curNum = 0; int carryTag = 0; int l1val = 0; int l2val = 0; // 对齐链表 只要有一个不为空,则进入循环 **圈重点** while (l1 != null || l2 != null) { l1val = l1 == null ? 0 : l1.val; l2val = l2 == null ? 0 : l2.val; l1 = l1 == null ? new ListNode(0) : l1; l2 = l2 == null ? new ListNode(0) : l2; curNum = l1val + l2val + carryTag; if (curNum / 10 > 0) { curNode.next = new ListNode(curNum % 10); curNode = curNode.next; carryTag = 1; }else { curNode.next = new ListNode(curNum); curNode = curNode.next; carryTag = 0; } // 循环进入下一位判断 l1 = l1.next; l2 = l2.next; } if (carryTag == 1){ curNode.next = new ListNode(1); } // **圈重点** return dummy.next; } } //leetcode submit region end(Prohibit modification and deletion)

本文作者:livebetter

本文链接:https://www.cnblogs.com/livebetter/p/17274849.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   积极向上的徐先生  阅读(19)  评论(0编辑  收藏  举报
评论
收藏
关注
推荐
深色
回顶
展开
点击右上角即可分享
微信分享提示