剑指off day2-链表

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、从尾到头打印链表

题目:输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

自己的解法

class Solution {
    public int[] reversePrint(ListNode head) {
      Stack<Integer> A;  
      A =new Stack<>();     
      int counts=0;
      while(head!=null){       
        A.push(head.val);
        head=head.next;
        counts++;
        }
      int[] nums=new int[counts];
      for(int i =0; i <counts; i++){
        nums[i]=A.pop();
      }
      return nums;
    }    
}

栈的特点是后进先出,即最后压入栈的元素最先弹出。考虑到栈的这一特点,使用栈将链表元素顺序倒置。从链表的头节点开始,依次将每个节点压入栈内,然后依次弹出栈内的元素并存储到数组中。

可优化之处

  • 其中栈的初始化可以更简洁
Stack<ListNode> stack = new Stack<ListNode>(); 
  • 可以利用栈的函数size
int size = stack.size();

注意事项

关于数组的动态初始化,加深印象

arrayName = new type[length];
int[] arr3 = new int[3];

以及入栈与结点移动的先后问题
在这里插入图片描述

其他思路

递归法

解题思路:

利用递归: 先走至链表末端,回溯时依次将节点值加入列表 ,这样就可以实现链表值的倒序输出。

  1. 递推阶段: 每次传入 head.next ,以 head == null(即走过链表尾部节点)为递归终止条件,此时直接返回。
  2. 回溯阶段: 层层回溯时,将当前节点值加入列表,即tmp.add(head.val)。
  3. 最终,将列表 tmp 转化为数组 res ,并返回即可。
class Solution {
    ArrayList<Integer> tmp = new ArrayList<Integer>();
    public int[] reversePrint(ListNode head) {
        recur(head);
        int[] res = new int[tmp.size()];
        for(int i = 0; i < res.length; i++)
            res[i] = tmp.get(i);
        return res;
    }
    void recur(ListNode head) {
        if(head == null) return;
        recur(head.next);
        tmp.add(head.val);
    }
}

二、反转链表

题目:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

自己的解法

class Solution { 
    public ListNode reverseList(ListNode head) {
        Stack<ListNode> stack=new Stack<ListNode>();
        int count=0;
        while(head!=null){
            head=head.next;
            stack.push(head);
            count++;
        }
        ListNode newlist=stack.pop();

        for(int i=0;i<count;i++){
            newlist=newlist.next;
            newlist=stack.pop();           
        }
        return newlist;
    }
}

输出有问题
在这里插入图片描述
栈的解法

class Solution { 
    public ListNode reverseList(ListNode head) {
        Stack<ListNode> stack=new Stack<ListNode>();
        if (head == null) return head;
        while(head!=null){
            stack.push(head);
            head=head.next;       
        }
        ListNode newlist=stack.pop();
        ListNode tailNode=newlist;

        while(!stack.isEmpty()){
            ListNode cur=stack.pop();   
            tailNode.next=cur;
            tailNode=cur;                 
        }
        tailNode.next=null;
        return newlist;
    }
}

迭代法

  1. 迭代需要三个指针,pre,cur,nxt,分别按顺序指向三个节点
  2. 三个指针的初始化:pre指向空节点,cur指向头结点head,nxt指向head.next
    因为head.next可能不存在,nxt在循环中定义,这样如果head为空就不会进入循环
  3. 迭代过程
    • 定义两个指针: prepre 和 curcur ;prepre 在前 curcur 在后
    • 每次让 prepre 的 nextnext 指向 curcur ,实现一次局部反转
    • 局部反转完成之后, prepre 和 curcur 同时往前移动一个位置
    • 循环上述过程,直至 prepre 到达链表尾部
    1. 当cur为空时,返回pre

涉及到链表的操作,一定要在纸上把过程先画出来,再写程序。

class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null, cur = head;
        while(cur != null){
            ListNode nxt = cur.next;
            cur.next = pre;
            pre = cur;
            cur = nxt;
        }
        return pre;
    }
}

简洁的递归

  • 使用递归函数,一直递归到链表的最后一个结点,该结点就是反转后的头结点,记作 ret .
  • 此后,每次函数在返回的过程中,让当前结点的下一个结点的 next 指针指向当前节点。
  • 同时让当前结点的 next指针指向NULL ,从而实现从链表尾部开始的局部反转
  • 当递归函数全部出栈后,链表反转完成。
class Solution {
    public ListNode reverseList(ListNode head) {
        return recur(head, null);    // 调用递归并返回
    }
    private ListNode recur(ListNode cur, ListNode pre) {
        if (cur == null) return pre; // 终止条件
        ListNode res = recur(cur.next, cur);  // 递归后继节点
        cur.next = pre;              // 修改节点引用指向
        return res;                  // 返回反转链表的头节点
    }
}

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值