研究生菜鸟的leetcode起步第二天(链表基本操作篇)

研究生菜鸟的leetcode起步第二天

一、链表的特点

  1. 访问  O(N)
  2. 搜索  O(N)
  3. 插入 O(1)
  4. 删除 O(1)

 写很快,读很慢,适合读多写少的场景。

二、链表的常用操作

  1. 创建链表
  2. 添加元素(LinkedList中的add操作时间复杂度其实是O(N)的,因为需要先查找的需要插入的位置,删除也同理。)
  3. 访问元素
  4. 查找元素
  5. 删除元素
  6. 链表的长度

三、 leetcode练习

leetcode 第203题

 该题要求对链表做出删除的操作,需要对链表进行遍历,如果对head指针直接进行移动的话,这个链表的结构就不完整了,这时可以在链表头部引入一个dummy节点,dummy.next指向head。因为在对head指针做出移动时,虽然能根据next方便的找到下一个节点,但不能找到上一个节点,因此设立prev指针,保存head前面的节点信息。(自己一开始做的时候,并没有充分考虑到这些因素,只是为了避免这些情况的出现,直接从head.next指针开始遍历,没有得到正确结果)

第一次的错误想法
/**
 * 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 removeElements(ListNode head, int val) {
        ListNode a;
        a = head;
        if(head == null){
            return head;
        }else{
            while(head.next != null){
                if(head.val == val){
                    a = head.next;
                    head = head.next;
                }else if(head.next.val == val){
                    head.next = head.next.next;
                }else{
                    head = head.next;
                }
            }
            return a;
        }
    }
}

 这种做法非常费力,笨拙,非常讨厌,而且得不到正确答案。

创建两个指针后的正确代码
/**
 * 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 removeElements(ListNode head, int val) {
        ListNode dummy = new ListNode(0,head);
        ListNode prev = dummy; //这种赋值操作相当于prev即为当前dummy所在的节点,而不是重新创立了一个也指向dummy的next,val和dummy一样的节点
        while(head != null){
            if(head.val == val){
                prev.next = head.next;
            }else{
                prev = head;
            }
            head = head.next;
        } 
        return dummy.next;
    }
}

 另外,该题还可以通过递归的方式去解决。

class Solution {
    public ListNode removeElements(ListNode head, int val) {
       if(head==null)
           return null;
        head.next=removeElements(head.next,val);
        if(head.val==val){
            return head.next;
        }else{
            return head;
        }
    }
}

leetcode 第206题

 该题开始思路是正确的但在遇到一些困难后没有坚持下去,而且通过该题深刻理解到在书面上把思路清晰的罗列出来是非常重要的。第一次得到了迭代的算法,尝试转化为递归解决问题的算法。

第一种以迭代处理问题的算法

 这种方法是通过添加头指针的方法来完成的。

/**
 * 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 reverseList(ListNode head) {
        ListNode dummy = new ListNode(0,head);
        ListNode prev = dummy;
        if((head == null)||(head.next == null)){
            return head;
        }
        while(head.next != null){
            ListNode l = dummy.next;
            dummy.next = head.next;
            head.next = head.next.next;
            dummy.next.next = l;      
        }  
        return dummy.next;
    }
}
双指针迭代解决问题

 通过前后的双指针可以更简单的解决该问题,这种方法是通过以下方式实现的链表的翻转。转载自leetcode路漫漫我不畏,侵删

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
}
递归解法

 递归需要满足的条件

  1. 问题可以分解为几个子问题
  2. 子问题求解方式和大问题一致
  3. 存在递归终止条件

 通过递归的方式来解决问题时,一定要先把问题分割成子问题,再从最小的子问题回归来找到共同的解法,因为程序之所以会提高效率,是因为循环的结构,他会做重复的事情,所以从他们要做的事情中找到一个规律,才是重点,类似于脑筋急转弯。

/**
 * 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 reverseList(ListNode head) {
        if((head == null) || (head.next == null)){
            return head;
        }
        ListNode l = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return l;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值