IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 2021年10月28日 链表的递归 奇偶链表 -> 正文阅读

[数据结构与算法]2021年10月28日 链表的递归 奇偶链表

删除链表倒数第N个节点

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

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    struct ListNode* fast=head;
    struct ListNode* slow=head;
    while(n--)
        fast=fast->next;
    while(fast&&fast->next){
        slow=slow->next;
        fast=fast->next;
    }
    if(fast==NULL) return head->next;
    slow->next=slow->next->next;
    return head;
}

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

?

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


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

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

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

public ListNode removeNthFromEnd(ListNode head, int n) {
    	int traverse = traverse(head, n);
    	if(traverse == n)
    	    return head.next;
    	return head;
    }
    
    private int traverse(ListNode node, int n) {
        if(node == null)
            return 0;
        int num = traverse(node.next, n);
        if(num == n)
            node.next = node.next.next;
        return num + 1;
    }

?反转链表?

方法一:三指针迭代

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

?方法二:递归

public ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) {
        return head;
    }

    "调用递推公式反转当前结点之后的所有节点"
    "返回的结果是反转后的链表的头结点"
    ListNode newHead = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return newHead;
}

反转前N个节点?

递归(java):?

ListNode topNSuccessor = null;

private ListNode reverseTopN(ListNode head, int n) {
    if (n == 1) {
        topNSuccessor = head.next;
        return head;
    }

    ListNode newHead = reverseTopN(head.next, n-1);
    head.next.next = head;
    head.next = topNSuccessor;
    return newHead;
}

迭代?(C)头插法

image.png

truct ListNode *reverseBetween(struct ListNode *head, int left, int right) {
    // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
    struct ListNode *dummyNode = malloc(sizeof(struct ListNode));
    dummyNode->val = -1;
    dummyNode->next = head;

    "找到起点的前一个节点"
    struct ListNode *pre = dummyNode;
    for (int i = 0; i < left - 1; i++) {
        pre = pre->next;
    }
    
    "开始头插法"
    struct ListNode *cur = pre->next;
    struct ListNode *next;
    for (int i = 0; i < right - left; i++) {
        next = cur->next;
        cur->next = next->next;
        next->next = pre->next;
        pre->next = next;
    }
    return dummyNode->next;
}

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


public ListNode reverseBetween(ListNode head, int m, int n) {
    if (m == 1) {
        return reverseTopN(head, n);
    }

    ListNode between = reverseBetween(head.next, m-1,n-1);
    head.next = between;
    return head;
}

ListNode topNSuccessor = null;

private ListNode reverseTopN(ListNode head, int n) {
    if (n == 1) {
        topNSuccessor = head.next;
        return head;
    }

    ListNode newHead = reverseTopN(head.next, n-1);
    head.next.next = head;
    head.next = topNSuccessor;
    return newHead;
}

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right)
    {
      ListNode temp=head;
      List<ListNode> list=new ArrayList<>();"创建数组作为栈"

      "全部节点入栈"
      while(temp!=null)
      {
          list.add(temp);
          temp=temp.next;
      }

      "小细节处理left和right,注意这里"
      left=left-1;
      right=right-1;

      for(int i=right;i>left;i--)
      {   
          list.get(i).next=list.get(i-1);"出栈并且反转"
      }   

      "没看得很懂"
      list.get(left).next=(right==list.size()-1?null:list.get(right+1));
      
      
      if(left==0)"如果从头结点开始反转"
      {
         return list.get(right);
      }
      else{"不是从头节点开始反转,那么就将段的最右边节点出栈然后接到原链表后"
          list.get(left-1).next=list.get(right);
          return head;
      }
    }
}

编程狂想曲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 移除链表元素

struct ListNode* removeElements(struct ListNode* head, int val) {
    struct ListNode* dummyHead = malloc(sizeof(struct ListNode));
    dummyHead->next = head;
    struct ListNode* temp = dummyHead;
    while (temp->next != NULL) {
        if (temp->next->val == val) {
            temp->next = temp->next->next;
            "如果一样那么就temp指针在temp->next的基础上后移一格"
        } 
        else {
            temp = temp->next;"如果不一样temp后移一格"
        }
    }
    return dummyHead->next;
}

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

递归版本:

(等待更新)

奇偶链表?

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

struct ListNode* oddEvenList(struct ListNode* head) {
    if (head == NULL) {
        return head;
    }
    struct ListNode* evenHead = head->next; "先存下偶数链表的头"
    struct ListNode* odd = head;  "odd指针指向第一个奇数节点,即头结点"
    struct ListNode* even = evenHead; "even指针指向第一个偶数节点,即第二个节点"
    while (even != NULL && even->next != NULL) {
        odd->next = even->next; "这里用even->next和odd->next->next好像没什么不同"
        odd = odd->next; "自我迭代"
        even->next = odd->next; "同上"
        even = even->next; "同上"
    }
    odd->next = evenHead;"偶数链表接到奇数链表后"
    return head;
}

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

(这个点吃了大亏)

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-29 13:18:32  更:2021-10-29 13:21:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:56:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码