c语言算法题目求职用

1.栈的压入与压出
/*
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。n<=100000 用一个栈作辅助,顺序描述压入序列和弹出序列,如果当前位置上压入序列和弹出序列值相等,直接都向后移一个元素;比较栈顶元素和弹出序列当前值,如果相等,出栈,弹出序列后移一个元素;其余情况,将压入序列当前值压栈,压入序列后移一个元素。如果到最后,弹出序列都处理不完,说明弹出序列不合法。时间复杂度为O(n)。 */ #include <stdio.h> #include <stack> using namespace std; int qin[100005]; int qout[100005]; int main(void) { int n; int i,j; while(scanf("%d", &n) == 1) { for(i=0; i<n; ++i) scanf("%d", &qin[i]); for(i=0; i<n; ++i) scanf("%d", &qout[i]); stack<int> s; i = 0; j = 0; while(i<n || j<n) { if(i<n && j<n && qin[i]==qout[j]) { ++i; ++j; } else { if(s.empty()) { if(i<n) s.push(qin[i++]); } else if(s.top() == qout[j]) { s.pop(); ++j; } else if(i<n) { s.push(qin[i++]); } else { break; } } } if(j==n) printf("Yes\n"); else printf("No\n"); } return 0; }

2.二叉搜索书的后续遍历序列

/*
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。n<=10000。

二叉搜索树的性质之一为:根结点值大于左子树,小于右子树。设后序遍历顺序为 A B C,则有A<C<B。因此,从根结点(遍历的最后一个结点)出发,向前找到所有连续的大于根结点的值作为右子树,再往前的所有连续小于根结点的作为左子树,如果往前还有大于根结点的,则不是二叉搜索树的后序遍历结果。递归处理左子树和右子树。时间复杂度约为O(nlogn)。
*/
#include <stdio.h>

int seq[10005];
bool valid(int x, int y)
{
    if(x >= y)
    return true;
    
    int i=y-1;
    while(i>=x && seq[i]>seq[y])
    {
        --i;
    }
    int j = i;
    while(i>=x && seq[i]<seq[y])
    {
        --i;
    }
    if(i>=x)
    return false;
    
    if(!valid(x, j))
    return false;
    
    if(!valid(j+1, y-1))
    return false;
    
    return true;
}

int main(void)
{
    int n;
    while(scanf("%d", &n) == 1)
    {
        for(int i=0; i<n; ++i)
        scanf("%d", &seq[i]);
        
        if(valid(0, n-1))
        printf("Yes\n");
        else
        printf("No\n");
    }
    
    return 0;
}

3.数组中出现次数超过一半的数字

/*
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。n<=100000

将出现一半的数与其他数两两抵消,剩余的最后一个数即是答案。具体做法是每次选两个不同的数两两抵消,要么会抵消一个答案数字和一个非答案数字,要么抵消两个非答案数字,到最后剩余的一定是答案。时间复杂度为O(n)。
*/
#include <stdio.h>

int f[100005];
int main(void)
{
    int i,n;
    while(scanf("%d", &n) == 1)
    {
        int ans = 0;
        int count = 0;
        for(i=0; i<n; ++i)
        {
            scanf("%d", &f[i]);
            if(count == 0)
            {
                 ans = f[i];
                 count = 1;
            }
            else if(f[i] == ans)
            {
                ++count;
            }
            else
            {
                --count;
            }
        }
        
        count = 0;
        for(i=0; i<n; ++i)
        {
            if(f[i] == ans)
            ++count;
        }
        
        if(count > n/2)
        printf("%d\n", ans);
        else
        printf("-1\n");
    }
    
    return 0;
}

4.整数中1出现的次数

/*
求两个整数间的数,10进制各个位上1出现的总次数,0<=a,b<=1,000,000,000 

按位统计,统计每位上1出现的次数。当前位刚好是1和刚好是0需要单独考虑。
*/
#include <stdio.h>

long long CountOne(long long x)
{
    long long base = 1;
    long long ans = 0;
    long long temp;
    long long rec = 0;
    while(x)
    {
        temp = x/10;
        ans += temp * base;
        if(x%10 > 1)
        ans += base;
        else if(x%10 == 1)
        {
            ans += rec + 1;
        }
        rec += x%10 * base;
        base *= 10;
        x /= 10;
    }
    return ans;
}

int main(void)
{
    long long a,b;
    while(scanf("%lld%lld", &a, &b) == 2)
    {
        long long sa = 0, sb = 0;
        if(a>b)
        {
            a += b;
            b = a - b;
            a = a - b;
        }
        if(a>0)
        sa = CountOne(a-1);
        sb = CountOne(b);
        printf("%lld\n", sb-sa);
    }
    return 0;
}

