15个使用频率极高的基础算法题(附完整代码)

  1. 合并排序,将两个已经排序的数组合并成一个数组,当中一个数组能容下两个数组的全部元素

    一般来说,合并两个已经有序的数组。首先是开一个能存的下两个数组的第三个数组,可是题目中已经说了。当中一个数组能所有存的下,显然就不应该浪费空间了。

    从前往后扫的话,数据要存在大数组的前头,这样每次要把大数组的元素一次后移一位,显然不是什么好主意,所以我们从后往前存。

    #include<iostream>
    #include<cstdlib>
    using namespace std;
    
    int cc[10];
    int tt[5];
    
    void init()
    {
        srand((unsigned)time(NULL));
        int num = rand() % 5;
        for(int i = 0; i < 5; i++)
        {
            cc[i] = num;
            num += rand() % 10 + 1;
        }
        num = rand() % 5;
        for(int i = 0; i < 5; i++)
        {
            tt[i] = num;
            num += rand() % 10 + 1;
        }
    }
    
    void merge()
    {
        int i = 4, j = 4, idx = 9;
        while(i>=0 && j>=0)
        {
            if(cc[i] > tt[j])
                cc[idx--] = cc[i--];
            else
                cc[idx--] = tt[j--];
        }
        while(i>=0)
            cc[idx--] = cc[i--];
        while(j>=0)
            cc[idx--] = tt[j--];
    }
    
    int main()
    {
        init();
        for(int i = 0; i < 5; i++)
            printf("%d ", cc[i]);
        putchar(10);
        for(int i = 0; i < 5; i++)
            printf("%d ", tt[i]);
        putchar(10);
    
        merge();
    
        for(int i = 0; i < 10; i++)
            printf("%d ", cc[i]);
        putchar(10);
    
        getchar();
        return 0;
    }
  2. 合并两个已经排序的单链表

    不能创建第三条链表,用上两种办法进行合并

    #include <iostream>
    using namespace std;
    
    struct node{
        int data;
        node *next;
    };
    
    void CreateNode(node *head) // 创建带有头结点的有序单链表
    {
        node *s = head;
        int val = rand() % 5 + 1;
        for (int i = 0; i < 5; i++)
        {
            val += rand() % 5 + 1;
            node *t = new node;
            t->data = val;
            t->next = NULL;
            s = s->next = t;
        }
    }
    
    void PrintNode(node *head)
    {
        node *s = head;
        while (s = s->next)
            printf("%d ", s->data);
        putchar(10);
    }
    
    node* Merge_1(node *head1, node *head2) // 顺序扫描
    {
        node *i = head1->next;
        node *j = head2->next;
        node *cc = new node;
        node *s = cc;
        while(i && j)
        {
            if(i->data < j->data)
            {
                s = s->next = i;
                i = i->next;
            }
            else
            {
                s = s->next = j;
                j = j->next;
            }
        }
        if(i)
            s->next = i;
        else
            s->next = j;
        return cc;
    }
    
    node* Merge_2(node *head1, node *head2) // 递归法
    {
        if(head1 == NULL)
            return head2;
        if(head2 == NULL)
            return head1;
        node *cc = NULL;
        if(head1->data < head2->data)
        {
            cc = head1;
            cc->next = Merge_2(head1->next, head2);
        }
        else
        {
            cc = head2;
            cc->next = Merge_2(head1, head2->next);
        }
        return cc;
    }
    
    int main()
    {
        srand((unsigned)time(NULL));
    
        node *LinkList1 = new node, *LinkList2 = new node;
        CreateNode(LinkList1);
        CreateNode(LinkList2);
        PrintNode(LinkList1);
        PrintNode(LinkList2);
    
        // LinkList1 = Merge_1(LinkList1, LinkList2);
        LinkList1->next = Merge_2(LinkList1->next, LinkList2->next);
        PrintNode(LinkList1);   // 合并后的链表存在1中
    
        getchar();
        return 0;
    }
    
  3. 倒序打印一个单链表

    #include <iostream>
    using namespace std;
    
    struct node{
        int data;
        node *next;
    };
    
    void CreateNode(node *&head) // 创建不带头结点的有序单链表
    {
        head = new node;
        head->data = rand() % 5 + 1;
        node *s = head, *t = NULL;
        for(int i = 0; i < 5; i++)
        {
            t = new node;
            t->data = s->data + rand() % 5 + 1;
            s = s->next = t;
        }
        s->next = NULL;
    }
    
    void PrintNode(node *head)
    {
        node *s = head;
        while (s != NULL)
        {
            printf("%d ", s->data);
            s = s->next;
        }
        putchar(10);
    }
    
    void PrintNode_Reverse(node *head)
    {
        if(head->next != NULL)
            PrintNode_Reverse(head->next);
        printf("%d ", head->data);
    }
    
    int main()
    {
        srand((unsigned)time(NULL));
    
        node *LinkList;
    
        CreateNode(LinkList);
        PrintNode(LinkList);
        PrintNode_Reverse(LinkList);
    
        putchar(10);
        getchar();
        return 0;
    }
    
  4. 给定一个单链表的头指针和一个指定节点的指针。在O(1)时间删除该节点

    參见博客:怎样在O(1)的时间里删除单链表的结点

  5. 找到链表倒数第K个节点

    设两个指针。一个先向前走K步。然后两个指针同步移动,等先走的指针走到了末尾,后走的指针就在倒数第K个位置了。

    #include <iostream>
    using namespace std;
    
    struct node{
        int data;
        node *next;
    };
    
    void CreateNode(node *&head) // 创建不带头结点的有序单链表
    {
        head = new node;
        head->data = rand() % 5 + 1;
        node *s = head, *t = NULL;
        for(int i = 0; i < 10; i++)
        {
            t = new node;
            t->data = s->data + rand() % 5 + 1;
            s = s->next = t;
        }
        s->next = NULL;
    }
    
    void PrintNode(node *head)
    {
        node *s = head;
        while (s != NULL)
        {
            printf("%d ", s->data);
            s = s->next;
        }
        putchar(10);
    }
    
    void find(node *head, int num)
    {
        node *s = head, *t = head;
        for(int i = 0; i < num; i++)
            t = t->next;
        while(t)
        {
            s = s->next;
            t = t->next;
        }
        printf("place: %dth value:%d\n", num, s->data);
    }
    
    int main()
    {
        srand((unsigned)time(NULL));
    
        node *LinkList;
    
        CreateNode(LinkList);
        PrintNode(LinkList);
        find(LinkList, 5);
        find(LinkList, 3);
    
        putchar(10);
        getchar();
        return 0;
    }
    
  6. 反转单链表

    用递归与非递归两种方法,注意检查链表仅仅有一个结点的时候反转函数不会出错

    #include <iostream>
    using namespace std;
    
    struct node{
        int data;
        node *next;
    };
    
    void CreateNode(node *&head) // 创建不带头结点的有序单链表
    {
        head = new node;
        head->data = rand() % 5 + 1;
        node *s = head, *t = NULL;
        for(int i = 0; i < 10; i++)
        {
            t = new node;
            t->data = s->data + rand() % 5 + 1;
            s = s->next = t;
        }
        s->next = NULL;
    }
    
    void PrintNode(node *head)
    {
        node *s = head;
        while (s != NULL)
        {
            printf("%d ", s->data);
            s = s->next;
        }
        putchar(10);
    }
    
    node* Reverse_1(node *head)  // 非递归
    {
        node *s = head, *t = head->next;
        s->next = NULL;
        while(t != NULL)
        {
            node *r = t->next;
            t->next = s;
            s = t;
            t = r;
        }
        return s;
    }
    
    void Reverse_2(node *front, node *n, node *&head)  // 递归
    {
        front->next = NULL;
        if(n != NULL)
            head = n;
        if(n != NULL && n->next != NULL)
            Reverse_2(n, n->next, head);
        if(n != NULL)
            n->next = front;
    }
    
    int main()
    {
        srand((unsigned)time(NULL));
    
        node *LinkList;
    
        CreateNode(LinkList);
        PrintNode(LinkList);
        LinkList = Reverse_1(LinkList);
        // Reverse_2(LinkList, LinkList->next, *&LinkList);
        PrintNode(LinkList);
    
        putchar(10);
        getchar();
        return 0;
    }
    
  7. 通过两个栈实现一个队列

    參见博客:用两个栈实现队列

  8. 二分查找

    #include <iostream>
    using namespace std;
    
    void BinarySearch(int cc[], int num, int key)// 数组, 数组个数, 待查数字
    {
        int i = 0, j = num;
        int cnt = 0, mid = 0;
        while(i < j)
        {
            cnt++;
            mid = (i + j) >> 1;
            if(cc[mid] == key)
            {
                printf("%d %s, index: %d\n", cnt, cnt==1?
    
    "time":"times", mid);
                return;
            }
            else if(cc[mid] < key)
                i = mid;
            else
                j = mid;
        }
    }
    
    int main()
    {
        int cc[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        BinarySearch(cc, 10, 3);
    
        getchar();
        return 0;
    }
    
  9. 高速排序

    两种稍微有些不一样的快排(传入參数不同)

    #include <iostream>
    using namespace std;
    
    int cc[10];
    
    void init()
    {
        srand((unsigned)time(NULL));
        for(int i = 0; i < 10; i++)
        {
            int idx = rand()%10;
            while(cc[idx])
                idx = rand()%10;
            cc[idx] = i+1;
        }
    }
    
    void show()
    {
        for(int i = 0; i < 10; i++)
            printf("%d ", cc[i]);
        putchar(10);
    }
    
    void QuickSort_1(int cc[], int num)
    {
        int s = 0, t = num-1;
        int base = cc[0];
        if(num <= 1)
            return;
        while(s < t)
        {
            while(t > s && cc[t] >= base)
                t--;
            cc[s] = cc[t];
            while(s < t && cc[s] <= base)
                s++;
            cc[t] = cc[s];
        }
        cc[s] = base;
        QuickSort(cc, s);
        QuickSort(cc+s+1, num-s-1);
    }
    
    void QuickSort_2(int cc[], int l, int r)
    {
        if(l >= r)
            return;
        int s = l, t = r;
        int base = cc[l];
        while(s < t)
        {
            while(t > s && cc[t] >= base)
                t--;
            cc[s] = cc[t];
            while(s < t && cc[s] <= base)
                s++;
            cc[t] = cc[s];
        }
        cc[s] = base;
        QuickSort_2(cc, l, s-1);
        QuickSort_2(cc, s+1, r);
    }
    
    int main()
    {
        init();
        show();
        //QuickSort_1(cc, sizeof(cc)/sizeof(int));
        QuickSort_2(cc, 0, sizeof(cc)/sizeof(int)-1);
        show();
    
        getchar();
        return 0;
    }
    
  10. 获得一个int型的数中二进制中的个数

    没明确这个题目的意思,我们就理解成两个小题好了:

    (1)求一个int型数字的二进制位数,如6->110->3位数

    (2)求这个int型数字的二进制中‘1‘的个数

    #include <iostream>
    using namespace std;
    
    int main()
    {
        int num;
        while(~scanf("%d", &num))
        {
            int bits = 0, cnt = 0;
            int val = num;
            while(val)
            {
                if(val & 1)
                    cnt++;
                bits++;
                val>>=1;
            }
            printf("%d has %d bit and %d '1' in binary\n", num, bits, cnt);
        }
        return 0;
    }
    
  11. 输入一个数组,实现一个函数。让全部奇数都在偶数前面

    #include <iostream>
    using namespace std;
    
    int cc[10];
    
    void init()
    {
        srand((unsigned)time(NULL));
        for(int i = 0; i < 10; i++)
        {
            int idx = rand()%10;
            while(cc[idx])
                idx = rand()%10;
            cc[idx] = i+1;
        }
    }
    
    void show()
    {
        for(int i = 0; i < 10; i++)
            printf("%d ", cc[i]);
        putchar(10);
    }
    
    void Sort(int cc[], int size)
    {
        int s = 0, t = size-1;
        while(s < t)
        {
            while(s < t && (cc[s]&1))
                s++;
            while(t > s && !(cc[t]&1))
                t--;
            cc[s] ^= cc[t];
            cc[t] ^= cc[s];
            cc[s] ^= cc[t];
        }
    }
    
    int main()
    {
        init();
        show();
        Sort(cc, sizeof(cc)/sizeof(int));
        show();
    
        getchar();
        return 0;
    }
    
  12. 推断一个字符串是否是还有一个字符串的子串

    经典问题,用KMP算法。

    #include <iostream>
    using namespace std;
    
    char t[1000];
    char p[100];
    int f[100];
    
    int cnt = 0;
    
    void KMP()  //须要使用的參数是char t[]长串, char p[]模式串.
    {
        int n = strlen(t);
        int m = strlen(p);
        /////计算模式串的失配边
        f[0] = f[1] = 0;
        for(int i = 1; i < m; i ++)
        {
            int j = f[i];
            while(j && p[i] != p[j])j = f[j];
            f[i+1] = p[i] == p[j]?j+1:0;
        }
    
        int j = 0;
        for(int i = 0; i < n; i ++)
        {
            while(j && t[i] != p[j]) j = f[j];
            if(p[j] == t[i])j ++;
            if(j == m)    //匹配成功
                cnt ++;
        }
    }
    
    int main()
    {
        cnt = 0;
        gets(t);
        gets(p);
        KMP();
        if(cnt >= 1)
            printf("match!\n");
        else
            printf("not match!\n");
        getchar();
        return 0;
    }
  13. 把一个int型数组中的数字拼成一个串,这个串代表的数字最小

    关键就是要把int数组排个序,排序的cmp代码应该这样:假设两个数是A和B,那么应该比較AB和BA的大小,比如12、15。就要比較1215和1512的大小了。所以为了方便我们把int先转成char型,这样比較的时候直接strcat很方便。

    #include <iostream>
    using namespace std;
    
    void CreateArray(int *cc, int num)
    {
        srand((unsigned int)time(NULL));
        for(int i = 0; i < num; i++)
            cc[i] = rand() % 50;
    }
    
    int cmp(const void *a, const void *b)
    {
        char *s1 = new char[10];
        char *s2 = new char[10];
        strcpy(s1, *(char**)a);
        strcat(s1, *(char**)b);
    
        strcpy(s2, *(char**)b);
        strcat(s2, *(char**)a);
        return strcmp(s1, s2);
    }
    
    void ConvertToMinString(int *cc, int len)
    {
        char** str = (char**)new int[len];
        for(int i = 0; i < len; i++)
        {
            str[i] = new char[5];
            sprintf(str[i], "%d", cc[i]);
        }
        qsort(str, len, sizeof(char*), cmp);
        for(int i = 0; i < len; i++)
            printf("%s ", str[i]);
        putchar(10);
    }
    
    int main()
    {
        int cc[5];
        CreateArray(cc, 5);
        ConvertToMinString(cc, 5);
        getchar();
        return 0;
    }
  14. 输入一颗二叉树。输出它的镜像(每一个节点的左右子节点交换位置)

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFjdHJveA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

    用上递归和非递归两种方法。

    #include <iostream>
    #include <queue>
    using namespace std;
    
    struct node{
        int val;
        node *left;
        node *right;
    };
    
    void insert(node *&root, int data)
    {
        if(root == NULL)
        {
            root = new node;
            root->val = data;
            root->left = root->right = NULL;
            return;
        }
        if(root->val > data)
            insert(root->left, data);
        else
            insert(root->right, data);
    }
    
    node* build()
    {
        node *root = NULL;
        insert(root, 10);
        for(int i = 8; i <= 12; i++)
        {
            if(i == 10)continue;
            insert(root, i);
        }
        return root;
    }
    
    void showTree(node *root)
    {
        if(root == NULL) return;
        printf("%d ", root->val);
        showTree(root->left);
        showTree(root->right);
    }
    
    void Mirror_1(node *&root)    // 递归方法
    {
        if(root == NULL) return;
        node *t = root->left;
        root->left = root->right;
        root->right = t;
        Mirror_1(root->left);
        Mirror_1(root->right);
    }
    
    void Mirror_2(node *&root)     // 非递归方法
    {
        queue<node*> q;
        if(root != NULL)
            q.push(root);
        while(!q.empty())
        {
            node *n = q.front();
            q.pop();
            node *t = n->left;
            n->left = n->right;
            n->right = t;
            if(n->left != NULL)
                q.push(n->left);
            if(n->right != NULL)
                q.push(n->right);
        }
    }
    
    int main()
    {
        node *root = build();
        showTree(root);putchar(10);
    
        Mirror_1(root);
        showTree(root);putchar(10);
    
        Mirror_2(root);
        showTree(root);putchar(10);
        
        getchar();
        return 0;
    }
    
  15. 输入两个链表,找到它们第一个公共节点

    也就是说这两个链表的形状就像“Y”一样。

    我想到了两种办法:

    ①两个链表先分别枚举一遍,计算出两个链表的长度,如果是N和M。如果长链是N的长度,即N>=M,让长链先走N-M步。短链指针先不走,这样两个指针到结尾的距离都同样了,然后两个指针一边同步走一边进行比較,什么时候两个指针同样,当前节点就是第一个公共节点了。

    时间复杂度:O(n+m)

    ②设一个map或者其它键值对(哈希表),然后第一个链表走一步。依据其地址或主键建立索引,第二个链表走一步。依据其地址或主键建立索引。两个链表在遍历的时候分别去检索索引。什么时候发现已经记录了,那么当前节点就是第一个公共节点了。如果两个链表在相交之前的长度各自是N和M,则空间复杂度是O(max(n, m)*2)。其时间复杂度是O(max(n, m) * 2)。

    相比之下我觉得②要好的多,毕竟时间相比于空间重要太多了。所以以下我给出了②的代码,用地址作为索引。事实上我觉得怎样创建这样交叉的链表和怎样存储指针地址也能够作为一个题目哈。

    #include <iostream>
    #include <map>
    using namespace std;
    
    struct node{
        int val;
        node *next;
    };
    
    node* buildFirTree()    // 第一个链表有20个节点
    {
        node *root = new node;
        root->val = 1;
    
        node *s = root, *t = root;
        for(int i = 2; i <= 20; i++)
        {
            t = new node;
            t->val = i;
            s = s->next = t;
        }
        s->next = NULL;
        return root;
    }
    
    node* buildSecTree(node *firnode)// 第二个链表创建5个结点,然后接到第一个链表的第8个结点上
    {
        node *root = new node;
        root->val = 11;
        node *s = root, *t = root;
        for(int i = 2; i <= 5; i++)
        {
            t = new node;
            t->val = 10 + i;
            s = s->next = t;
        }
        node *k = firnode;
        for(int i = 0; i < 7; i++)
            k = k->next;
        s->next = k;
        return root;
    }
    
    void disp(node *root)
    {
        node *t = root;
        while(t)
        {
            printf("%d ", t->val);
            t = t->next;
        }
        putchar(10);
    }
    
    node *GetFirstCommonNode(node *fir, node *sec)
    {
        map<long, bool> mp;
        mp.clear();
    
        while(fir && sec)
        {
            if(mp[(long)fir] == true)
                return fir;
            mp[(long)fir] = true;
            fir = fir->next;
    
            if(mp[(long)sec] == true)
                return sec;
            mp[(long)sec] = true;
            sec = sec->next;
        }
        return NULL;
    }
    
    int main()
    {
        node *fir = buildFirTree();
        printf("First linklist: ");disp(fir);
        node *sec = buildSecTree(fir);
        printf("second linklist: ");disp(sec);
    
        node *common = GetFirstCommonNode(fir, sec);
        if(common != NULL)
            printf("common node is: %d\n", common->val);
        else
            printf("There is no common node\n");
    
        getchar();
        return 0;
    }
时间: 2024-10-13 01:54:17

15个使用频率极高的基础算法题(附完整代码)的相关文章

15道使用频率极高的基础算法题

1.合并排序,将两个已经排序的数组合并成一个数组,其中一个数组能容下两个数组的所有元素; 合并排序一般的思路都是创建一个更大数组C,刚好容纳两个数组的元素,先是一个while循环比较,将其中一个数组A比较完成,将另一个数组B中所有的小于前一个数组A的数及A中所有的数按顺序存入C中,再将A中剩下的数存入C中,但这里是已经有一个数组能存下两个数组的全部元素,就不用在创建数组了,但只能从后往前面存,从前往后存,要移动元素很麻烦. void MergeArray(int a[], int alen, i

fcc 基础算法题

fcc 基础算法题 fcc Reverse a String 翻转字符串 先把字符串转化成数组,再借助数组的reverse方法翻转数组顺序,最后把数组转化成字符串. function reverseString(str) { var arr =str.split(""); //string.split("");以""分割字符串 并返回新的数组 不改变原字符串 arr.reverse(); //反转数组 返回数组的引用 改变原数组 arr = ar

基础算法题-----百元买百鸡

基础算法题-–百元买百鸡 题目:公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱,用100文钱买一百只鸡,其中公鸡,母鸡,小鸡都必须要有,问公鸡,母鸡,小鸡要买多少只刚好凑足100文钱. 首先来分析一下: 设公鸡为x只,母鸡为y只,小鸡为z只,可的 x+y+z=100 5x+3y+z/3=100 由于每种鸡最少1只,所以公鸡最多能有(100 - 3 - 1) / 5只,母鸡最多能有(100 - 5 - 1) / 3只 至此我们便可以编码实现了 // 买公鸡最大数量 int gongJI = (10

MongoDB实战开发 【零基础学习,附完整Asp.net示例】

MongoDB实战开发 [零基础学习,附完整Asp.net示例] 阅读目录 开始 下载MongoDB,并启动它 在C#使用MongoDB 重构(简化)代码 使用MongoDB的客户端查看数据 使用MongoDB的客户端维护数据 MongoDB提供的C#驱动 MongoDB不支持在查询数据库时使用Join操作 获取MongoDB服务端状态 [目标]:本文将以实战的形式,向您展示如何用C#访问MongoDB,完成常见的数据库操作任务, 同时,也将介绍MongoDB的客户端(命令行工作模式)以及一些基

java基础算法题

为了提高自己的代码能力和算法能力,我决定每天学习一道算法题,吸收前辈思想. [程序1] TestRabbit.java 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 程序分析:兔子数量的规律为数列:1,1,2,3,5,8,13.....其实就是斐波那契数列  使用递归就可以实现 1 /** 2 * 兔子问题 3 * 2016/5/9 4 * 斐波那契数列求值 5 *题目:古典问题:有一对兔子,

EXCEL的VLOOKUP函数(使用频率极高,适用于各种需要数据分析的场合)

爬虫爬到的基础数据,假设如下: 使用VLOOKUP函数整理数据: 加入筛选条件: 加入新的统计参数,区域 重新分析 加入新列的数据:

链表【基础算法题】

题目一 代码实现 1 package class_03; 2 3 public class Code_07_ReverseList { 4 5 public static class Node { 6 public int value; 7 public Node next; 8 9 public Node(int data) { 10 this.value = data; 11 } 12 } 13 14 public static Node reverseList(Node head) { 1

Js基础算法题

1.字符串翻转 1 要求:先把字符串转化成数组,再借助数组的reverse方法翻转数组顺序,最后把数组转化成字符串 2 3 function reverseString(str) { 4 str=str.split('').reverse().join(''); 5 return str; 6 } 7 reverseString("hello"); 8 //split方法把字符串转换成数组 9 //reverse方法翻转数组顺序 10 //join 方法来把数组转换成字符串 2.如果给

FCC JS基础算法题(2):Check for Palindromes(检查回文字符串)

题目描述: 如果给定的字符串是回文,返回true,反之,返回false.如果一个字符串忽略标点符号.大小写和空格,正着读和反着读一模一样,那么这个字符串就是palindrome(回文).注意你需要去掉字符串多余的标点符号和空格,然后把字符串转化成小写来验证此字符串是否为回文.函数参数的值可以为"racecar","RaceCar"和"race CAR". 算法: function palindrome(str) { var str_obj = s