线性表相关算法题

一.两个递增有序链表合并成一个有序链表,要求新的链表使用这两个链表的内存,不占用新的内存空间,并且没有重复数据

分析:设两个链表A{1,3,5,6,7,9},B{2,3,6}。合成后:C{1,2,3,5,6,7,9}。不使用新的内存空间,那么C的头结点需要使用A或B的头结点,进入循环:
A:1<B:2------head->1
A:3>B:2------head->1->2
A:3=B:3------head->1->2->A:3 (B:3没用了,释放掉)
A:5<B:6------head->1->2->A:3->5
A:6=B:6------head->1->2->A:3->5->A:6 (B:6没用了,释放掉)
B循环结束----head->1->2->A:3->5->A:6->7->9
循环结束,B的头指针没有用了,释放掉。

为了记住A和B循环到哪里了,需要声明两个临时变量来记录:tempAtempB;
为了记住C的最后一个结点,需要声明一个临时变量来记录:tempC;
为了释放重复结点,需要声明一个临时变量记录:temp

int mergeList(LinkList *A,LinkList *B, LinkList *C){
    
    LinkList tempA, tempB, tempC, temp;
    
    tempC = *C = *A;//使用A的头结点
    tempA = (*A)->next;
    tempB = (*B)->next;
    
    while (tempA && tempB) {
        if (tempA->data == tempB->data) {
            tempC->next = tempA;
            tempA = tempA->next;

            temp = tempB;
            tempB = tempB->next;
            tempC = tempC->next;
            
            free(temp);
        }else if (tempA->data < tempB->data){
            tempC->next = tempA;
            tempA = tempA->next;
            
            tempC = tempC->next;
        }else {//>
            tempC->next = tempB;
            tempB = tempB->next;
            
            tempC = tempC->next;
        }
    }
    printf("循环结束");
    if (tempA == NULL) {
        tempC->next = tempB;
    }else {
        tempC->next = tempA;
    }
    
    free(*B);
    
    return OK;
}

以上算法时间复杂度:O(n)n是较短的链表的长度。

二. 两个递增有序链表A和B,求出A和B的交集存储在A链表中

分析:假设A{1,3,5,6,7,9},B{2,3,6}。交集为A{3,6}。
进入循环:作比较,释放较小的,相等,释放B的。
A:1<B:2------释放1
A:3>B:2------释放2
A:3=B:3------head->B:3 (B:3没用了,释放掉)
A:5<B:6------释放5
A:6=B:6------head->3->A:6 (B:6没用了,释放掉)
B循环结束----A剩余的结点一定不存在和B的交集,释放
循环结束,B的头指针没有用了,释放掉。

为了记住A和B循环到哪里了,需要声明两个临时变量来记录:tempAtempB;
为了记录新的链表,需要声明一个临时变量:sameList
为了释放不重复的结点,需要声明一个临时变量记录:temp

Status GetSame(LinkList *A,LinkList *B) {
    
    LinkList tempA,tempB,sameList,temp;
    
    tempA = (*A)->next;
    tempB = (*B)->next;
    sameList = (*A);
    
    while (tempA && tempB) {
        if (tempA->data == tempB->data) {
            sameList->next = tempA;
            sameList = sameList->next;
            
            tempA = tempA->next;
            temp = tempB;
            tempB = tempB->next;
            
        }else if (tempA->data < tempB->data){
            temp = tempA;
            tempA = tempA->next;
            
            free(temp);
        }else{//>
            temp = tempB;
            tempB = tempB->next;
            
            free(temp);
        }
    }
    sameList->next = NULL;
    
    if (tempA) {
        while (tempA) {
            temp = tempA;
            tempA = tempA->next;
            
            free(temp);
        }
    }
    
    if (tempB) {
        while (tempB) {
            temp = tempB;
            tempB = tempB->next;
            
            free(temp);
        }
    }
    
    free(*B);
    
    return OK;
}

以上算法时间复杂度:O(n)n是较长的链表的长度。

三.设计一个算法将链表的所有结点的连接方向原地旋转,要求不开辟额外的内存空间

分析:链表A{1,2,3,4,5,6,7}。旋转后A{7,6,5,4,3,2,1}。
使用头插法创建链表链表时,链表顺序是逆序的,可以使用头插法的思路。不能开辟新的空间,所以依然使用链表A的头指针。

临时变量q记录旧的链表,p记录从旧链表中摘下的结点,用头插法将p插入到新的链表A中。过程如图:

Status translateList (LinkList *A) {
    
    LinkList p,q;
    
    p = (*A)->next;
    (*A)->next = NULL;
    
    while (p) {
        q = p->next;
        
        p->next = (*A)->next;
        
        (*A)->next = p;
        p = q;
    }
    
    return OK;
}

四. 设计算法,删除递增有序链表中值大于等于minK且小于等于maxK的所有元素。(minK和maxK是给定的两个参数,可以和表中元素相同,也可以不同)

分析:链表A{1,2,3,4,5,6,8}删除>=3且<=7的结点之后为A{1,2,8}。
循环找到要删除的第一个结点之前的结点q,并记录要删除的第一个结点deletList,继续循环找到要删除的最后一个结点p,让q指向p的下一个结点完成新的链表。释放删除的结点。