5.数组中的逆袭对

/*
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。 

归并排序,在merge的时候统计逆序对,设需要merge的数组为A,B,A大小为n,B大小为m。如果A[i]>B[j],则逆序数将增加n-i。
*/
#include <stdio.h>

int f[100005];
int g[100005];
long long ans;
void Sort(int x, int y)
{
    if(x >= y)
    return ;
    
    int mid = (x+y)>>1;
    Sort(x, mid);
    Sort(mid+1, y);
    
    int i = x;
    int j = mid+1;
    int k = x;
    while(i<=mid || j<=y)
    {
        if(i>mid)
        {
            g[k++] = f[j++];
        }
        else if(j>y)
        {
            g[k++] = f[i++];
        }
        else if(f[i]<=f[j])
        {
            g[k++] = f[i++];
        }
        else if(f[i]>f[j])
        {
            ans += mid - i + 1;
            g[k++] = f[j++];
        }
    }
    for(k=x; k<=y; ++k)
    f[k] = g[k];
}

int main(void)
{
    int n;
    while(scanf("%d", &n) == 1)
    {
        for(int i=0; i<n; ++i)
        scanf("%d", &f[i]);
        
        ans = 0;
        Sort(0, n-1);
        printf("%lld\n", ans);
    }
    
    return 0;
}

6.和为s的两个数字

/*
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S。n<=1000000

用两个游标,一个从头开始A[i],一个从尾开始A[j],如果A[i]+A[j]<S,则i后移一格,否则j前移一格,如果相等,则记录结果。算法复杂度为O(n)。
*/
#include <stdio.h>

long long num[1000005];
int main(void)
{
    int n;
    long long m;
    while(scanf("%d%lld", &n, &m) == 2)
    {
        int i,j;
        for(i=0; i<n; ++i)
        scanf("%lld", &num[i]);
        
        i = 0;
        j = n-1;
        long long x=-1, y=-1;
        long long v;
        long long res = num[j]*num[j];
        while(i<j)
        {
            v = num[i] + num[j];
            if(v == m)
            {
                if(num[i]*num[j] <= res)
                {
                    x = num[i];
                    y = num[j];
                    res = num[i]*num[j];
                }
                ++i;
                --j;
            }
            else if(v < m)
            {
                ++i;
            }
            else
            {
                --j;
            }
        }
        printf("%lld %lld\n", x, y);
    }
    
    return 0;
}

7.猜数字游戏

/*
给定n个骰子,每个骰子点数为m,求按概率排序前3的点数和。 概率值按 4 舍 5 入要求保留 2 位小数, n(0<=n<=10),m(6<=m<=8)。 

递推,令f[i][j]表示前i个骰子,点数和为j的次数。有f[i][j] = f[i-1][j-1]+....+f[i-1][j-m]。也可直接用一维的轮换数组进行计算,即g[j] = f[j-1]+...+f[j-m], f=g。
*/
#include <stdio.h>
#include <algorithm>
#include <vector>
using namespace std;

struct T
{
    int id;
    double v;
};

bool cmp(const T &a, const T &b)
{
    if(a.v>b.v)
        return true;
    else if(a.v<b.v)
        return false;
    else
        return a.id<b.id;
}

int main(void)
{
    int n,m;
    bool first = true;
    while(scanf("%d", &n)==1 && n)
    {
        scanf("%d", &m);
        int f[85] = {0};
        int g[85] = {0};
        int i,j,k;
        for(i=1; i<=m; ++i)
        f[i] = 1;
        
        for(i=1; i<n; ++i)
        {
            for(j=0; j<=80; ++j)
            g[j] = 0;
            
            for(j=1; j<=80; ++j)
            {
                for(k=1; k<=m; ++k)
                {
                    if(j-k>0)
                    {
                        g[j] += f[j-k];
                    }
                }
            }
            
            for(j=0; j<=80; ++j)
            f[j] = g[j];
        }
        
        int sum = 0;
        vector<T> ans;
        T t;
        for(i=1; i<=80; ++i)
        {
            if(f[i] > 0)
            {
                sum += f[i];
                t.id = i;
                t.v = f[i];
                ans.push_back(t);
            }
        }
        for(i=0; i<ans.size(); ++i)
        {
            ans[i].v = ((int)(100.0*ans[i].v/sum+0.5))/100.0;
        }
        sort(ans.begin(), ans.end(), cmp);
        
        if(first)
        first = false;
        else
        printf("\n");
        
        for(i=0; i<3; i++)
        {
            printf("%d %.2lf\n", ans[i].id, ans[i].v);
        }
    }
    
    return 0;
}

 

posted on 2014-03-02 20:27  初日  阅读(344)  评论(0编辑  收藏  举报

导航