每日三题-两数相加、反转链表、回文链表

简介: 每日三题两数相加反转链表回文链表

两数相加


2b8233ffe7994e6abd520e0e85318144 (1).png

解法一

使用双指针

每次l1、l2指针都向后移动,但是可能存在一个进位然后保存下来

所以当前值每次都是(l1.val+l2.val+进位)%10,而进位值就是(l1.val+l2.val+进位 )/10

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        // 判断一下是否有空的
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        ListNode res = new ListNode(0);
        ListNode temp = res;
        int jin = 0; //进位
        while(l1 != null || l2 != null){
            int add1 = l1 == null?0:l1.val;  // 第一个加数
            int add2 = l2 == null?0:l2.val;  // 第二个加数
            int sum = add1 + add2 + jin; //和
            temp.next = new ListNode(sum%10);
            temp = temp.next;
            jin = sum/10;           
            if(l1 != null) l1 = l1.next;
            if(l2 != null) l2 = l2.next;
        }
        if(jin != 0)temp.next = new ListNode(jin); //最后可能有进位
        return res.next;
    }
}


反转链表


62a10892b34b44daaf1d46e77f1e3cb5.png

解法一

使用双指针

cur指针指向当前节点,pre指向上一个节点,每次ne临时指针指向下一个节点

cur 指向pre,然后pre = cur,cur = ne然后继续循环

因为返回条件是cur != null ,所以返回时候cur是null我们需要返回cur的前一个也就是pre

class Solution {
    public ListNode reverseList(ListNode head) {
        // 如果为空或者只有一个节点
        if(head  == null || head.next == null)return head;
        ListNode pre = null; // 前一个节点
        ListNode cur = head; // 当前节点
        while(cur != null){
            ListNode ne = cur.next; // 保留下一个节点
            cur.next = pre; // 当前节点的下个节点为前一个节点
            pre = cur; 
            cur = ne;
        }
        return pre;
    }
}


解法二

使用递归

链表反转,所以最后我们返回的节点就是末尾的那个节点,每次返回末尾节点所以递归完成我们就是返回的最后一个节点

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null)return head; // 递归结束条件
        ListNode ne = reverseList(head.next); // 会一直递归找到了5这个节点
        head.next.next = head; // 将下个节点的下个节点设置为当前节点
        head.next = null; // 当前节点的下个节点设置为null,避免链表成环
        return ne;
    }
}


解法三

循环头插法

每次到插入到res的下一个节点位置

class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode res =  new ListNode(); // 新的头节点的前一个节点
        while(head != null){
            ListNode ne = head.next; // 保存当前节点的下一个节点
            head.next = res.next; // 当前节点下个节点为res的下个节点
            res.next = head; // res的下个节点为当前节点
            head = ne; //当前节点为下个节点
        }
        return res.next;
    }
}


回文链表


29a5215f231a440da20011e9d0aab01d.png


解法一

使用

将数据全部压入栈中,因为栈是先进后出,所以栈中数据相当于反转后的数据

然后栈中数据与链表数据一一比较,如果不一致直接returen false结束

class Solution {
    public boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null) return true;
        Stack<ListNode> s = new Stack<ListNode>();
        ListNode p = head;
        while(p != null){ // 将链表所有数据压入栈中
            s.add(p);
            p = p.next;
        }
        p = head;
        while(!s.isEmpty()){ // 比较栈中的值与链表的值是否相等
            ListNode t = s.pop();
            if(t.val != p.val) return false;
            p = p.next;
        }
        return true;
    }
}


解法二

链表反转+比较

与上面链表反转类似不再赘述


解法三

快慢指针 + 链表反转 O(n) 时间 O(1) 空间

与解法二类似,只是只反转后部分链表然后比较

class Solution {
    public boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null) return true;
        ListNode s = head;
        ListNode q = head.next;
        while(q != null && q.next != null){
            s = s.next;
            q = q.next.next;
        }
        ListNode t = reverse(s.next); // 反转后半截
        while(t != null){
            if(t.val != head.val) return false;
            head = head.next;
            t = t.next;
        }
        return true;
    }
    public ListNode reverse(ListNode head){
        if(head == null || head.next == null) return head;
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode ne = cur.next;
            cur.next = pre;
            pre =cur;
            cur = ne;
        }
        return pre;
    }
}


解法四

使用递归

因为递归相当于帮我们维护一个栈

class Solution {
    ListNode t = null;
    public boolean isPalindrome(ListNode head) {
        if(head == null) return true; // 结束条件
        t = head;
        return check(head);
    }
    public boolean check(ListNode head){
        if(head == null) return true; // 没有head.next,因为使用head.next那么最后一个不会展示出来
        boolean res = check(head.next)&&(t.val == head.val);
        t = t.next;
        return res;
    }
}


相关文章
|
2月前
|
索引
【力扣刷题】两数求和、移动零、相交链表、反转链表
【力扣刷题】两数求和、移动零、相交链表、反转链表
23 2
【力扣刷题】两数求和、移动零、相交链表、反转链表
|
6天前
|
算法 C语言
【数据结构与算法 经典例题】链表的回文结构(图文详解)
【数据结构与算法 经典例题】链表的回文结构(图文详解)
|
2月前
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点.
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点
26 1
|
2月前
题目----力扣--回文链表
题目----力扣--回文链表
21 0
|
2月前
|
索引
【力扣刷题】回文链表、环形链表、合并两个有序链表
【力扣刷题】回文链表、环形链表、合并两个有序链表
22 0
|
2月前
|
C++
[leetcode 链表] 反转链表 vs 链表相交
[leetcode 链表] 反转链表 vs 链表相交
|
2月前
|
算法
【每日一题】牛客网——链表的回文结构
【每日一题】牛客网——链表的回文结构
|
2月前
|
C语言 C++ 索引
【力扣】141. 环形链表、160. 相交链表、206.反转链表、234. 回文链表
【力扣】141. 环形链表、160. 相交链表、206.反转链表、234. 回文链表
|
2月前
|
C语言
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】
|
2月前
|
存储 算法 Java
【数据结构与算法】2、链表(简单模拟 Java 中的 LinkedList 集合,反转链表面试题)
【数据结构与算法】2、链表(简单模拟 Java 中的 LinkedList 集合,反转链表面试题)
49 0