当前位置:   article > 正文

2021年10月28日 链表的递归 奇偶链表_利用递归算法将链表拆分奇数和偶数

利用递归算法将链表拆分奇数和偶数

删除链表倒数第N个节点

 在自己的版本上参考大佬修改后的代码

  1. struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
  2. struct ListNode* fast=head;
  3. struct ListNode* slow=head;
  4. while(n--)
  5. fast=fast->next;
  6. while(fast&&fast->next){
  7. slow=slow->next;
  8. fast=fast->next;
  9. }
  10. if(fast==NULL) return head->next;
  11. slow->next=slow->next->next;
  12. return head;
  13. }

很奇怪啊,为什么判断条件有fast呢?原来是为了满足一些特殊数据啊!

 

自己写的话要分很多类,但是在这里做判断确实更好! 


 java后序遍历递归回溯法:(来自力扣大佬)

我自己感觉if(num==n)这个条件有点问题,应该是"!=",这样后面才会做;

至于"node==null"的时候是返回0还是返回1,也应该再想想。

  1. public ListNode removeNthFromEnd(ListNode head, int n) {
  2. int traverse = traverse(head, n);
  3. if(traverse == n)
  4. return head.next;
  5. return head;
  6. }
  7. private int traverse(ListNode node, int n) {
  8. if(node == null)
  9. return 0;
  10. int num = traverse(node.next, n);
  11. if(num == n)
  12. node.next = node.next.next;
  13. return num + 1;
  14. }

 反转链表 

方法一:三指针迭代

  1. List Reverse(List L){
  2. if(!L) return NULL;
  3. List temp,nxt; //两个光标,nxt用来保存temp后面一个节点,
  4. temp=L->Next; //这里L反而可以变了,因为是尾巴不是头结点,
  5. L->Next=NULL;
  6. while(temp){
  7. nxt=temp->Next;//先用nxt保存
  8. temp->Next=L;//指向L(尾巴),可以理解为入队
  9. L=temp;//队伍尾巴更新(有点像堆栈的top)
  10. temp=nxt;//更新temp的值
  11. }
  12. return L;
  13. }

 方法二:递归

  1. public ListNode reverseList(ListNode head) {
  2. if (head == null || head.next == null) {
  3. return head;
  4. }
  5. "调用递推公式反转当前结点之后的所有节点"
  6. "返回的结果是反转后的链表的头结点"
  7. ListNode newHead = reverseList(head.next);
  8. head.next.next = head;
  9. head.next = null;
  10. return newHead;
  11. }

反转前N个节点 

递归(java): 

  1. ListNode topNSuccessor = null;
  2. private ListNode reverseTopN(ListNode head, int n) {
  3. if (n == 1) {
  4. topNSuccessor = head.next;
  5. return head;
  6. }
  7. ListNode newHead = reverseTopN(head.next, n-1);
  8. head.next.next = head;
  9. head.next = topNSuccessor;
  10. return newHead;
  11. }

迭代 (C)头插法

image.png

  1. truct ListNode *reverseBetween(struct ListNode *head, int left, int right) {
  2. // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
  3. struct ListNode *dummyNode = malloc(sizeof(struct ListNode));
  4. dummyNode->val = -1;
  5. dummyNode->next = head;
  6. "找到起点的前一个节点"
  7. struct ListNode *pre = dummyNode;
  8. for (int i = 0; i < left - 1; i++) {
  9. pre = pre->next;
  10. }
  11. "开始头插法"
  12. struct ListNode *cur = pre->next;
  13. struct ListNode *next;
  14. for (int i = 0; i < right - left; i++) {
  15. next = cur->next;
  16. cur->next = next->next;
  17. next->next = pre->next;
  18. pre->next = next;
  19. }
  20. return dummyNode->next;
  21. }

