PTA刷题总结-Part3.1 数组与链表专题

1 链表的基本操作

我做链表题比较习惯于给链表设置哨兵(sentinel),这样可以减少边界极端情况的判断,避免没有考虑周全导致出错。如下图中,深灰色部分就是哨兵结点。

image.png

1.1 顺序创建链表

输入样例:
1 2 3 4 5 6 7 -1
输出样例
1 2 3 4 5 6 7

读入结点,遇到-1就不读了,那么借助哨兵结点(head)创建链表的写法如下,最后返回的链表又去掉了哨兵:

#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int data;
    struct ListNode *next;
};

struct ListNode *readlist(); // 最后不返回哨兵结点

void printlist( struct ListNode *L )
{
     struct ListNode *p = L;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode *L, *Odd;
    L = readlist();
    printlist(L);

    return 0;
}


struct ListNode *readlist(){
    int curr = 0;
    scanf("%d", &curr);
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->data = NULL;
    head->next = NULL;
    struct ListNode* p = head;
    while (curr != -1){
        struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
        temp->data = curr;
        temp->next = NULL;
        p->next = temp;
        p = p->next;
        scanf("%d", &curr);
    }
    return head->next;
}

改成不使用哨兵,就需要加入对头节点是否为NULL的判断。

struct ListNode *readlist(){
    int curr = 0;
    scanf("%d", &curr);
    struct ListNode* head = NULL;
    struct ListNode* p = head;
    while (curr != -1){
        struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
        temp->data = curr;
        temp->next = NULL;
        if (head == NULL){
            head = temp;
            p = head;
        } else {
            p->next = temp;
            p = p->next;
        }
        scanf("%d", &curr);
    }
    return head;
}

1.2 逆序创建链表

逆序创建链表,其实就是把新读入的结点,插到现有链表的头部。这个时候就没有哨兵节点了。

输入样例:
1 2 3 4 5 6 7 -1
输出样例
7 6 5 4 3 2 1

#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int data;
    struct ListNode *next;
};

struct ListNode *createlist();  // 这个时候就没有哨兵节点了

int main()
{
    struct ListNode *p, *head = NULL;

    head = createlist();
    for ( p = head; p != NULL; p = p->next )
        printf("%d ", p->data);
    printf("\n");

    return 0;
}

struct ListNode *createlist(){
    int curr = 0;
    scanf("%d", &curr);

    struct ListNode *head = NULL;
    while (curr != -1){
        struct ListNode *newNode = (struct ListNode *) malloc(sizeof(struct ListNode));
        newNode->data = curr;
        newNode->next = head;
        head = newNode;
        scanf("%d", &curr);
    }
    return head;
};

1.3 插入元素

将x插入到以head为头节点的链表指针的第pos位置上
输入样例:
1 2 3 4 5 6 8 9 -1
7 7
输出样例
1 2 3 4 5 6 7 8 9

#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int data;
    struct ListNode *next;
};

struct ListNode *createlist(); // 带哨兵结点的创建链表
void insert(struct ListNode *head, int pos, int X); // 带哨兵结点的插入
void printlist( struct ListNode *head )
{
     struct ListNode *p = head->next;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode *head = NULL;
    int pos=0,X=0;
    head = createlist();
    scanf("%d %d", &pos, &X);
    insert(head, pos, X);
    printlist(head);

    return 0;
}

struct ListNode *createlist(){
    int curr = 0;
    scanf("%d", &curr);
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->data = NULL;
    head->next = NULL;
    struct ListNode* p = head;
    while (curr != -1){
        struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
        temp->data = curr;
        temp->next = NULL;
        p->next = temp;
        p = p->next;
        scanf("%d", &curr);
    }
    return head;
};

void insert(struct ListNode *head, int pos, int X){
    struct ListNode *pre = head;
    for (int i=0;i<pos-1;i++){
        pre = pre->next;
    }
    struct ListNode *newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
    newNode->data = X;
    newNode->next = pre->next;
    pre->next = newNode;
}

1.4 查找和删除元素

删除以head为头节点的链表指针上,所有数值为X的结点。其实是先查找然后删除。

输入样例:
10 11 10 12 10 -1
10
输出样例
11 12

#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int data;
    struct ListNode *next;
};

struct ListNode *createlist(); // 带哨兵结点的创建链表
void deleteItem(struct ListNode *head, int X); // 带哨兵结点的删除
void printlist( struct ListNode *head )
{
     struct ListNode *p = head->next;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode *head = NULL;
    int pos=0,X=0;
    head = createlist();
    scanf("%d",  &X);
    deleteItem(head, X);
    printlist(head);

    return 0;
}

