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\n", 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\n", 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\n", 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\n", 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\n", 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\n", 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", &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 ? ' ' : '\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\n", 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\n", 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\n", 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\n", 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\n", 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("\t");
}
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] = '\0';
    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("\t");
}
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] = '\0';
    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\n", 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\n", 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\n", 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\n", 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\n", 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\n", 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\n", 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\n", 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 ++ = '\0';
        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 ++ = '\0';
    //printf("%d %s\n\n", 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\n", 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] = '\0';
    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\n", s, index1, index2);
    }
    return 0;
}
View Code

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM