• 9.15开始


    1.

    写一个程序, 要求功能:求出用1,2,5这三个数不同个数组合的和为100的组合个数。

    如:100个1是一个组合,5个1加19个5是一个组合。。。。 请用C++语言写。

    解决方案:

    普通方法大家都会:

    int main(){
        int cnt = 0;
        for(int i = 0; i <= 100; i ++){
            for(int j = 0; j <= 50; j ++){
                for(int k = 0; k <= 20; k ++){
                    if(i + 2 * j + 5 * k == 100)
                        cnt ++;
                }
            }
        }
        printf("%d
    ", cnt);
        return 0;
    }
    View Code

    但是这循环是101*51*21次,复杂度大

    由题知:假设X为1的个数,Y为2的个数,Z为5的个数,那么满足X+2*Y+5*Z = 100

    所以X+5*Z = 100 - 2*Y,很明显X+5*Z是一个偶数,并且Z是<=20的,那么对Z做循环

    Z=0, X=100,98,...,0

    Z=1,X=95,93,...,1

    Z=2,X=90,88,...0

    .

    .

    .

    Z=19,X=5,3,1

    Z=20,X=0

    所以结果只要求出100以内的偶数,95以内的奇数...最后是5以内的奇数再加一次就行了

    对于一个奇数N求0到N之间的奇数个数为N/2+1,同样的偶数个数为N/2+1

    代码如下:

    int main(){
        int sum = 0;
        for(int i = 0; i <= 100; i += 5){
            sum += (100 - i) / 2 + 1;
        }
        printf("%d
    ", sum);
        return 0;
    }
    View Code

    2.

    写一个链表,删除一个结构体中指定的结点

    解决方案:

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    
    
    struct stu{
        int age;
        stu *next;
    }*list;
    struct stu *creatlist(int n){
        stu *h, *p, *s;
        h = new stu;
        h->next = NULL;
        p = h;
        for(int i = 0; i < n; i ++){
            s = new stu;
            p->next = s;
            scanf("%d", &s->age);
            s->next = NULL;
            p = s;
        }
        return h;
    }
    void output(stu *s){
        s = s->next;
        while(s != NULL){
            printf("%d ", s->age);
            s = s->next;
        }
        puts("");
    }
    void deletelist(stu *h, int age){
        stu *p = h;
        stu *s = h->next;
        while(s != NULL){
            if(s->age == age){
                p->next = s->next;
                s = s->next;
            }
            else{
                p = p->next;
                s = s->next;
            }        
        }
    }
    int main(){
        int n;
        scanf("%d", &n);
        stu *s = creatlist(n);
        //output(s->next);
        int age;
        scanf("%d", &age);
        deletelist(s, age);
        output(s);
        return 0;
    }
    View Code

     3.

    将二叉树的两个孩子换位置,即左变右,右变左。不能用递规

    解决方案:

    1)根结点入队列

    2)取队首元素并出列,并将该元素左右儿子进行交换

    3)如果队列不为空则跳到步骤2

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <queue>
    using namespace std;
    
    
    struct tree{
        tree *right;
        tree *left;    
    }*list;
    void solve(tree *list){
        queue <tree*> Q;
        Q.push(list);
        while(!Q.empty()){
            tree *tmp = Q.front();
            Q.pop();
            swap(tmp->right, tmp->left);
            if(tmp->right != NULL)
                Q.push(tmp->right);
            if(tmp->left != NULL)
                Q.push(tmp->left);
        }
    }
    View Code

     4.

    38头牛中选出3头跑得最快的,使用一个每次只能供6头比赛的场地,要求用最快的方法

    解决方案:

    38只取6只一组,6*6,取前3名,得3*6+2=20,用了6次

    20只取5只一组,取前3名,得到3*4=12,用了4次

    12只分两组取前3名,得3*2=6,用了2次

    最后再加1次

    累计13次

    5.

    n1开始,每个操作可以选择对n1或者对n加倍。若想获得整数2013,最少需要多少个操作

    解决方案:

    直接进行计算,奇数减1除2,偶数直接除以2,2013>1006>503>251>125>62>31>15>7>3>1

    再反过来计算从1到2013的次数,为18次

     6.

    如下函数,在32bit系统foo(2^31-3)的值是:

    Int foo(int x)
    {

    Return x&-x;

    }

    解决方案:

    这题是先计算31-3再计算2异或28的,然后进行 x & -x

    对于x & -x的含义:返回值为0,表示x=0;返回值为1,表示x为奇数;返回值为其他数,表示x为x与2^64的最大公约数,即二进制中从右到左的第一个1出现的位数

    扩展:x & (x-1) 表示x进进制中1的个数,每执行一次x = x&(x-1),会将x用二进制表示时最右边的一个1变为0,因为x-1将会将该位(x用二进制表示时最右边的一个1)变为0

      所以可通过这个求得一个数是不是2的n次方,代码如下

    int func(int x)
    {
        if( (x&(x-1)) == 0 )
            return 1;
        else
            return 0;
    }
    
    int main()
    {
        int x = 8;
        printf("%d
    ", func(x));
    }
    View Code

     7.

    给两个单向链表,求是否有公共节点并求该公共节点,要求使用空间最小算法

    解决方案:

    将链表A遍历以及链表B遍历,分别保存最后一个节点以及他们长度,若相同再证明有公共节点

    如果他们长度相等,依次遍历就行,如果长度不等,将长度长的先遍历|len_a - len_b|(表示绝对值)

    如图

     9.

    static静态在申请的时候不分配内存

    struct A{
        A() {}
        ~A() {}
        int m1;
        int m2;
    };
    struct B{
        B() {}
        ~B() {}
        int m1;
        char m2;
        static char m3;
    };
    struct C{
        C() {}
        virtual~C() {}
        int m1;
        short m2;
    };
    
    int main(){
        printf("%d %d %d
    ", sizeof A, sizeof B, sizeof C);
        return 0;
    }
    View Code

    输出的是:8 8 12

     10.

    定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数minpush以及pop的时间复杂度都是O(1)

    解决方案:这题难点在于pop一个元素之后,怎样确定栈中的最小元素,然后查找就要遍历显示不行,

    那么就设定一个辅助栈,将每次数据栈中最小的元素依次入栈,见代码(考虑整型)

    #include <cstdio>
    #include <cstring>
    #include <stack>
    using namespace std;
    
    
    class Stack
    {
    public:
        void push(int num){
            data_stack.push(num);
            if(!min_stack.size())
                min_stack.push(num);
            else
                if(num <= min_stack.top())
                    min_stack.push(num);
        }
        void pop(){
            if(data_stack.top() == min_stack.top())
                min_stack.pop();
            data_stack.pop();
        }
        void output(){
            printf("%d
    ", min_stack.top());
        }
    protected:
    private:
        stack <int > data_stack;
        stack <int > min_stack;
    };
    
    int main(){
        Stack s;
        s.push(3);
        s.output();
        s.push(4);
        s.output();
        s.push(2);
        s.output();
        s.push(1);
        s.output();
        s.pop();
        s.output();
        s.pop();
        s.output();
        s.push(0);
        s.output();
        return 0;
    }
    View Code

     11.

    求最大子和段

    解决方案:从第一个数开始加,如果碰到和为负数则置0,否则和max值比较取最大值

    #include <cstdio>
    #include <cstring>
    #include <stack>
    using namespace std;
    
    
    int a[8] = {1, -2, 3, 10, -4, 7, 2, -5};
    int main(){
        int sum = a[0], max = a[0];
        for(int i = 1; i < 8; i ++){
            if(sum + a[i] < 0) sum = 0;
            else sum += a[i];
            if(max < sum)
                max = sum;
        }
        printf("%d
    ", max);
        return 0;
    }
    View Code

     12.

    查找最小的k个元素

    解决方案:

    朴素方案或者遍历选择最小K个或者快速排序选择前K个,复杂度略高

    可以先插入K个到数组中,然后每插入一个数和前K个比较,比最大的小才插入并删除最大的

    如何做到在K个当中查找最大的,可以用一个最大堆,或者用第10题两个栈的做法(个人认为可以,只是弹栈的要换一种方式了)

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    
    multiset <int > m;
    int main(){
        m.clear();
        m.insert(3);
        m.insert(5);
        m.insert(4);
        m.insert(1);
        m.insert(7);
        m.insert(8);
        m.insert(2);
        m.insert(6);
        for(multiset<int > :: iterator it= m.begin(); it != m.end(); it ++){
            cout<<*it<<endl;
        }
        return 0;
    }
    code1

    参考别人的

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    const int k = 5;
    const int maxn = 1000;
    int max_heap[k + 1];
    int ed, maxpos;
    
    void insert_min_heap(int data){
        int child = 0;
        if(ed == k + 1){
            if(data >= max_heap[1])
                return;
            max_heap[1] = data;
            for(int i = 1; i * 2 <= k; i = child){
                child = 2 * i;
                if((i * 2 + 1 <= k && max_heap[i*2] < max_heap[i*2+1])){
                    child ++;
                }
                if(max_heap[i] < max_heap[child])
                    swap(max_heap[i], max_heap[child]);
                else
                    break;
            }
            return;
        }
        max_heap[ed ++] = data;
        for(int i = ed - 1; i > 1; i /= 2){
            if(max_heap[i] > max_heap[i/2])
                swap(max_heap[i], max_heap[i/2]);
            else
                break;
        }
    }
    int main(){
        int n, data;
        ed = 1;
        while(~scanf("%d", &data)){
            insert_min_heap(data);
        }
        for(int i = 1; i <= k; i ++)
            printf("%d ", max_heap[i]);
        puts("");
    
        return 0;
    }
    code2

     13.

    写一个堆排序

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    int n, a[100];
    
    void init_heap(){
        for(int i = n; i; i --){
            int cur = i;
            while(true){
                int next = -1;
                if((cur * 2 <= n) && (next < 0 || a[cur*2] > a[next]))
                    next = cur * 2;
                if((cur * 2 + 1 <= n) && (a[cur*2+1] > a[next]))
                    next = cur * 2 + 1;
                if(next < 0 || a[next] <= a[cur])
                    break;
                else{
                    swap(a[cur], a[next]);
                    cur = next;
                }
            }
        }
    }
    void heap_sort(){
        for(int i = n; i > 1; i --){
            swap(a[1], a[i]);
            int cur = 1;
            while(true){
                int next = -1;
                if((cur * 2 < i) && (next < 0 || a[cur*2] > a[next]))
                    next = cur * 2;
                if((cur * 2 + 1 < i) && (a[cur*2+1] > a[next]))
                    next = cur * 2 + 1;
                if(next < 0 || a[next] <= a[cur])
                    break;
                else{
                    swap(a[cur], a[next]);
                    cur = next;
                }
            }
        }
    }
    
    int main(){
        scanf("%d
    ", &n);
        for(int i = 1; i <= n; i ++)
            scanf("%d", a + i);
        init_heap();
        heap_sort();
        for(int i = 1; i <= n; i ++){
            printf("%d%c", a[i], i < n ? ' ' : '
    ');
        }
    }
    View Code

     14.

    前序中序后序遍历,创建二叉树时采用队列实现层序遍历创建

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    struct Node{
        int num;
        Node *l, *r;
    };
    queue <Node * > Q;
    void creat_tree(Node *p, int num, int &f){
        Node *s = new Node;
        s->num = num;
        s->l = s->r = NULL;
        if(f == 1){
            p->l = s;
            f = 2;
            Q.push(s);
            return;
        }
        p->r = s;
        f = 1;
        Q.push(s);
        Q.pop();
    }
    void dlr_output(Node *p){
        if(p == NULL) return;
        printf("%d ", p->num);
        dlr_output(p->l);
        dlr_output(p->r);
    }
    void ldr_output(Node *p){
        if(p == NULL) return;    
        ldr_output(p->l);
        printf("%d ", p->num);
        ldr_output(p->r);
    }
    void lrd_output(Node *p){
        if(p == NULL) return;
        lrd_output(p->l);
        lrd_output(p->r);
        printf("%d ", p->num);
    }
    int main(){
        Node *root = new Node;
        Node *p = new Node;
        int f = 0;
        int num;
        while(!Q.empty()) Q.pop();//清空队列
        while(~scanf("%d", &num)){
            if(f == 0){
                root->num = num;
                root->l = NULL;
                root->r = NULL;
                f = 1;
                p = root;
                Q.push(p);
                continue;
            }
            p = Q.front();
            creat_tree(p, num, f);
        }
        dlr_output(root);puts("");
        ldr_output(root);puts("");
        lrd_output(root);puts("");
        return 0;
    }
    递归
    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    
    
    struct TreeNode{
        int value;
        TreeNode *left;
        TreeNode *right;
    };
    TreeNode *creatTreeNode(int m){
        TreeNode *node = new TreeNode;
        node->value = m;
        node->right = node->left = NULL;
        return node;
    }
    void DestroyTree(TreeNode *root){
        if(root != NULL){
            TreeNode *l = root->left;
            TreeNode *r = root->right;
            delete root;
            root = NULL;
            DestroyTree(l);
            DestroyTree(r);
        }
    }
    void connectTree(TreeNode *root, TreeNode *l, TreeNode *r){
        if(root != NULL){
            root->left = l;
            root->right = r;
        }
    }
    void solve(TreeNode *root);
    int main(){
        TreeNode *node1 = creatTreeNode(1);
        TreeNode *node2 = creatTreeNode(2);
        TreeNode *node3 = creatTreeNode(3);
        TreeNode *node4 = creatTreeNode(4);
        TreeNode *node5 = creatTreeNode(5);
        TreeNode *node6 = creatTreeNode(6);
        TreeNode *node7 = creatTreeNode(7);
        connectTree(node1, node2, node3);
        connectTree(node2, node4, node5);
        connectTree(node3, node6, node7);
        solve(node1);
        //DestroyTree(node1);
        return 0;
    }
    
    void dlr(TreeNode *root){
        if(!root) return;
        stack <TreeNode* > sta;
        TreeNode *tmp = root;
        while(tmp != NULL || !sta.empty()){        
            while(tmp != NULL){
                printf("%d ", tmp->value);
                sta.push(tmp);
                tmp = tmp->left;
            }
            if(!sta.empty()){
                tmp = sta.top();
                sta.pop();
                tmp = tmp->right;
            }
        }
        puts("");
    }
    void ldr(TreeNode *root){
        if(!root) return;
        stack <TreeNode* > sta;
        TreeNode *tmp = root;
        while(tmp != NULL || !sta.empty()){
            while(tmp != NULL){
                sta.push(tmp);
                tmp = tmp->left;
            }
            if(!sta.empty()){
                tmp = sta.top();
                sta.pop();
                printf("%d ", tmp->value);
                tmp = tmp->right;
            }
        }
        puts("");
    }
    void lrd(TreeNode *root){
        if(!root) return;
        stack <TreeNode* > sta;
        TreeNode *cur, *pre = NULL;
        sta.push(root);
        while(!sta.empty()){
            cur = sta.top();
            if( (cur->left == NULL && cur->right ==NULL) ||
                (pre != NULL && (pre == cur->left || pre == cur->right))){
                    printf("%d ", cur->value);
                    sta.pop();
                    pre = cur;
            }else{
                if(cur->right != NULL)
                    sta.push(cur->right);
                if(cur->left != NULL)
                    sta.push(cur->left);
            }
        }
        puts("");
    }
    void solve(TreeNode *root){
        dlr(root);
        ldr(root);
        lrd(root);
    }
    非递归

     15.

    查找链表中倒数第k个结点

    解决方案:

    设置两个指针,开始指向头结点,然后第一个移动并计数,当移动了k-1次另一指针开始移动,复杂度为o(n)

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    struct Node{
        int num;
        Node *next;
    };
    
    Node *insert(Node *p, int num){
        Node *s = new Node;
        s->num = num;
        s->next = NULL;
        p->next = s;
        return s;
    }
    int main(){
        int num;
        Node *root = new Node;
        Node *p = root;
        int k;
        scanf("%d", &k);
        while(~scanf("%d", &num)){
            p = insert(p, num);
        }
        int cnt = 0;
        Node *s1 = root;
        Node *s2 = root;
        while(s1 != NULL){
            cnt ++;
            if(cnt >= k + 1){
                s2 = s2->next;
            }
            s1 = s1->next;
        }
        printf("%d
    ", s2->num);
        return 0;
    }
    View Code

     16.

    在排序数组中查找和为给定值的两个数字

    解决方案:

    确定第一个和最后一个的和,假如相加大于给定的数,则较大数前移,小于则较小数后移,相等就输出

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    int a[100];
    int main(){
        int n;
        while(~scanf("%d", &n)){
            for(int i = 0; i < n; i ++)
                scanf("%d", a + i);
            int num;
            scanf("%d", &num);
            int st = 0, ed = n - 1;
            while(true){
                if(a[st] + a[ed] == num){
                    printf("%d %d
    ", a[st], a[ed]);
                    break;
                }else
                    if(a[st] + a[ed] > num)
                        ed --;
                    else 
                        st ++;
            }
        }
        return 0;
    }
    View Code

     17.

    O(logn)Fibonacci数列

    解决方案:

    (转) 

    下面介绍一种时间复杂度是O(logn)的方法。在介绍这种方法之前,先介绍一个数学公式:

    {f(n), f(n-1), f(n-1), f(n-2)} ={1, 1, 1,0}n-1

    (注:{f(n+1), f(n), f(n), f(n-1)}表示一个矩阵。在矩阵中第一行第一列是f(n+1),第一行第二列是f(n),第二行第一列是f(n),第二行第二列是f(n-1)。)

    有了这个公式,要求得f(n),我们只需要求得矩阵{1, 1, 1,0}的n-1次方,因为矩阵{1, 1, 1,0}的n-1次方的结果的第一行第一列就是f(n)。这个数学公式用数学归纳法不难证明。感兴趣的朋友不妨自己证明一下。

    现在的问题转换为求矩阵{1, 1, 1, 0}的乘方。如果简单第从0开始循环,n次方将需要n次运算,并不比前面的方法要快。但我们可以考虑乘方的如下性质:

    /  an/2*an/2                      n为偶数时
    an=
              a(n-1)/2*a(n-1)/2            n为奇数时

    要求得n次方,我们先求得n/2次方,再把n/2的结果平方一下。如果把求n次方的问题看成一个大问题,把求n/2看成一个较小的问题。这种把大问题分解成一个或多个小问题的思路我们称之为分治法。这样求n次方就只需要logn次运算了。

    实现这种方式时,首先需要定义一个2×2的矩阵,并且定义好矩阵的乘法以及乘方运算。当这些运算定义好了之后,剩下的事情就变得非常简单。完整的实现代码如下所示。

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    struct matrix2by2{
        matrix2by2(
            long long m00 = 0,
            long long m01 = 0,
            long long m10 = 0,
            long long m11 = 0
            )
            :m_00(m00), m_01(m01), m_10(m10), m_11(m11){}
    
        long long m_00;
        long long m_01;
        long long m_10;
        long long m_11;
    };
    matrix2by2 matrixmultiply(const matrix2by2 &a, const matrix2by2 &b){
        return matrix2by2(
            a.m_00 * b.m_00 + a.m_01 * b.m_10,
            a.m_00 * b.m_01 + a.m_01 * b.m_11,
            a.m_10 * b.m_00 + a.m_11 * b.m_10,
            a.m_10 * b.m_01 + a.m_11 * b.m_11
            );
    }
    matrix2by2 matrixpower(int n){
        matrix2by2 matrix;
        if(n == 1)
            matrix = matrix2by2(1, 1, 1, 0);
        else if(n % 2 == 0){
            matrix = matrixpower(n/2);
            matrix = matrixmultiply(matrix, matrix);
        }
        else if(n % 2 == 1){
            matrix = matrixpower((n-1)/2);
            matrix = matrixmultiply(matrix, matrix);
            matrix = matrixmultiply(matrix, matrix2by2(1, 1, 1, 0));
        }
        return matrix;
    }
    int main(){
        printf("%d
    ", matrixpower(10-1).m_00);
        return 0;
    }
    View Code

     18.

    定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。如把字符串abcdef左旋转2位得到字符串cdefab。请实现字符串左旋转的函数。要求时间对长度为n的字符串操作的复杂度为O(n),辅助内存为O(1)

    解决方案:

    假设这字符串简化为XY,刚分三次操作即可,X旋转,Y旋转,XY旋转

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    char s[] = "12345";
    int n = 5;
    int k = 2;
    
    void reversestring(char *st, char *ed){
        while(st < ed){
            char tmp = *st;
            *st = *ed;
            *ed = tmp;
    
            st ++;
            ed --;
        }
    }
    int main(){
        char *pst1 = s;
        char *ped1 = s + k - 1;
        char *pst2 = s + k;
        char *ped2 = s + n - 1;
        reversestring(pst1, ped1);
        reversestring(pst2, ped2);
        reversestring(pst1, ped2);
        printf("%s
    ", s);
        return 0;
    }
    View Code

     19.

    解决方案:从右上角开始查找,如果大就消除该列,如果小就消除该行

    (修改)

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    
    
    bool find(int *a, int rows, int cols, int num){
        int row = 0;
        int col = cols - 1;
      //  printf("%d %d %d
    ", a[0], num, a[rows * cols - 1]);
        for(int i = 0; i < rows; i ++){
            for(int j = 0; j < cols; j ++){
          //      printf("%d ", a[i * cols + j]);
            }
           // puts("");
        }
        if(a[0] > num || a[rows * cols - 1] < num)
            return false;
        //puts("asdf");
        while(row < rows && col >= 0){
            if(a[row * cols + col] == num)
                return true;
            if(a[row * cols + col] > num)
                col --;
            else row ++;
        }
        return false;
    }
    void test(){
        int a[][4] =  {{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
        bool ans = find((int*)a, 4, 4, 15);
        if( ans )
            puts("yes");
        else
            puts("no");
    }
    int main(){
        test();
        return 0;
    }
    View Code

     20.

    旋转数组二分查找

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    
    
    int a[111];
    void solve(int st, int ed, int num){
        int index1 = st, index2 = ed, mid = st;
        while(index1 <= index2){
            int mid = index1 + index2 >> 1;
            if(a[mid] == num){
                puts("yes");
                return;
            }
            if(a[mid] >= a[st]){
                if(num < a[mid] && num >= a[index1])
                    index2 = mid - 1;
                else
                    index1 = mid + 1;
            }else{
                if(num > a[mid] && num <= a[index2])
                    index1 = mid + 1;
                else
                    index2 = mid - 1;
            }
        }
        puts("no");
    }
    int main(){
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n; i ++)
            scanf("%d", a + i);
        int num;
        scanf("%d", &num);
        solve(0, n - 1, num);
        return 0;
    }
    View Code

     21.

    给一个数,打印从1到这个数位数的最大数字

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    
    
    void PrintNum(char *num){
        int len = strlen(num);
        bool f = 1;
        for(int i = 0; i < len; i ++){
            if(f && num[i] == '0')
                continue;
            else f = 0;
            putchar(num[i]);
        }
        printf("	");
    }
    bool Increment(char *num){
        bool isOverflow = false;
        int nTakeover = 0;
        int len = strlen(num);
        for(int i = len - 1; i >= 0; i --){
            int sum = num[i] - '0' + nTakeover;
            if(i == len - 1)
                sum ++;
            if(sum >= 10){
                if(i == 0)
                    isOverflow = true;
                else{
                    sum -= 10;
                    nTakeover = 1;
                    num[i] = '0' + sum;
                }
            }else{
                num[i] = '0' + sum;
                break;
            }
        }
        return isOverflow;
    }
    int main(){
        int n;
        scanf("%d", &n);
        char *num = new char [n + 1];
        memset(num, '0', n);
        num[n] = '';
        while(!Increment(num)){
            PrintNum(num);
        }
        delete [] num;
        return 0;
    }
    code2
    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    
    
    void PrintNum(char *num){
        int len = strlen(num);
        bool f = 1;
        for(int i = 0; i < len; i ++){
            if(f && num[i] == '0')
                continue;
            else f = 0;
            putchar(num[i]);
        }
        printf("	");
    }
    void f(char *num, int len, int index){
        if(index == len - 1){
            PrintNum(num);
            return;
        }
        for(int i = 0; i < 10; i ++){
            num[index + 1] = i + 48;
            f(num, len, index+1);
        }
    }
    int main(){
        int n;
        scanf("%d", &n);
        char *num = new char [n + 1];
        memset(num, '0', n);
        num[n] = '';
        for(int i = 0; i < 10; i ++){
            num[0] = i + 48;
            f(num, n, 0);
        }
        delete [] num;
        return 0;
    }
    code2

     22.

    判断一棵树是不是平衡二叉树

    解决方案:要想知道是不是平衡二叉树,就得先知道该点左右孩子深度之差,超过二就不是 了

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    struct TreeNode{
        int value;
        TreeNode *left;
        TreeNode *right;
    };
    TreeNode *creatTreeNode(int m){
        TreeNode *node = new TreeNode;
        node->value = m;
        node->right = node->left = NULL;
        return node;
    }
    void DestroyTree(TreeNode *root){
        if(root != NULL){
            TreeNode *l = root->left;
            TreeNode *r = root->right;
            delete root;
            root = NULL;
            DestroyTree(l);
            DestroyTree(r);
        }
    }
    void connectTree(TreeNode *root, TreeNode *l, TreeNode *r){
        if(root != NULL){
            root->left = l;
            root->right = r;
        }
    }
    bool fun(TreeNode *root, int &depth){
        if(root == NULL){
            depth = 0;
            return true;
        }
        int l_depth, r_depth;
        if(fun(root->left, l_depth) && fun(root->right, r_depth)){
            int diff = l_depth - r_depth;
            if(diff <= 1 && diff >= -1){
                depth = 1 + (l_depth > r_depth ? l_depth : r_depth);
                return true;
            }
        }
        return false;
    }
    
    int main(){
        TreeNode *node1 = creatTreeNode(1);
        TreeNode *node2 = creatTreeNode(2);
        TreeNode *node3 = creatTreeNode(3);
        TreeNode *node4 = creatTreeNode(4);
        TreeNode *node5 = creatTreeNode(5);
        TreeNode *node6 = creatTreeNode(6);
        TreeNode *node7 = creatTreeNode(7);
    
        connectTree(node1, node2, node3);
        connectTree(node2, node4, node5);
        connectTree(node3, node7, node6);
        //connectTree(node5, node7, NULL);
    
        int depth = 0;
        if(fun(node1, depth))
            puts("yes");
        else
            puts("no");
        printf("%d
    ", depth);
    
        DestroyTree(node1);
        return 0;
    }
    View Code

     23.

    统计一个排序数组中某一数字出现的次数

    解决方案:两次二分查找,第一次查询该数字最左边位置,第二次最右边,因为连续,所以差值+1就是该数字个数了

        二分查找时,要稍微处理下

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    int a[8] = {1,3,3,3,3,3,3,7};
    int len = 8;
    int getFirstK(int l, int r, int k){
        //int l = 0, r = len - 1;
        if(l > r) return -1;
        int mid = l + r >> 1;
        if(a[mid] == k){
            if((mid && a[mid - 1] != k) || mid == 0)
                return mid;
            else
                r = mid - 1;
        }else
            if(a[mid] < k)
                l = mid + 1;
            else
                r = mid - 1;
        return getFirstK(l, r, k);
    }
    int getLastK(int l, int r, int k){
        //int l = 0, r = len - 1;
        if(l > r) return -1;
        int mid = l + r >> 1;
        if(a[mid] == k){
            if((mid != len - 1 && a[mid + 1] != k) || mid == len - 1)
                return mid;
            else
                l = mid + 1;
        }else
            if(a[mid] < k)
                l = mid + 1;
            else
                r = mid - 1;
        return getLastK(l, r, k);
    }
    
    int main(){
        int first = getFirstK(0, len-1, 2);
        int last = getLastK(0, len-1, 2);
        if(first > -1 && last > -1)
            printf("%d
    ", last - first + 1);
        else
            puts("no");
        return 0;
    }
    View Code

    24.

    一个整型数组里除了两个数字之外,其他的数字都出现了两次,求这两个数字。时间O(n),空间O(1)

    解决方案:异或所有元素,求最右边的1,然后按这情况将数组分为两组

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    int a[8] = {2,4,3,6,3,2,5,5};
    int len = 8;
    bool is_ok(int num, int cnt){
        num = num >> cnt;
        return (num & 1);
    }
    int main(){
        int res = 0;
        for(int i = 0; i < len; i ++)
            res ^= a[i];
        int cnt = 0;
        while((res & 1) == 0 && cnt < 32){
            res = res >> 1;
            cnt ++;
        }    
        int ans1 = 0, ans2 = 0;
        for(int i = 0; i < len; i ++){
            if(is_ok(a[i], cnt))
                ans1 ^= a[i];
            else
                ans2 ^= a[i];
        }
        printf("%d %d
    ", ans1, ans2);
        return 0;
    }
    View Code

     25.

    输入一个正整数,打印出所有和为该数的正数序列

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    
    void printf_n(int l, int r){
        for(int i = l; i < r; i ++){
            printf("%d ", i);
        }
        printf("%d
    ", r);
    }
    void solve(int n){
        int l = 1, r = 2;
        if(n < 3) return;
        int mid = 1 + n >> 1;
        int sum = l + r;
        while( l < mid){
            if(sum == n)
                printf_n(l, r);
            while(l < mid && sum > n){
                sum -= l;
                l ++;
                if(sum == n)
                    printf_n(l, r);
            }
            r ++;
            sum += r;
        }
    }
    int main(){
        int n;
        scanf("%d", &n);
        solve(n);
        return 0;
    }
    View Code

     26.

    二叉搜索树不创建新的结点转换成双向链表

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    
    struct TreeNode{
        int value;
        TreeNode *left;
        TreeNode *right;
    };
    TreeNode *creatTreeNode(int m){
        TreeNode *node = new TreeNode;
        node->value = m;
        node->right = node->left = NULL;
        return node;
    }
    void DestroyTree(TreeNode *root){
        if(root != NULL){
            TreeNode *l = root->left;
            TreeNode *r = root->right;
            delete root;
            root = NULL;
            DestroyTree(l);
            DestroyTree(r);
        }
    }
    void connectTree(TreeNode *root, TreeNode *l, TreeNode *r){
        if(root != NULL){
            root->left = l;
            root->right = r;
        }
    }
    
    
    void covertToDoubleList(TreeNode **head, TreeNode **list, TreeNode  *root){
        //TreeNode *root = tt;
        root->left = *list;
        if(NULL != *list)
            (*list)->right = root;
        else
            (*head) = root;
        (*list) = root;
        printf("%d ", root->value);
    }
    void fun(TreeNode **head, TreeNode **list, TreeNode *root){
        if(NULL == root)
            return;
        if(NULL != root->left)
            fun(head, list, root->left);
        covertToDoubleList(head, list, root);
    /*
        root->left = *list;
        if(NULL != *list)
            (*list)->right = root;
        else
            (*head) = root;
        (*list) = root;
        printf("%d ", root->value);
    */
        if(NULL != root->right)
            fun(head, list, root->right);
    }
    void solve(TreeNode *root){
        TreeNode *head = new TreeNode();
        TreeNode *list = new TreeNode();
        head = list = NULL;
        //if(head == NULL)puts("adsf");
        fun(&head, &list, root);
        puts("");
        TreeNode *p = head;
        while(p != NULL){
            printf("%d ", p->value);
            p = p->right;
        }
        puts("");
    }
    int main(){
        TreeNode *node1 = creatTreeNode(10);
        TreeNode *node2 = creatTreeNode(6);
        TreeNode *node3 = creatTreeNode(14);
        TreeNode *node4 = creatTreeNode(4);
        TreeNode *node5 = creatTreeNode(8);
        TreeNode *node6 = creatTreeNode(12);
        TreeNode *node7 = creatTreeNode(16);
        connectTree(node1, node2, node3);
        connectTree(node2, node4, node5);
        connectTree(node3, node6, node7);
        solve(node1);
        //DestroyTree(node1);
        return 0;
    }
    View Code

     27.

    找出数组中次数超过一半的数字

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    
    int a[9] = {1,2,2,3,2,2,5,4,2};
    int len = 9;
    bool check(int num){
        int cnt = 0;
        for(int i = 0; i < len; i ++)
            if(a[i] == num)
                cnt ++;
        if(cnt * 2 <= len)
            return false;
        else
            return true;
    }
    void solve(){
        int res = a[0];
        int cnt = 1;
        for(int i = 1; i < len; i ++){
            if(cnt == 0){
                res = a[i];
                cnt ++;
            }else
                if(a[i] == res)
                    cnt ++;
                else cnt --;
        }
        if(check(res))
            puts("yes");
        else
            puts("no");
    }
    int main(){
        solve();
        return 0;
    }
    View Code

     28.

    给定一个整数,求从1到这整数十进制中1出现的次数

    解决方案:

    分析(转)

    简单的方法就是按照给位进行分析

    在个位出现1的个数=n/10+(个位=0,0;个位>1,1;个位=1,低0位+1);

    十位位出现1的个数=n/100*10+(十位=0,0;十位>1,10,;十位=1,低一位+1);

    百位出现1的个数=n/1000*100+(百位=0,0;百位>1,100;百位=1,低两位+1);

    等等

    算法的复杂度仅仅和位数有关

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    using namespace std;
    
    
    
    int f(int a){
        if(a == 0) return 1;
        int num = 1;
        for(int i = 1; i <= a; i ++)
            num *= 10;
        return num;
    }
    int solve(int n){
        int tmp = n;
        int len = 0;
        while(tmp){
            tmp /= 10;
            len ++;
        }
        tmp = n;
        int sum = 0;
        for(int i = 1; i <= len; i ++){
            sum += tmp / f(i) * f(i-1);
            int t = n / f(i-1) % 10;
            if(t == 1)
                sum += n % f(i-1) + 1;
            else if(t > 1)
                sum += f(i-1);
        }
        return sum;
    }
    int main(){
        int n;
        scanf("%d", &n);
        int t = solve(n);
        printf("%d
    ", t);
        return 0;
    }
    View Code

     29.

    把数组排成最小的数

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    
    
    
    int a[3] = {3,32,321};
    const int len = 3;
    
    
    int cmp(const string &s1, const string &s2){
        string ss1 = s1 + s2;
        string ss2 = s2 + s1;
        return s1 > s2;
    }
    int main(){
        char s[len+1][10];
        string ss[len];
        for(int i = 0; i < len; i ++){
            sprintf(s[i], "%d", a[i]);
            ss[i] = s[i];
        }
        sort(ss,ss + len, cmp);
        for(int i = 0; i < len; i ++)
            //printf("%s", s[i]);
            cout<<ss[i];
        puts("");
        return 0;
    }
    View Code

     30.

    寻找丑数(只包含因子为2 3 5的数)

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    
    
    
    int Min(int a, int b, int c){
        int x = a < b ? a: b;
        x = x < c ? x : c;
        return x;
    }
    int getUgly(int n){
        if(n <= 0) return 0;
        int *ugly = new int[n];
        ugly[0] = 1;
        int cnt = 1;
        int *m2 = ugly;
        int *m3 = ugly;
        int *m5 = ugly;
        while(cnt < n){
            int min = Min(*m2 * 2, *m3 * 3, *m5 * 5);
            ugly[cnt] = min;
            while(*m2 * 2 <= ugly[cnt])
                m2 ++;
            while(*m3 * 3 <= ugly[cnt])
                m3 ++;
            while(*m5 * 5 <= ugly[cnt])
                m5 ++;
            cnt ++;
        }
        int ans = ugly[n - 1];
        delete [] ugly;
        return ans;
    }
    int main(){
        int n;
        scanf("%d", &n);
        int t =    getUgly(n);
        printf("%d
    ", t);
        return 0;
    }
    View Code

     31.

    在字符串中找出第一个只出现一次的字符

    解决方案:

    先遍历一次建立hash表,然后查找就行

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    
    
    
    int main(){
        char s[333];
        scanf("%s", s);
        int hashmap[270];
        memset(hashmap, 0, sizeof hashmap);
        for(int i = 0; s[i]; i ++)
            hashmap[s[i]] ++;
        bool f = true;
        for(int i = 0; s[i]; i ++){
            if(hashmap[s[i]] == 1){
                printf("%c
    ", s[i]);
                f = false;
                break;
            }
        }
        if(f)
            puts("not found");
        return 0;
    }
    View Code

     32.

    判断一个序列是不是某二叉排序树(二叉搜索树,二元查找树)的后序遍历序列

    解决方案:

    最后一个结点必为根结点,然后根据二叉排序树的性质找到它的左右孩子,然后再递归查找

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    
    
    
    bool check(int *a, int n){
        if(a == NULL || n < 1)
            return false;
        int root = a[n-1];
        int l = 0;
        for(; l < n - 1; l ++){
            if(a[l] > root)
                break;
        }
        int r = l;
        for(; r < n - 1; r ++)
            if(a[r] < root)
                return false;
        bool left = true;
        if(l > 0)
            left = check(a, l);
        bool right = true;
        if(r < n - 1)
            right = check(a+l, n - l + 1);
        return (left && right);
    }
    int main(){
        int n;
        scanf("%d", &n);
        int *a = new int[n];
        for(int i = 0; i < n; i ++){
            scanf("%d", a + i);
        }
        bool ans = check(a, n);
        if(ans)
            puts("yes");
        else
            puts("no");
        return 0;
    }
    View Code

    33.

    约瑟夫环问题

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    
    
    
    int main(){
        int n;
        scanf("%d", &n);    
        int m;
        scanf("%d", &m);
        int last = 0;
        for(int i = 2; i <= n; i ++)
            last = (last + m) % i;
        printf("%d
    ", last);
        return 0;
    }
    View Code

     34.

    输入两个整数n和m,从数列1,2.......n中随意取几个数,使其和等于m,要求将其中所有的可能组合列出来

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    
    
    void solve(int n, int m){
        if(n < 1 || m < 1)
            return;
        if(n > m)
            n = m;
        int maxn = 1 << n;
        for(int i = 1; i < maxn; i ++){
            int sum = 0;
            for(int j = i, k = 1; j; j >>= 1, k ++)
                if(j&1)
                    sum += k;
            if(sum == m){
                for(int j = i, k = 1; j; j >>= 1, k ++)
                    if(j&1)
                        printf("%d ", k);
                puts("");
            }
        }
    }
    int main(){
        int n, m;
        scanf("%d%d", &n, &m);
        solve(n, m);
        return 0;
    }
    View Code

     35.

    将一个整数以字符串输出

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    
    
    
    
    char *int2str(int n){
        char *s = new char;
        char *p = s;
        bool f = true;
        if(n == 0){
            *p ++ = '0';
            *p ++ = '';
            return s;
        }else
            if(n < 0){
                f = false;
                n = - n;
            }
        int len = 0;
        while(n){
            *p ++ = n % 10 + 48;
            n /= 10;
            ++ len;
        }
        if(!f){
            len ++;
            *p ++ = '-';
        }
        *p ++ = '';
        //printf("%d %s
    
    ", len, s);
        for(int i = 0; i < len / 2; i ++){
            char c = s[i];
            s[i] = s[len - i - 1];
            s[len - i - 1] = c;
        }
        return s;
    }
    int main(){
        int n;
        scanf("%d", &n);
        char *s = int2str(n);
        printf("%s
    ", s);
        return 0;
    }
    View Code

     36.

    求两个字符串的最长连续公共子串并返回分别在两个子串中的位置

    #include <cstdio>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    
    
    
    char *lcs(int &index1, int &index2, char *s1, char *s2){
        int mat[111][111];
        memset(mat, 0, sizeof mat);
        int maxlen = 0;
        for(int i = 0; s1[i]; i ++){
            for(int j = 0; s2[j]; j ++){
                if(s1[i] == s2[j]){
                    if(i && j){
                        mat[i][j] = mat[i-1][j-1] + 1;
                    }
                    else mat[i][j] = 1;
                    if(mat[i][j] > maxlen){
                        maxlen = mat[i][j];
                        index1 = i;
                        index2 = j;
                    }
                }
            }
        }
        char *s = new char[maxlen+1];
        for(int i = 0; i < maxlen; i ++){
            s[i] = s1[index1 - maxlen + i + 1];
        }
        index1 = index1 - maxlen + 1;
        index2 = index2 - maxlen + 1;
        s[maxlen] = '';
        return s;
    }
    int main(){
        char s1[111], s2[111];
        while(~scanf("%s%s", s1, s2)){
            int index1, index2;
            char *s = lcs(index1, index2, s1, s2);
            printf("%s %d %d
    ", s, index1, index2);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    C语言文件
    java课程设计-彩票购买抽奖程序
    面向对象设计大作业——图书馆
    有理数类设计
    图总结
    编译器、编辑器、文件、IDE等常见概念辨析
    树、二叉树、查找算法总结
    互评:数据结构、算法及线性表总结
    c语言文件
    第二次博客园作业
  • 原文地址:https://www.cnblogs.com/louzhang/p/3322215.html
Copyright © 2020-2023  润新知