精华内容
下载资源
问答
  • public class Node{ int value; Node next; public Node(int value){ this.value = value;... //这个反转单链表这样想象,把原先链表的节点从头取出来接在另一个新链表上 public Node reverse(Node head){ ...
    public class Node{
        int value;
        Node next;
        public Node(int value){
          this.value = value;    
        }
        
        //这个反转单链表这样想象,把原先链表的节点从头取出来接在另一个新链表上
        public Node reverse(Node head){
          if(root == null){
             return null;
          }
          Node pre = null;//pre可以认为是不断构造的反转链表的头结点
          Node next = null;//next用来保存next的值
          while(head != null){//这里直接修改head,这个head用不着保存了
              next = head.next;
              head.next = pre;
              pre = head;
              head = next;
          }
          return pre;
          
    }

    时间复杂度就是O(n),就只是遍历一下单链表。

    展开全文
  • 单链表插入时间复杂度分析

    千次阅读 2021-05-24 22:28:08
    从我画的单链表图中,你应该可以发现,其中有两个结点是比较特殊的,它们分别是第一个结点和最后一个结点。我们习惯性地把第一个结点叫作头结点,把最后一个结点叫作尾结点。其中,头结点用来记录链表的基地址。有了...

    链表通过指针将一组零散的内存块串联在一起。其中,我们把内存块称为链表的“结点”。为了将所有的结点串起来,每个链表的结点除了存储数据之外,还需要记录链上的下一个结点的地址。如图所示,我们把这个记录下个结点地址的指针叫作后继指针 next。
    在这里插入图片描述
    从我画的单链表图中,你应该可以发现,其中有两个结点是比较特殊的,它们分别是第一个结点和最后一个结点。我们习惯性地把第一个结点叫作头结点,把最后一个结点叫作尾结点。其中,头结点用来记录链表的基地址。有了它,我们就可以遍历得到整条链表。而尾结点特殊的地方是:指针不是指向下一个结点,而是指向一个空地址 NULL,表示这是链表上最后一个结点。

    添加的时间复杂度

    在链表尾部添加(addLast())需要从头遍历,时间复杂度为O(n)
    在链表头部添加(addFirst()),时间复杂度为O(1)
    在链表任意位置添加(add(int index,E e)),平均情况下为O(n/2)=O(n)

    总结

    • 在不同的位置添加元素,时间复杂度是不一样的,并不都是O(1),好多文章这里的说法是错的

    参考

    单向链表基本操作的时间复杂度分析_枣面包的博客-CSDN博客_单链表时间复杂度总结

    展开全文
  • 单链表时间复杂度

    万次阅读 2018-04-19 17:50:44
    让我们来研究一下单链表时间复杂度 相比于数组,单链表在插入删除节点的时候,不需要移动大量的元素,只需要改变指针的指向,所以我们往往看到好多文章说它的时间复杂度是O(1)。但是,这种说法是不对的,应该根据...

    让我们来研究一下单链表的时间复杂度

    相比于数组,单链表在插入删除节点的时候,不需要移动大量的元素,只需要改变指针的指向,所以我们往往看到好多文章说它的时间复杂度是O(1)。但是,这种说法是不对的,应该根据情况而定。

    O(1)的情况

    一个已知头结点的链表,删除某结点,且告诉你该元素的地址node

    由于这是单链表,我们无法获取node前一个节点的地址,看上去貌似不能删除这个结点。但是,是否删除这个节点只是看这个节点的data值是否还存在于链表中,因此,我们可以让链表看起来删除了node,实则删除了结点node.next.

    newNode=node.next;  
    node.data=newNode.data;//移交元素  
    node.next=newNode.next;//移交指针  
    free(newNode);//释放目标删除结点后一个节点的内存  
    newNode=NULL;//置空指针 

    这样,看起来删除了node结点,实际上node.next成了真正的牺牲品。上述操作在O(1)内完成。

    一个已知头结点的链表,在某结点后面插入新节点,大小为newdata,且告诉你该结点的地址node

    newNode=NULL;  
    newNode.data=newdata;  
    newNode.next=node.next;  
    node.next=newNode;

    O(n)的情况

    一个已知头结点的链表,删除第index个元素

    首先需要从头开始向后遍历,直到找到第index-1个结点,这需要O(n)时间;找到以后,改变指针的指向,这需要O(1)的时间。所以这种情况下,时间复杂度为O(n)。

    let i=0; 
    let p = head; 
    while(head&&i<=index-2)//找到第index-1个结点退出  
    {  
        p=p.next;  
        i++;  
    }  
    let q=p.next;//q是第index个节点,即要删除的节点  
    p.next=q.next;//转移指针  
    free(q);//释放内存
    newNode=NULL;  
    newNode.data=newdata;  
    newNode.next=node.next;  
    node.next=newNode;

    一个已知头结点的链表,在第index个元素前插入一个元素

    首先需要从头开始向后遍历,直到找到第index-1个结点,这需要O(n)时间;找到以后,创建新节点,改变指针的指向,这需要O(1)的时间。所以这种情况下,时间复杂度为O(n)。

    let p=head;  
    int i=0;  
    while(p&&i<=index-2)  
    {  
       p=p.next;  
        i++;  
    }  
    let newNode=NULL;  
    newNode.data=newdata;  
    newNode.next=p.next;  
    p.next=newNode;
    展开全文
  • 题目描述 在O(n log n)的时间内...这个时间复杂度O(nlogn)一般就是归并排序,然而要使用常数级的空间,那只能在链表上进行排序而不能转成数组排序后再转换成链表了。归并排序核心思想就是递归地对当前数组或链表...

    题目描述
    在O(n log n)的时间内使用常数级空间复杂度对链表进行排序。
    Sort a linked list in O(n log n) time using constant space complexity.

    分析

    这个时间复杂度O(nlogn)一般就是归并排序,然而要使用常数级的空间,那只能在链表上进行排序而不能转成数组排序后再转换成链表了。归并排序核心思想就是递归地对当前数组或链表的左部和右部分别排序后再合并。看到讨论区有人说用递归的话也要申请空间。那也没办法啊,我只会递归版的归并排序(笑死)

    时间复杂度
    O(n)
    空间复杂度
    O(1) (虽然用了递归需要额外空间,但也是常数级别的啊哈哈哈哈哈哈哈哈哈哈

    代码

    /**
     * Definition for singly-linked list.
     * class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    public class Solution {
        public ListNode sortList(ListNode head) {
            if(head == null || head.next == null)return head;
            ListNode middle = findMiddle(head);
            ListNode right = sortList(middle.next);
            middle.next = null;
            ListNode left = sortList(head);
            return merge(left, right);
        }
        //快慢指针,用法类似判断链表是否有环,找链表倒数第n个结点也要两个指针
        ListNode findMiddle(ListNode head){
            ListNode slow = head, quick = head;
            while(quick.next!=null && quick.next.next!=null){
                slow = slow.next;
                quick = quick.next.next;
            }
            return slow;
        }
        //为了节省空间,直接对两条链进行归并,不另外开一条链
        ListNode merge(ListNode p1, ListNode p2){
            if(p1 == null && p2 !=null)return p2;
            if(p1 != null && p2 ==null)return p1;
            ListNode head = new ListNode(0);
            ListNode pHead = new ListNode(0);
            //在p1中插入p2
            if(p1.val<=p2.val){
                head = p1;
                pHead = head;
                p1 = p1.next;
                while(p1 !=null && p2 !=null){
                    if(p1.val<=p2.val){
                        head = head.next;
                        p1 = p1.next;
                    }
                    else{
                        //插入p2的一个结点
                        ListNode p = p2;
                        p2 = p2.next;
                        p.next = head.next;
                        head.next = p;
                        head = head.next;
                    }
                }
                if(p1 == null)head.next = p2;
                else head.next = p1;
            }
            else{
                //在p2中插入p1
                head = p2;
                pHead = head;
                p2 = p2.next;
                while(p1 !=null && p2 !=null){
                    if(p2.val<=p1.val){
                        head = head.next;
                        p2 = p2.next;
                    }
                    else{
                        ListNode p = p1;
                        p1 = p1.next;
                        p.next = head.next;
                        head.next = p;
                        head = head.next;
                    }
                }
                if(p1 == null)head.next = p2;
                else head.next = p1;
            }
            return pHead;
        }
    }
    
    展开全文
  • 单链表经典算法与时间复杂度分析

    千次阅读 2020-04-13 18:03:25
    } } 设计算法将两个递增有序带头结点的单链表A,B合并为一个递减有序的带头结点的单链表,并要求算法的时间复杂度为两个表长之和的数量级 【算法分析】 合并两个递增链表为一个递减链表,基本思想是比较之后进行头...
  • (1)如果不要求空间复杂度,则可以将链表元素存至vectorvectorvector,排序后将其化为链表 #include <iostream> #include <vector> #include <algorithm> using namespace std; struct ListNode { ...
  • 单链表插入删除操作的时间复杂度

    千次阅读 2019-11-10 10:31:23
    单链表相比数组的优势在于插入删除元素快,不需要移动大量的元素,只需要改变指针的指向,那么插入删除操作的时间复杂度应该是O(1),但是这是不对的,应该分情况讨论。 单链表结构体声明: typedefstruct LNode { ...
  • 学习目标:单链表的插入删除 提示:这里可以添加学习目标 例如:一周掌握 Java 入门知识 学习内容: 提示:这里可以添加要学的内容 例如: 1、 单链表带头结点和不带头结点的区别? 2、 按位序插入带头结点 3、 按...
  • 注意看带头结点的双向链表,他的时间效率,不管哪种操作,都是O(1),实际上是利用了空间提高时间
  • #if 1 #include<stdio.h> #include<stdlib.h> #include<iostream> using namespace std; struct Node { int data; Node *next; }; //初始化 ... Node *head...
  • 其实这个才是逆序输出链表的正确操作,记得前面写的时候有四种办法,但除了递归比较简洁而且时间复杂度和空间复杂度都满足外,其他的方法都太丑陋了...  Code: /* 反转链表的函数 */ struct reverseList * ...
  • #include #include #include using namespace std; typedef struct LNode{ int data; int sum = 0; struct LNode *next; }LNode,*List; void creat_list(List &L){ L = ... } 用此方法达到合并链表的时间复杂度为O(n).
  • 平时我们在计算单链表的第i个节点删除时间复杂度时一般认为是O(n),过程如下 1.先从头节点开始遍历链表,找到第i-1个节点 2.将第i-1节点next指向第i个节点的next 可以看到时间主要花在了遍历链表上 如果我们...
  • 思路: 将头节点摘下,然后以第一个节点开始依次插入到头节点的后面(模仿头插法)知道最后一个节点,如此就是就地逆置算法!... printf("就地逆置单链表: \n"); reverse_List(); print_List(); return 0; }
  • 顺序表插入数据时,可以很快找到要插入数据的位置,只要将(前或后的)数据移位就行,但他的时间复杂度也是O(N) 单链表插入数据的时候,不是也要通过查找数据这一步,然后再进行插入数据,这种时间复杂度也是O(N) ...
  • 如果没有要求空间复杂度为O(1),可以遍历链表并将每个节点的值存入vector中,利用...时间复杂度O(nlogn),空间复杂度O(n)。 考点: 1. 归并排序O(nlogn);2. 快慢指针定位链表中间节点。 复杂度分析: T(n) ...
  • 顺序存储结构查找的时间复杂度为O(1) 链式存储结构查找的时间复杂度为O(n) 插入和删除: 顺序存储结构插入和删除时间复杂度为O(n) 链式存储结构插入和删除时间复杂度为O(1) 空间性能 顺序存储结构需要分配好空间...
  • 一个编程练习,删除单链表一个节点,且时间复杂度控制在O(1)内. 1.核心操作代码如下: struct ListNode { int m_data; ListNode *m_pNext; }; void DeleteNode(ListNode **pListHead, ListNode *...
  • //LNode结点,LinkList单链表 /*如果用后插法插入元素,时间复杂度为O(n2)*/ /*设置一个表尾指针r,始终指向表尾*/ /*尾插法建立单链表时间复杂度O(n)*/ LinkList List_TailInsert(LinkList &L)//正向建立单链表 {...
  • 一、存储分配方式: ...二、时间性能 1、查找 顺序存储方式(相当于数组):O(1),可直接取用。 单链表:O(n),每次得遍历整个链表。 2、插入删除: 顺序存储:每次得将前或者后面的元素移动一个元素位置,平...
  • * 数据结构的辅导书上答案是两个都是O(1). * 我觉得循环单链表要找到最后一个结点,把最后一个指针指向新的开始结点,所以,时间复杂度应该是O(n)。 是不是我哪里想错了呢?
  • 顺序表与链表时间复杂度比较

    千次阅读 2020-02-15 20:03:25
    顺序表与链表时间复杂度比较 名称 访问 查找 插入 删除 数组 O(1) O(n) O(n) O(n) 有序数组 O(1) O(logN) O(n) O(n) 链表 O(n) O(n) O(1) O(1) 有序链表 O(n) O(n) O(n) O(n) 1、向一个有序数组中...
  • ,从头部插入的话是O1的复杂度,但是插入到其他地方的话就就是On,所以不管是从最坏的角度考虑,还是从综合的角度考虑,其时间复杂度都为On。   上面讲的是在任意位置的插入,其实就是教科书里说的尾插法,...
  • //heada 头指针 ,pa 前驱节点,pb后驱节点 void ReverseAList(Node *heada,NOde *Listc){ Node *pa = heada->next; Node *pb = pa->next; pa->next = null;... //一个头指针来指向...
  • typedef struct Node{ int data; struct Node *next; }node; typedef struct{ node head; node tail; }link;void link_revert(link *p) ... node *first = NULL, *mid = NULL, *last = NULL, *tmp = NULL;... if(p
  • 算法实现:自底向上的归并排序 /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next;... * ListNode(int x) : val(x), next(NULL) {} ...class Solu...
  • 下面就我自己的感受说说我对内存空间换取降低操作数据时的时间复杂度的一点浅见。 首先单向链表的结构可以简单的表示为: 头结点是节点1的引用,而节点1的next属性又是节点2的应用,以此类推,最后一个节点的next...
  • 对于一个单链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。 1、问题描述: 给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。 ...
  • 要使单链表逆置而且空间复杂度为O(1) 只能在当前链表进行操作。 这个操作和头插法类似(当数据输入进来的时候若是用头插法建立链表,输出时就会和输入逆序,其实栈就是这个思想:先入后出)。 这里就相当于是将...
  • 单向链表的时间复杂度 在单向链表原理和实现中已经和动态数组相比对比并分析了单向链表的时间复杂度: 情况分类 添加 删除 最好 头节点 O(1) O(1) 最差 尾节点 O(n) O(n) 平均 O(n) O(n) 双向链表的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,968
精华内容 13,187
关键字:

单链表时间复杂度