struct ListNode *createlist(){
    int curr = 0;
    scanf("%d", &curr);
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->data = NULL;
    head->next = NULL;
    struct ListNode* p = head;
    while (curr != -1){
        struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
        temp->data = curr;
        temp->next = NULL;
        p->next = temp;
        p = p->next;
        scanf("%d", &curr);
    }
    return head;
};

void deleteItem(struct ListNode *head, int X){
    struct ListNode *pre = head;
    struct ListNode *p = pre->next;
    while (p){
        if (p->data == X){
            pre->next = pre->next->next;
            free(p);
            p = pre->next;
        } else {
            pre = pre->next;
            p = p->next;
        }
    }
}

1.5 单链表的反转

原始单链表.png
循环结束.png
1结点的next指向oldn结点.png
头结点指向newn结点.png

链表反转是个常考的操作,上图中展示了让单链表1->2->3->4->5->6->null反转前4个结点,变成4->3->2->1->5->6->null的过程。

其实就是使用三个指针newn, oldn, temp进行以下循环操作,直到反转完题目要求的结点个数

  1. temp记录old的下一个结点位置
  2. 然后让oldn结点往回指向newn
  3. 然后依次将newn,oldn向右移动一个结点,返回第1步

循环结束后,要处理head->next->nexthead->next 指向正确的位置

输入样例:
1 2 3 4 5 6 6 7 -1
输出样例
1 2 3 4 5 6 6 7
7 6 6 5 4 3 2 1

#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int data;
    struct ListNode *next;
};

struct ListNode *createlist();
struct ListNode *reverse( struct ListNode *head );

void printlist( struct ListNode *head )
{
     struct ListNode *p = head;
     while (p) {
           printf("%d ", p->data);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode *p, *head = NULL,*reHead=NULL;

    head = createlist();
    printlist(head);
    reHead = reverse(head);
    printlist(reHead);

    return 0;
}

struct ListNode *createlist(){
    int curr = 0;
    scanf("%d", &curr);
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->data = NULL;
    head->next = NULL;
    struct ListNode* p = head;
    while (curr != -1){
        struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
        temp->data = curr;
        temp->next = NULL;
        p->next = temp;
        p = p->next;
        scanf("%d", &curr);
    }
    return head->next;
};

struct ListNode *reverse( struct ListNode *head ){
    if (head==NULL){
        return NULL;
    }
    struct ListNode* phead = (struct ListNode*)malloc(sizeof(struct ListNode));
    phead->data = NULL;
    phead->next = head;
    struct ListNode* newn = phead->next;
    struct ListNode* oldn = newn->next;
    while (oldn){
        struct ListNode* temp = oldn->next;
        oldn->next = newn;
        newn = oldn;
        oldn = temp;
    }
    phead->next->next = oldn;
    phead->next = newn;
    return phead->next;
}

1.6 链表的合并

链表的合并操作很容易让人想到归并排序里的merge操作,本质上都一样,只不过这里是用指针进行操作,归并排序一般用数组进行操作。

L1和L2是给定的带头结点的单链表。要注意最后L1和L2要指向NULL。

输入样例

3
1 3 5
5
2 4 6 8 10

输出样例

1 2 3 4 5 6 8 10 
NULL
NULL
List Merge(List L1, List L2){
    List L = (List)malloc(sizeof(struct Node));
    L->Next = NULL;
    List p = L,p1=L1,p2=L2;
    p1 = p1->Next;
    p2 = p2->Next;
    while (p1 && p2){
        if (p1->Data <=p2->Data){
            p->Next = p1;
            p1 = p1->Next;
            p = p->Next;
        } else {
            p->Next = p2;
            p2 = p2->Next;
            p = p->Next;
        }
    }
    if (p1){
        p->Next = p1;
    }
    if (p2){
        p->Next = p2;
    }
    L1->Next = NULL;
    L2->Next = NULL;
    return L;
}

1.7 快慢指针

1.7.1 快慢指针解决单链表回文问题

leetcode-234:回文链表
请判断一个链表是否为回文链表。

示例 1:

输入: 1->2
输出: false
示例 2:

输入: 1->2->2->1
输出: true

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct ListNode {
    int val;
    struct ListNode *next;
};

struct ListNode *createlist(); // 不带头结点的创建链表
bool isPalindrome(struct ListNode* head); // 判断是否是回文单链表
void printlist( struct ListNode *head )
{
     struct ListNode *p = head;
     while (p) {
           printf("%d ", p->val);
           p = p->next;
     }
     printf("\n");
}

int main()
{
    struct ListNode *head = NULL;
    head = createlist();

    bool ans = isPalindrome(head);
    if (ans){
        printf("true");
    } else {
        printf("false");
    }
    return 0;
}

struct ListNode *createlist(){
    int curr = 0;
    scanf("%d", &curr);
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    head->val = NULL;
    head->next = NULL;
    struct ListNode* p = head;
    while (curr != -1){
        struct ListNode* temp = (struct ListNode*)malloc(sizeof(struct ListNode));
        temp->val = curr;
        temp->next = NULL;
        p->next = temp;
        p = p->next;
        scanf("%d", &curr);
    }
    return head->next;
};


bool isPalindrome(struct ListNode* head){
    struct ListNode* fast = head, *slow = head;
    // fast ==NULL 偶数,slow指向链表1->2->2->1->NULL的第二个2
    // fast != NULL 奇数,slow指向链表1->2->3->2->1->NULL的3
    while (fast !=NULL && fast->next!=NULL){
        fast = fast->next->next;
        slow = slow->next;
    }
    if(fast!=NULL){ // 奇数时slow再向右一步
        slow = slow->next;
    }

    // 反转slow后面的链表
    struct ListNode* newn = NULL;
    struct ListNode* oldn = slow;
    while (oldn){
        struct ListNode* temp = oldn->next;
        oldn->next = newn;
        newn = oldn;
        oldn = temp;
    }

    // 比较
    struct ListNode* left = head;
    struct ListNode* right = newn;
    while (right){
        if (left->val != right->val){
            return false;
        }
        left = left->next;
        right = right->next;
    }
    return true;
}

1.7.2 快慢指针解决环形链表问题

判断是否有环
leetcode-141:环形链表
给定一个链表,判断链表中是否有环。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    struct ListNode *fast = head, *slow = head;
    while (fast && fast->next){
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow){
            return true;
        }
    }
    return false;
}