92.反转第a个到第b个节点 

  1. public ListNode reverseBetween(ListNode head, int m, int n) {
  2. if (m == 1) {
  3. return reverseTopN(head, n);
  4. }
  5. ListNode between = reverseBetween(head.next, m-1,n-1);
  6. head.next = between;
  7. return head;
  8. }
  9. ListNode topNSuccessor = null;
  10. private ListNode reverseTopN(ListNode head, int n) {
  11. if (n == 1) {
  12. topNSuccessor = head.next;
  13. return head;
  14. }
  15. ListNode newHead = reverseTopN(head.next, n-1);
  16. head.next.next = head;
  17. head.next = topNSuccessor;
  18. return newHead;
  19. }

  1. class Solution {
  2. public ListNode reverseBetween(ListNode head, int left, int right)
  3. {
  4. ListNode temp=head;
  5. List<ListNode> list=new ArrayList<>();"创建数组作为栈"
  6. "全部节点入栈"
  7. while(temp!=null)
  8. {
  9. list.add(temp);
  10. temp=temp.next;
  11. }
  12. "小细节处理left和right,注意这里"
  13. left=left-1;
  14. right=right-1;
  15. for(int i=right;i>left;i--)
  16. {
  17. list.get(i).next=list.get(i-1);"出栈并且反转"
  18. }
  19. "没看得很懂"
  20. list.get(left).next=(right==list.size()-1?null:list.get(right+1));
  21. if(left==0)"如果从头结点开始反转"
  22. {
  23. return list.get(right);
  24. }
  25. else{"不是从头节点开始反转,那么就将段的最右边节点出栈然后接到原链表后"
  26. list.get(left-1).next=list.get(right);
  27. return head;
  28. }
  29. }
  30. }

编程狂想曲https://leetcode-cn.com/problems/reverse-linked-list/solution/yi-bu-yi-bu-jiao-ni-ru-he-yong-di-gui-si-67c3/https://leetcode-cn.com/problems/reverse-linked-list/solution/yi-bu-yi-bu-jiao-ni-ru-he-yong-di-gui-si-67c3/ 这里提供了怎么写递归的思路。


203 移除链表元素

  1. struct ListNode* removeElements(struct ListNode* head, int val) {
  2. struct ListNode* dummyHead = malloc(sizeof(struct ListNode));
  3. dummyHead->next = head;
  4. struct ListNode* temp = dummyHead;
  5. while (temp->next != NULL) {
  6. if (temp->next->val == val) {
  7. temp->next = temp->next->next;
  8. "如果一样那么就temp指针在temp->next的基础上后移一格"
  9. }
  10. else {
  11. temp = temp->next;"如果不一样temp后移一格"
  12. }
  13. }
  14. return dummyHead->next;
  15. }

        真是掉到坑里了,一开始这里还去特别设计如果有连续相同的数要怎么删除,其实哪里需要考虑这个 ,直接交给循环了就好了,这里自然而然地会帮你去后移指针。

递归版本:

(等待更新)

奇偶链表 

基本思路:用双指针来爬奇偶点,注意要同时爬,用一个节点来保存偶数链表的头(及原链表的第二个 节点),奇数链表的表头自然就是原始的head了。

  1. struct ListNode* oddEvenList(struct ListNode* head) {
  2. if (head == NULL) {
  3. return head;
  4. }
  5. struct ListNode* evenHead = head->next; "先存下偶数链表的头"
  6. struct ListNode* odd = head; "odd指针指向第一个奇数节点,即头结点"
  7. struct ListNode* even = evenHead; "even指针指向第一个偶数节点,即第二个节点"
  8. while (even != NULL && even->next != NULL) {
  9. odd->next = even->next; "这里用even->next和odd->next->next好像没什么不同"
  10. odd = odd->next; "自我迭代"
  11. even->next = odd->next; "同上"
  12. even = even->next; "同上"
  13. }
  14. odd->next = evenHead;"偶数链表接到奇数链表后"
  15. return head;
  16. }

 ATTETION :这里要注意while的循环条件,不能换成奇数判断,也不能写"odd->next&&even->next",这样子写会出错。因为偶数比奇数大,所以我们用偶数来判断是否遍历完。

(这个点吃了大亏)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/395451
推荐阅读
相关标签
  

闽ICP备14008679号