Status DeletNodes(LinkList *A, int minK, int maxK){
    
    LinkList deletList = NULL, p, q;
    
    p = q = (*A)->next;
    
    while (p->next) {
        if (p->next->data >= minK && p->next->data < maxK) {
            deletList = p->next;
            q = p;
            break;
        }
        p = p->next;
    }
    
    while (p->next) {
        if (p->next->data > maxK) {
            q->next = p->next;
            p->next = NULL;
            
            break;
        }else if (p->next->data == maxK) {
            p = p->next;
            q->next = p->next;
            p->next = NULL;
            
            break;
        }
        p = p->next;
    }
    
    if (deletList) {
        LinkList temp;
        p  = deletList->next;
        while (p) {
            temp = p;
            p = p->next;
            
            free(temp);
        }
        
        free(deletList);
    }else {
        return -1;
    }
    
    return OK;
}

五. 设将n(n>1)个整数存放到一维数组R中, 将R中保存的序列循环左移p个位置(0<p<n), 即将R中的数据由(x0,x1,......,xn-1)变换为 (xp,xp+1,...,xn-1,x0,x1,...,xp-1).设计算法要求时间和空间两方面都尽可能的高效

分析:假设R=[1,2,3,4,5,6,7,8,9]。p=3,移动之后为:R= [4,5,6,7,8,9,1,2,3]。
第一步:[1,2,3,4,5,6,7,8,9]
第二步:[9,8,7,6,5,4] [3,2,1]
第二步:[4,5,6,7,8,9] [1,2,3]

void listChange(int *R, int left, int right) {
    
    int i = left, j = right;
    int temp;
    
    while (i<j) {
        temp = R[i];
        R[i] = R[j];
        R[j] = temp;
        i++;
        j--;
    }
}

Status arrayTranslate(int *R, int p, int n) {
    
    if (p<n && p>0) {
        listChange(R, 0, n-1);
        listChange(R, 0, n-p-1);
        listChange(R, n-p, n-1);
    }
    
    return OK;
}

以上算法时间复杂度:O(n),空间复杂度O(1)

六.⽤单链表保存m个整数, 结点的结构为(data,link),且|data|<=n(n为正整数). 现在要去设计一个时间复杂度尽可能高效的算法. 对于链表中的data绝对值相等的结点, 仅保留第一次出现的结点,而删除其余绝对值相等的结点.

分析:A{2,-3,4,3,15,-15,3}处理后:A{2,-3,4,15}
---------R:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
A:2----- R:[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0]
A:-3---- R:[0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0]
A:4----- R:[0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0]
A:3----- R:[0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0]---R[3]位置已经是1,这个节点删除
A:15---- R:[0,0,1,1,1,0,0,0,0,0,0,0,0,0,15,0]
A:-15--- R:[0,0,1,1,1,0,0,0,0,0,0,0,0,0,15,0]---R[15]位置已经是1,这个节点删除
A:3----- R:[0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0]---R[3]位置已经是1,这个节点删除

Status deletSameNode(LinkList *A, int n) {
    
    int *R = malloc(sizeof(int)*(n+1));
    
    for (int i = 0; i<n; i++) {
        R[i] = 0;
    }
    
    LinkList p = (*A);
    LinkList temp = (*A)->next;
    int absValue;
    
    while (temp) {
        absValue = abs((temp->data));
        
        if (R[absValue] == 0) {
            R[absValue] = 1;
            p = p->next;
            temp = temp->next;
        }else {
            //删除这个结点
            p->next = temp->next;
            free(temp);
            temp = p->next;
        }
    }
    return OK;
}

以上算法时间复杂度:O(m)m是链表的长度。空间复杂度:O(n)n是链表中最大的值。

七.A中的n个元素保存在⼀个⼀维数组中,请设计一个尽可能高效的算法,找出数组元素中的主元素,若存在主元素则输出该元素,否则输出-1.

  • 概念解释:主元素-数组中出现次数大于元素总数一半的元素。例如:A[2,1,2,3,2,4,2,5,2,6,2]中2是A的主元素,A[1,2,3,2,4,2,5,2,6,2]中没有主元素。

分析:如果A中一个11个元素,元素X出现了6次,那么就有5个其他元素,让1个X和一个其他元素结为一对。那么最后会剩下一个单独的元素,而且一定是X。再判断X出现的次数是否大于总元素个数的一半,我们就知道了X是否是主元素。

int findMainElement(int *A, int n){
    
    int count = 1;
    int key = A[0];
    
    for (int i = 1; i<n; i++) {
        if (A[i] == key) {
            count++;
        }else {
            if (count>0) {
                count--;
            }else {
                key = A[i];
                count = 1;
            }
        }
        printf("count=%d,key=%d\n",count,key);
    }
    
    int num = 0;
    if (count > 0) {
        for (int i = 0; i<n; i++) {
            if (A[i] == key) num++;
        }
        if (num > n/2) {
            printf("主元素是:%d\n",key);
            return key;
        }
    }
    printf("没有主元素\n");
    return -1;
}

以上算法时间复杂度:O(n)。空间复杂度:O(1)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345

推荐阅读更多精彩内容