找到链表开始入环的第一个节点
leetcode-142: 环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast = head, *slow = head;
    while (fast && fast->next){
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow){
            break;
        }
    }
    if (fast == NULL || fast->next == NULL){
        return NULL;
    }
    slow = head;
    while (slow != fast){
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}

找到链表倒数第k个元素
leetcode:返回倒数第 k 个节点
leetcode:面试题22. 链表中倒数第k个节点
leetcode-19:删除链表的倒数第N个节点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


int kthToLast(struct ListNode* head, int k){
    struct ListNode* fast = head, *slow = head;
    while (k>0){
        fast = fast->next;
        k--;
    }
    while (fast){
        fast = fast->next;
        slow = slow->next;
    }
    return slow->val;
}

2 静态链表

动态链表使用指针来建立结点之间的关联关系,而当题目告诉你结点地址在5位数及以内时,可以使用静态链表。
静态链表其实就是使用结构体数组,数组中每个元素是一个包含数据、下一个地址的结构体。使用数组的方便之处在于,可以直接使用下标表示结点的地址,查询也快速。

02-线性结构3 Reversing Linked List (25分)

给定整数 K 和单链表 L, 你需要每K个元素把链表反转一次。

  • 例如给定链表 1→2→3→4→5→6, K=3,那么反转后的结果是3→2→1→6→5→4;
  • 如果 K=4, 输出结果是 4→3→2→1→5→6.
  • 要注意这道题会有多余结点不在链表上

样例输入

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

样例输出

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

这道题我用了两种方法。第一种方法偷懒,直接使用了c++的reverse() 方法,但是当时写完仍然不知道对单链表到底怎么反转。于是尝试用c写了第二种方法。

#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <vector> 
using namespace std;
#define MaxLen 100001 
struct node{
    int Addr;
    int num;
    int NextAddr;
};
typedef struct node Node;
Node nodes[MaxLen];
vector<Node> nodeList;
int main(){
    int firstAdd, N, K;
    scanf("%d %d %d", &firstAdd, &N,&K);
    while (N--){
        Node n;
        scanf("%d %d %d", &n.Addr, &n.num,&n.NextAddr);
        nodes[n.Addr] = n;
    }
    int address = firstAdd;
    while(address!=-1){
        nodeList.push_back(nodes[address]);
        address = nodes[address].NextAddr;
    }
    int len = nodeList.size();
    int period = len/K;
    for (int i=1;i<=period;i++){
        int head = (i-1)*K;
        int end = i*K;
        reverse(nodeList.begin()+head,nodeList.begin()+end);
    }

    for (int i=0;i<len-1;i++){
        nodeList[i].NextAddr = nodeList[i+1].Addr;
        printf("%05d %d %05d\n", nodeList[i].Addr,nodeList[i].num,nodeList[i].NextAddr);
    }
    nodeList[len-1].NextAddr =-1;
    printf("%05d %d %d", nodeList[len-1].Addr,nodeList[len-1].num,nodeList[len-1].NextAddr);
} 

