剑指offer和leetcode都有的_反转链表

输入一个链表,反转链表后,输出链表的所有元素。

  一开始我的做法非常复杂,因为我一次变了两个指针,导致要分别判断单数个结点和偶数个结点的情况。

  反转链表要解决的两个问题就是

  1.结点指向它的前驱

  2.头结点变为其尾结点

  

  当反转一个结点时,假设反转i,首先需要记录它的前驱,让它指向它的前驱,还需要记录它的后继结点,否则就会造成链表的断裂,所以至少需要三个结点。

  后来我整理了一下思路,发现有两种方法,一种用的是循环,一种用的是递归。

  1.循环做法

/**循环做法来反转链表
 * 思路是用三个指针来记录,
 * newCur表示现在正在反转的指针
 * newNext表示newCur将要指向的指针
 * newPre表示下一个要进行反转的指针
 *
 *
 */
public class ReverseLinkedListIterate {
	public static ListNode reverseLinkedList(ListNode head){
		 if(head==null||head.next==null){
			 return head;
		 }
		ListNode newPre=null;
		ListNode newCur=head;//指向头结点
		ListNode newNext=null;//指向头结点的前一个,也就是null
		while(newCur!=null) {
			newPre=newCur.next;
			newCur.next=newNext;
			newNext=newCur;
			newCur=newPre;
		}
		return newNext;
	}
}

  2.递归做法

    因为每个节点的操作其实是相同的,就是把节点指向前驱,所以我们想到了用递归的方法,但是在最后一步要做一些处理。

public static ListNode reverseLinkedList(ListNode head){
		 if(head==null||head.next==null){
			 return head;
		 }
		 return reverse(null,head);
	}
	/**
	 *
	 * @param newNext 表示结点的前驱,该结点指向的新的结点
	 * @param newCurrent 表示当前结点
	 * @return
	 */
	public static ListNode reverse(ListNode newNext,ListNode newCurrent) {
		//当当前结点的下一个不为空时,即该结点不是最后一个结点时
		if(newCurrent.next!=null) {
			//先记录该结点的下一个结点
			ListNode newPrevious=newCurrent.next;
			//该结点指向前驱
			newCurrent.next=newNext;
			//再把下一个结点当做当前结点。
			return reverse(newCurrent,newPrevious);

		}
		//当当前结点为最后一个结点时,不需要再进行下一步了,但此时需要变换指针的指向
		newCurrent.next=newNext;
		//再把尾结点返回。
		return newCurrent;
	}

  

  

时间: 2025-01-14 17:23:18

剑指offer和leetcode都有的_反转链表的相关文章

剑指Offer:合并两个排序的链表【25】

剑指Offer:合并两个排序的链表[25] 题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 题目分析 每次都是比较箭头节点,把小节点连接到已经合并的链表之后,重复的执行此过程,最后如果那个链表已经走完,那就将另一个链表直接连接到合并的链表之后. Java题解 public static ListNode Merge(ListNode list1,ListNode list2) { if(list1==null) return list2;

【Java】 剑指offer(17) 在O(1)时间删除链表结点

本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点. 思路 通常那样从头开始查找删除需要的时间为O(n),要在O(1)时间删除某结点,可以这样实现:设待删除结点i的下一个结点为j,把j的值复制到i,再把i的指针指向j的下一个结点,最后删除j,效果就相当于删除j. 注意特殊情况:1.当待删除结点i为尾结点时,无下一个结点,则只能从头到尾顺序遍历:2.当链

剑指offer(leetcode 10.) 正则表达式匹配

这题一年前就做过,当时刚开始刷leetcode,提交了几十次过不去,就放那没管了.今天剑指offer又遇到这题,终于做出来了,用的dp. 1 class Solution { 2 public: 3 bool isMatch(string s, string p) { 4 int s_len=s.size(),p_len=p.size(); 5 vector<vector<bool>> dp(s_len+1,vector<bool>(p_len+1,false)); 6

剑指Offer 16. 合并两个排序的链表 (链表)

题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 题目地址 https://www.nowcoder.com/practice/d8b6b4358f774294a89de2a6ac4d9337?tpId=13&tqId=11169&rp=3&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-ranking&tPage=1 思

剑指offer——面试题18.1:删除链表中重复的节点

1 // 面试题18(二):删除链表中重复的结点 2 // 题目:在一个排序的链表中,如何删除重复的结点?例如,在图3.4(a)中重复 3 // 结点被删除之后,链表如图3.4(b)所示. 4 5 #include <cstdio> 6 #include "List.h" 7 8 void DeleteDuplication(ListNode** pHead) 9 { 10 if(pHead == nullptr || *pHead == nullptr) 11 retur

剑指offer 17:合并两个有序链表

题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 解题思路 链表基础操作考察,难点在于对于输入数据的把握,一定要考虑输入数据的全面性 1.出现单链表为NULL: 2.两个链表都为NULL: 3.一个链表遍历完成,另一链表还有剩余的节点 4.两个链表等长: 下面给出具体C++代码实现: /* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), n

《剑指Offer》题目——从尾到头打印链表

题目描述:输入一个链表,从尾到头打印链表每个节点的值. 题目分析:用栈:Java用Stack不如用Deque接口,原因可以见链接:http://stackoverflow.com/questions/12524826/why-should-i-use-deque-over-stack public class ReverseList { class ListNode{ int val; ListNode next = null; ListNode(int val){ this.val = val

剑指Offer之在O(1)时间删除链表节点

题目描述 给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点. 解题思路 在单向链表中删除一个节点,最常规的做法无疑是从链表的头结点开始,顺序的遍历查找要删除的节点,并在链表中删除该节点.这种思路由于需要顺序查找,时间复杂度自然就是$O(n)$了. 之所以需要从头开始查找,是因为我们需要得到将删除的节点的前面一个节点.在单向链表中,节点中没有指向前一个节点的指针,所以只好从链表的头结点开始顺序查找.那是不是一定需要得到被删除的节点的前一个节点呢?答案是否定的.我们可以很方便

剑指OFFER之合并两个排序的链表

题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 解决办法 1.递归方法: if(pHead1==NULL) return pHead2; else if(pHead2==NULL) return pHead1; ListNode* pMerge=NULL; if(pHead1->val<=pHead2->val){ pMerge=pHead1; pMerge->next=Merge(pHead1->next,pHead2