系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 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];
以及入栈与结点移动的先后问题
其他思路
递归法
解题思路:
利用递归: 先走至链表末端,回溯时依次将节点值加入列表 ,这样就可以实现链表值的倒序输出。
- 递推阶段: 每次传入 head.next ,以 head == null(即走过链表尾部节点)为递归终止条件,此时直接返回。
- 回溯阶段: 层层回溯时,将当前节点值加入列表,即tmp.add(head.val)。
- 最终,将列表 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;
}
}
迭代法
- 迭代需要三个指针,pre,cur,nxt,分别按顺序指向三个节点
- 三个指针的初始化:pre指向空节点,cur指向头结点head,nxt指向head.next
因为head.next可能不存在,nxt在循环中定义,这样如果head为空就不会进入循环 - 迭代过程
- 定义两个指针: prepre 和 curcur ;prepre 在前 curcur 在后
- 每次让 prepre 的 nextnext 指向 curcur ,实现一次局部反转
- 局部反转完成之后, prepre 和 curcur 同时往前移动一个位置
- 循环上述过程,直至 prepre 到达链表尾部
- 当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提供了大量能使我们快速便捷地处理数据的函数和方法。