c语言,手写反转链表

#include <stdlib.h>
#include <stdio.h>

struct node{
    int Addr;
    int num;
    int NextAddr;
};
typedef struct node Node;
Node nodes[100001];

int main(){
    // 读入
    int firstAdd, N, K;
    scanf("%d %d %d", &firstAdd, &N,&K);
    for (int i=0;i<N;i++){
        Node currNode;
        scanf("%d %d %d", &currNode.Addr, &currNode.num,&currNode.NextAddr);
        nodes[currNode.Addr] = currNode;
    }

    Node head;
    head.Addr = NULL;
    head.num = NULL;
    head.NextAddr = firstAdd;
    Node *currHead = &head; // 指向头节点,作为每次翻转的头指针

    // 获取真实结点个数,因为会有多余结点不在链表上
    Node *q = &head;
    int realN = 0;
    while (q && q->NextAddr!=-1){
        q = &nodes[q->NextAddr];
        realN++;
    }
    // 逆序
    int period = realN/K;
    while (period > 0 && K>1){ // 如果K=1就不需要做逆序
        Node *newn = &nodes[currHead->NextAddr];
        Node *oldn = &nodes[newn->NextAddr];
        int len = K;
        while (len>1){ // 4个结点翻转时,会有3个结点指向前一个结点
            Node *temp; // 依次3个相邻指针 newn,oldn,temp
            if (oldn->NextAddr!=-1){
                temp = &nodes[oldn->NextAddr];
            } else {
                temp = NULL;
            }

            oldn->NextAddr = newn->Addr;
            newn = oldn;
            oldn = temp;
            len--;
        }
        Node *temp2 = &nodes[currHead->NextAddr]; // 指向下一批要翻转结点的头节点
        if (oldn){
            nodes[currHead->NextAddr].NextAddr = oldn->Addr;
        } else {
            nodes[currHead->NextAddr].NextAddr = -1;
        }

        currHead->NextAddr = newn->Addr;
        if(period == realN/K){
            head.NextAddr = newn->Addr;
        }
        currHead = temp2;
        period--;
    }

     // 输出
    Node p = nodes[head.NextAddr];
    while(p.NextAddr != -1){
        printf("%05d %d %05d\n", p.Addr, p.num,p.NextAddr);
        p = nodes[p.NextAddr];
    }
    printf("%05d %d %d\n", p.Addr, p.num,p.NextAddr);
}

3 线性结构练习题

02-线性结构2 一元多项式的乘法与加法运算 (20分)
设计函数分别求两个一元多项式的乘积与和。

输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。

输入样例:

4 3 4 -5 2  6 1  -2 0
3 5 20  -7 4  3 1

输出样例:

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

最开始我是用链表做的。链表的注意点有

  1. head节点是没有数据的,真正的第一个数据在head->Next节点里,这样写的目的是利用哨兵简化实现难度
  2. 指针指向一个不存在的地址时就会出现段错误
  3. 理解题意,题目说的是head->Next为NULL时,只需要输出0 0
  4. 当相加时俩系数相互抵消,那么这个节点也就不存在了
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode *List;
struct LNode{
    int co;
    int exp;
    List Next;
};

List PtrL;
List read(int n1){
    List pL1 = (List) malloc(sizeof(struct LNode));
    pL1->Next = NULL;
    List t = pL1;
    for (int i=0;i<n1;i++){
        List a = (List) malloc(sizeof(struct LNode));
        a->Next = NULL;
        scanf("%d", &(a->co));
        scanf("%d", &(a->exp));
        t->Next = a;
        t = t->Next;
    }
    t->Next = NULL;
    return pL1;
}

void attach(int c, int e, List rear){
    List t = (List) malloc(sizeof(struct LNode));
    t->co = c;
    t->exp = e;
    t->Next = NULL;
    rear->Next = t;
    rear = t;
}

List Addp2(List L1,List L2){
    List r = (List) malloc(sizeof(struct LNode));
    r->Next = NULL;
    List curr = r;
    List p1 = L1->Next, p2=L2->Next;
    if (!p1 && !p2){
        return NULL;
    }
    while (p1 && p2){
        if (p1->exp > p2->exp){
            attach(p1->co, p1->exp, curr);
            p1 = p1->Next;
            curr = curr->Next;
        }
        else if (p1->exp < p2->exp){
            attach(p2->co, p2->exp, curr);
            p2 = p2->Next;
            curr = curr->Next;
        }
        else {
            int sum = 0;
            sum = p1->co+p2->co;
            if (sum){
                attach(sum, p2->exp, curr);
                curr = curr->Next;
            }
            p1 = p1->Next;
            p2 = p2->Next;  
        }
    }
    while (p1){
        attach(p1->co, p1->exp, curr);
        p1 = p1->Next;
        curr = curr->Next;
    }
    while (p2){
        attach(p2->co, p2->exp, curr);
        p2 = p2->Next;
        curr = curr->Next;
    }
    return r;
}
List Multiply(List pL1,List pL2){
    List p1 = pL1->Next, p2=pL2->Next;
    List sumHead = (List) malloc(sizeof(struct LNode));
    if (!p1 && !p2){
        return NULL;
    }
    List t = sumHead;
    while (p1){
        attach(p2->co * p1->co, p2->exp + p1->exp, t);
        p1 = p1->Next;
        t= t->Next;
    }
    p2 = p2->Next;
    while (p2){ // 当p2为NULL时退出循环
        p1 = pL1->Next;// p1重新回到起点 
        t = sumHead;
        while (p1){
            int c = p2->co * p1->co;
            int e = p2->exp + p1->exp;
            while (t->Next && t->Next->exp > e){
                t = t->Next;
            }
            if ((t->Next) && (t->Next->exp==e)){
                if (t->Next->co + c !=0){
                    t->Next->co+=c;
                } else {
                    List dis = t->Next;
                    t->Next = dis->Next;
                    free(dis);
                }
            }
            else {
                List insert = (List) malloc(sizeof(struct LNode));
                insert->co = c;
                insert->exp = e;
                insert->Next = t->Next;
                t->Next = insert;
                t = t->Next;
            }

            p1 = p1->Next;
        }
        p2 = p2->Next;
        
    }
    return sumHead;
}

void Display(List L){
    List p = L;

    p = p->Next;
    if (p==NULL){
        printf("0 0");
    }
    int flag = 0;
    while (p){
        if (flag==0){
            printf("%d %d", p->co, p->exp);
            flag = 1;
        } else {
            printf(" %d %d", p->co, p->exp);
        }
        p = p->Next;
    }
}

int main(){
    int n1=0,n2=0;
    scanf("%d", &n1);
    List pL1 = read(n1);
    scanf("%d", &n2);
    List pL2 = read(n2);
    
    List M = Multiply(pL1,pL2);
    Display(M);
    printf("\n");
    List A = Addp2(pL1,pL2);
    Display(A);
    return 0;
}

然后参考网上的方法使用结构数组和连续数组,其中连续数组的下标是指数exp,值是系数co

#include <stdio.h>
struct Poly{
    int ex;
    int co;
}Poly[1001];
int main(){
    int n1,n2,M[2005]={0},A[1001]={0};
    scanf("%d", &n1);
    for (int i=0;i<n1;i++){
        scanf("%d %d", &Poly[i].co,&Poly[i].ex);
        A[Poly[i].ex] += Poly[i].co;
    }
    
    int temp1,temp2;
    scanf("%d", &n2);
    for (int i=0;i<n2;i++){
        scanf("%d %d", &temp1,&temp2);
        A[temp2]+=temp1;
        for (int j=0;j<n1;j++){
            M[temp2+Poly[j].ex] += (temp1*Poly[j].co);
        }
    }
    int isFirst =1;// 1-是第一个输出
    int haveOutput = 0; // 0 不是零多项式
    for (int i=2001;i>=0;i--){
        if (M[i]!=0){
            if (!isFirst){
                printf(" %d %d", M[i],i);
            } else {
                isFirst = 0;
                printf("%d %d", M[i],i);
            }
            haveOutput = 1;
        }
    }
    if (!haveOutput){
        printf("0 0");
    }
    isFirst =1;
    haveOutput = 0;
    printf("\n");
    for (int i=1001;i>=0;i--){
        if (A[i]!=0){
            if (!isFirst){
                printf(" %d %d", A[i],i);
            } else {
                isFirst = 0;
                printf("%d %d", A[i],i);
            }
            haveOutput = 1;
        }
    }
    if (!haveOutput){
        printf("0 0");
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容